From 8f29b6274480bd2040c09e5446c65b468714f099 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Fri, 7 May 2021 19:17:57 -0300 Subject: [PATCH] refactor: changes per PR feedback --- app/assets/javascripts/components/Icon.tsx | 40 +++++----------- .../components/NotesContextMenu.tsx | 10 ++-- .../javascripts/components/NotesOptions.tsx | 30 ++++++------ .../components/NotesOptionsPanel.tsx | 4 +- .../ui_models/app_state/notes_state.ts | 47 +++++++++++++++++-- .../ui_models/app_state/tags_state.ts | 45 +----------------- app/assets/stylesheets/_sn.scss | 4 -- 7 files changed, 78 insertions(+), 102 deletions(-) diff --git a/app/assets/javascripts/components/Icon.tsx b/app/assets/javascripts/components/Icon.tsx index 6fb7dbeda..45a6431ff 100644 --- a/app/assets/javascripts/components/Icon.tsx +++ b/app/assets/javascripts/components/Icon.tsx @@ -11,42 +11,28 @@ import RestoreIcon from '../../icons/ic-restore.svg'; import CloseIcon from '../../icons/ic-close.svg'; import { toDirective } from './utils'; -export enum IconType { - PencilOff = 'pencil-off', - RichText = 'rich-text', - Trash = 'trash', - Pin = 'pin', - Unpin = 'unpin', - Archive = 'archive', - Unarchive = 'unarchive', - Hashtag = 'hashtag', - ChevronRight = 'chevron-right', - Restore = 'restore', - Close = 'close', -} - const ICONS = { - [IconType.PencilOff]: PencilOffIcon, - [IconType.RichText]: RichTextIcon, - [IconType.Trash]: TrashIcon, - [IconType.Pin]: PinIcon, - [IconType.Unpin]: UnpinIcon, - [IconType.Archive]: ArchiveIcon, - [IconType.Unarchive]: UnarchiveIcon, - [IconType.Hashtag]: HashtagIcon, - [IconType.ChevronRight]: ChevronRightIcon, - [IconType.Restore]: RestoreIcon, - [IconType.Close]: CloseIcon, + 'pencil-off': PencilOffIcon, + 'rich-text': RichTextIcon, + 'trash': TrashIcon, + 'pin': PinIcon, + 'unpin': UnpinIcon, + 'archive': ArchiveIcon, + 'unarchive': UnarchiveIcon, + 'hashtag': HashtagIcon, + 'chevron-right': ChevronRightIcon, + 'restore': RestoreIcon, + 'close': CloseIcon, }; type Props = { - type: IconType; + type: keyof (typeof ICONS); className: string; } export const Icon: React.FC = ({ type, className }) => { const IconComponent = ICONS[type]; - return IconComponent ? : null; + return ; }; export const IconDirective = toDirective( diff --git a/app/assets/javascripts/components/NotesContextMenu.tsx b/app/assets/javascripts/components/NotesContextMenu.tsx index f2c4936fd..3058c035f 100644 --- a/app/assets/javascripts/components/NotesContextMenu.tsx +++ b/app/assets/javascripts/components/NotesContextMenu.tsx @@ -2,7 +2,7 @@ import { AppState } from '@/ui_models/app_state'; import { toDirective, useCloseOnBlur } from './utils'; import { observer } from 'mobx-react-lite'; import { NotesOptions } from './NotesOptions'; -import { useEffect, useRef } from 'preact/hooks'; +import { useCallback, useEffect, useRef } from 'preact/hooks'; type Props = { appState: AppState; @@ -10,23 +10,23 @@ type Props = { const NotesContextMenu = observer(({ appState }: Props) => { const contextMenuRef = useRef(); - const [closeOnBlur, setLockCloseOnBlur] = useCloseOnBlur( + const [closeOnBlur] = useCloseOnBlur( contextMenuRef, (open: boolean) => appState.notes.setContextMenuOpen(open) ); - const closeOnClickOutside = (event: MouseEvent) => { + const closeOnClickOutside = useCallback((event: MouseEvent) => { if (!contextMenuRef.current?.contains(event.target as Node)) { appState.notes.setContextMenuOpen(false); } - }; + }, [appState]); useEffect(() => { document.addEventListener('click', closeOnClickOutside); return () => { document.removeEventListener('click', closeOnClickOutside); }; - }); + }, [closeOnClickOutside]); return appState.notes.contextMenuOpen ? (
void; }; -const MAX_TAGS_MENU_HEIGHT = 265; +const MAX_TAGS_MENU_HEIGHT = 320; export const NotesOptions = observer( ({ appState, closeOnBlur, onSubmenuChange }: Props) => { @@ -57,7 +57,7 @@ export const NotesOptions = observer( }} > - + Prevent editing @@ -70,7 +70,7 @@ export const NotesOptions = observer( }} > - + Show preview @@ -102,11 +102,11 @@ export const NotesOptions = observer( className={`${buttonClass} py-1.5 justify-between`} >
- + {'Add tag'}
@@ -120,7 +120,7 @@ export const NotesOptions = observer( style={{ ...tagsMenuPosition, }} - className="sn-dropdown sn-dropdown-anchor-right flex flex-col py-2 max-w-265px max-h-80 overflow-y-scroll" + className="sn-dropdown sn-dropdown-anchor-right flex flex-col py-2 max-h-80 overflow-y-scroll" > {appState.tags.tags.map((tag) => ( @@ -149,7 +149,7 @@ export const NotesOptions = observer( }} > {appState.notes.selectedNotesCount > 1 @@ -168,7 +168,7 @@ export const NotesOptions = observer( }} > {archived ? 'Unarchive' : 'Archive'} @@ -180,7 +180,7 @@ export const NotesOptions = observer( await appState.notes.setTrashSelectedNotes(!trashed); }} > - + {trashed ? 'Restore' : 'Move to Trash'} {appState.selectedTag?.isTrashTag && ( @@ -191,7 +191,7 @@ export const NotesOptions = observer( await appState.notes.deleteNotesPermanently(); }} > - + Delete Permanently )} diff --git a/app/assets/javascripts/components/NotesOptionsPanel.tsx b/app/assets/javascripts/components/NotesOptionsPanel.tsx index b9e655760..a046f7be1 100644 --- a/app/assets/javascripts/components/NotesOptionsPanel.tsx +++ b/app/assets/javascripts/components/NotesOptionsPanel.tsx @@ -23,7 +23,7 @@ export const NotesOptionsPanel = observer(({ appState }: Props) => { }); const buttonRef = useRef(); const panelRef = useRef(); - const [closeOnBlur, setLockCloseOnBlur] = useCloseOnBlur(panelRef, setOpen); + const [closeOnBlur] = useCloseOnBlur(panelRef, setOpen); const [submenuOpen, setSubmenuOpen] = useState(false); const onSubmenuChange = (open: boolean) => { @@ -70,7 +70,7 @@ export const NotesOptionsPanel = observer(({ appState }: Props) => { style={{ ...position, }} - className="sn-dropdown sn-dropdown-anchor-right flex flex-col py-2 max-w-265" + className="sn-dropdown sn-dropdown-anchor-right flex flex-col py-2" > {open && ( { - this.selectedNotes = {}; - this.contextMenuOpen = false; - }); + this.unselectNotes(); + this.contextMenuOpen = false; } } @@ -297,6 +298,42 @@ export class NotesState { this.selectedNotes = {}; } + async addTagToSelectedNotes(tag: SNTag): Promise { + const selectedNotes = Object.values( + this.application.getAppState().notes.selectedNotes + ); + await this.application.changeItem(tag.uuid, (mutator) => { + for (const note of selectedNotes) { + mutator.addItemAsRelationship(note); + } + }); + this.application.sync(); + } + + async removeTagFromSelectedNotes(tag: SNTag): Promise { + const selectedNotes = Object.values( + this.application.getAppState().notes.selectedNotes + ); + await this.application.changeItem(tag.uuid, (mutator) => { + for (const note of selectedNotes) { + mutator.removeItemAsRelationship(note); + } + }); + this.application.sync(); + } + + isTagInSelectedNotes(tag: SNTag): boolean { + const selectedNotes = Object.values( + this.application.getAppState().notes.selectedNotes + ); + return selectedNotes.every((note) => + this.application + .getAppState() + .getNoteTags(note) + .find((noteTag) => noteTag.uuid === tag.uuid) + ); + } + private get io() { return this.application.io; } diff --git a/app/assets/javascripts/ui_models/app_state/tags_state.ts b/app/assets/javascripts/ui_models/app_state/tags_state.ts index 60b2410e2..439a47e7a 100644 --- a/app/assets/javascripts/ui_models/app_state/tags_state.ts +++ b/app/assets/javascripts/ui_models/app_state/tags_state.ts @@ -1,5 +1,5 @@ import { ContentType, SNSmartTag, SNTag } from '@standardnotes/snjs'; -import { action, computed, makeObservable, observable } from 'mobx'; +import { computed, makeObservable, observable } from 'mobx'; import { WebApplication } from '../application'; export class TagsState { @@ -15,10 +15,6 @@ export class TagsState { smartTags: observable, tagsCount: computed, - - addTagToSelectedNotes: action, - removeTagFromSelectedNotes: action, - isTagInSelectedNotes: action, }); appEventListeners.push( @@ -34,45 +30,6 @@ export class TagsState { ); } - async addTagToSelectedNotes(tag: SNTag): Promise { - const selectedNotes = Object.values( - this.application.getAppState().notes.selectedNotes - ); - await this.application.changeItem(tag.uuid, (mutator) => { - for (const note of selectedNotes) { - mutator.addItemAsRelationship(note); - } - }); - this.application.sync(); - } - - async removeTagFromSelectedNotes(tag: SNTag): Promise { - const selectedNotes = Object.values( - this.application.getAppState().notes.selectedNotes - ); - await Promise.all( - selectedNotes.map( - async (note) => - await this.application.changeItem(tag.uuid, (mutator) => { - mutator.removeItemAsRelationship(note); - }) - ) - ); - this.application.sync(); - } - - isTagInSelectedNotes(tag: SNTag): boolean { - const selectedNotes = Object.values( - this.application.getAppState().notes.selectedNotes - ); - return selectedNotes.every((note) => - this.application - .getAppState() - .getNoteTags(note) - .find((noteTag) => noteTag.uuid === tag.uuid) - ); - } - get tagsCount(): number { return this.tags.length; } diff --git a/app/assets/stylesheets/_sn.scss b/app/assets/stylesheets/_sn.scss index 3c55ae8f8..e91093780 100644 --- a/app/assets/stylesheets/_sn.scss +++ b/app/assets/stylesheets/_sn.scss @@ -107,10 +107,6 @@ max-width: 15rem; } -.max-w-265px { - max-width: 265px; -} - .h-32px { height: 32px; }