From 5265a0d01076c0661520cc11815fb8490ef6f9c8 Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Wed, 23 Feb 2022 18:59:25 +0530 Subject: [PATCH 01/17] fix: tag context menu (#893) --- .../components/Tags/TagContextMenu.tsx | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/components/Tags/TagContextMenu.tsx b/app/assets/javascripts/components/Tags/TagContextMenu.tsx index 3ca82232c..51054d34e 100644 --- a/app/assets/javascripts/components/Tags/TagContextMenu.tsx +++ b/app/assets/javascripts/components/Tags/TagContextMenu.tsx @@ -5,6 +5,7 @@ import { useCallback, useEffect, useRef } from 'preact/hooks'; import { Icon } from '../Icon'; import { Menu } from '../menu/Menu'; import { MenuItem, MenuItemType } from '../menu/MenuItem'; +import { usePremiumModal } from '../Premium'; import { useCloseOnBlur } from '../utils'; type Props = { @@ -13,6 +14,7 @@ type Props = { export const TagsContextMenu: FunctionComponent = observer( ({ appState }) => { + const premiumModal = usePremiumModal(); const selectedTag = appState.tags.selected; if (!selectedTag) { @@ -39,9 +41,19 @@ export const TagsContextMenu: FunctionComponent = observer( }, [reloadContextMenuLayout]); const onClickAddSubtag = useCallback(() => { + if (!appState.features.hasFolders) { + premiumModal.activate('Folders'); + return; + } + appState.tags.setContextMenuOpen(false); appState.tags.setAddingSubtagTo(selectedTag); - }, [appState.tags, selectedTag]); + }, [ + appState.features.hasFolders, + appState.tags, + premiumModal, + selectedTag, + ]); const onClickRename = useCallback(() => { appState.tags.setContextMenuOpen(false); @@ -71,11 +83,14 @@ export const TagsContextMenu: FunctionComponent = observer( - - Add subtag +
+ + Add subtag +
+ {!appState.features.hasFolders && }
Date: Wed, 23 Feb 2022 20:51:34 +0530 Subject: [PATCH 02/17] feat: add "Listed actions" option in note context menu (#891) --- .../javascripts/components/ActionsMenu.tsx | 329 ------------------ .../components/NoteView/NoteView.tsx | 71 ---- .../NotesOptions/ListedActionsOption.tsx | 299 ++++++++++++++++ .../components/NotesOptions/NotesOptions.tsx | 7 + .../utils/calculateSubmenuStyle.tsx | 77 ++++ app/assets/stylesheets/_editor.scss | 3 +- app/assets/stylesheets/_sn.scss | 8 + 7 files changed, 392 insertions(+), 402 deletions(-) delete mode 100644 app/assets/javascripts/components/ActionsMenu.tsx create mode 100644 app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx create mode 100644 app/assets/javascripts/utils/calculateSubmenuStyle.tsx diff --git a/app/assets/javascripts/components/ActionsMenu.tsx b/app/assets/javascripts/components/ActionsMenu.tsx deleted file mode 100644 index 40393a52e..000000000 --- a/app/assets/javascripts/components/ActionsMenu.tsx +++ /dev/null @@ -1,329 +0,0 @@ -import { WebApplication } from '@/ui_models/application'; -import { - Action, - SNActionsExtension, - UuidString, - SNNote, - ListedAccount, -} from '@standardnotes/snjs'; -import { ActionResponse } from '@standardnotes/snjs'; -import { render } from 'preact'; -import { PureComponent } from './Abstract/PureComponent'; -import { MenuRow } from './MenuRow'; -import { RevisionPreviewModal } from './RevisionPreviewModal'; - -type ActionRow = Action & { - running?: boolean; - spinnerClass?: string; - subtitle?: string; -}; - -type MenuSection = { - uuid: UuidString; - name: string; - loading?: boolean; - error?: boolean; - hidden?: boolean; - deprecation?: string; - extension?: SNActionsExtension; - rows?: ActionRow[]; - listedAccount?: ListedAccount; -}; - -type State = { - menuSections: MenuSection[]; - selectedActionIdentifier?: string; -}; - -type Props = { - application: WebApplication; - note: SNNote; -}; - -export class ActionsMenu extends PureComponent { - constructor(props: Props) { - super(props, props.application); - - this.state = { - menuSections: [], - }; - - this.loadExtensions(); - } - - private async loadExtensions(): Promise { - const unresolvedListedSections = - await this.getNonresolvedListedMenuSections(); - const unresolvedGenericSections = - await this.getNonresolvedGenericMenuSections(); - this.setState( - { - menuSections: unresolvedListedSections.concat( - unresolvedGenericSections - ), - }, - () => { - this.state.menuSections.forEach((menuSection) => { - this.resolveMenuSection(menuSection); - }); - } - ); - } - - private async getNonresolvedGenericMenuSections(): Promise { - const genericExtensions = this.props.application.actionsManager - .getExtensions() - .sort((a, b) => { - return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; - }); - - return genericExtensions.map((extension) => { - const menuSection: MenuSection = { - uuid: extension.uuid, - name: extension.name, - extension: extension, - loading: true, - hidden: this.appState.actionsMenu.hiddenSections[extension.uuid], - }; - return menuSection; - }); - } - - private async getNonresolvedListedMenuSections(): Promise { - const listedAccountEntries = - await this.props.application.getListedAccounts(); - return listedAccountEntries.map((entry) => { - const menuSection: MenuSection = { - uuid: entry.authorId, - name: `Listed ${entry.authorId}`, - loading: true, - listedAccount: entry, - hidden: this.appState.actionsMenu.hiddenSections[entry.authorId], - }; - return menuSection; - }); - } - - private resolveMenuSection(menuSection: MenuSection): void { - if (menuSection.listedAccount) { - this.props.application - .getListedAccountInfo(menuSection.listedAccount, this.props.note.uuid) - .then((accountInfo) => { - if (!accountInfo) { - this.promoteMenuSection({ - ...menuSection, - loading: false, - }); - return; - } - const existingMenuSection = this.state.menuSections.find( - (item) => item.uuid === menuSection.listedAccount?.authorId - ) as MenuSection; - const resolvedMenuSection: MenuSection = { - ...existingMenuSection, - loading: false, - error: false, - name: accountInfo.display_name, - rows: accountInfo?.actions, - }; - this.promoteMenuSection(resolvedMenuSection); - }); - } else if (menuSection.extension) { - this.props.application.actionsManager - .loadExtensionInContextOfItem(menuSection.extension, this.props.note) - .then((resolvedExtension) => { - if (!resolvedExtension) { - this.promoteMenuSection({ - ...menuSection, - loading: false, - }); - return; - } - - const actions = resolvedExtension.actionsWithContextForItem( - this.props.note - ); - - const resolvedMenuSection: MenuSection = { - ...menuSection, - rows: actions, - deprecation: resolvedExtension.deprecation, - loading: false, - error: false, - }; - this.promoteMenuSection(resolvedMenuSection); - }); - } - } - - private promoteMenuSection(newItem: MenuSection): void { - const menuSections = this.state.menuSections.map((menuSection) => { - if (menuSection.uuid === newItem.uuid) { - return newItem; - } else { - return menuSection; - } - }); - this.setState({ menuSections }); - } - - private promoteAction(newAction: Action, section: MenuSection): void { - const newSection: MenuSection = { - ...section, - rows: section.rows?.map((action) => { - if (action.url === newAction.url) { - return newAction; - } else { - return action; - } - }), - }; - this.promoteMenuSection(newSection); - } - - private idForAction(action: Action) { - return `${action.label}:${action.verb}:${action.desc}`; - } - - executeAction = async (action: Action, section: MenuSection) => { - const isLegacyNoteHistoryExt = action.verb === 'nested'; - if (isLegacyNoteHistoryExt) { - const showRevisionAction = action.subactions![0]; - action = showRevisionAction; - } - - this.promoteAction( - { - ...action, - running: true, - }, - section - ); - - const response = await this.props.application.actionsManager.runAction( - action, - this.props.note - ); - - this.promoteAction( - { - ...action, - running: false, - }, - section - ); - - if (!response || response.error) { - return; - } - - this.handleActionResponse(action, response); - this.resolveMenuSection(section); - }; - - handleActionResponse(action: Action, result: ActionResponse) { - switch (action.verb) { - case 'render': { - const item = result.item; - render( - , - document.body.appendChild(document.createElement('div')) - ); - } - } - } - - public toggleSectionVisibility(menuSection: MenuSection) { - this.appState.actionsMenu.toggleSectionVisibility(menuSection.uuid); - this.promoteMenuSection({ - ...menuSection, - hidden: !menuSection.hidden, - }); - } - - renderMenuSection(section: MenuSection) { - return ( -
-
{ - this.toggleSectionVisibility(section); - $event.stopPropagation(); - }} - > -
-
{section.name}
- {section.hidden &&
} - {section.deprecation && !section.hidden && ( -
- {section.deprecation} -
- )} -
- - {section.loading &&
} -
- -
- {section.error && !section.hidden && ( - - )} - - {!section.rows?.length && !section.hidden && ( - - )} - - {!section.hidden && - !section.loading && - !section.error && - section.rows?.map((action, index) => { - return ( - { - this.executeAction(action, section); - }} - label={action.label} - disabled={action.running} - spinnerClass={action.running ? 'info' : undefined} - subtitle={action.desc} - > - {action.access_type && ( -
- {'Uses '} - {action.access_type} - {' access to this note.'} -
- )} -
- ); - })} -
-
- ); - } - - render() { - return ( -
-
- {this.state.menuSections.length == 0 && ( - - )} - {this.state.menuSections.map((extension) => - this.renderMenuSection(extension) - )} -
-
- ); - } -} diff --git a/app/assets/javascripts/components/NoteView/NoteView.tsx b/app/assets/javascripts/components/NoteView/NoteView.tsx index 2edd3bfa0..49e881e45 100644 --- a/app/assets/javascripts/components/NoteView/NoteView.tsx +++ b/app/assets/javascripts/components/NoteView/NoteView.tsx @@ -33,7 +33,6 @@ import { Icon } from '../Icon'; import { PinNoteButton } from '../PinNoteButton'; import { NotesOptionsPanel } from '../NotesOptionsPanel'; import { NoteTagsContainer } from '../NoteTagsContainer'; -import { ActionsMenu } from '../ActionsMenu'; import { ComponentView } from '../ComponentView'; import { PanelSide, PanelResizer, PanelResizeType } from '../PanelResizer'; import { ElementIds } from '@/element_ids'; @@ -107,7 +106,6 @@ type State = { noteLocked: boolean; noteStatus?: NoteStatus; saveError?: any; - showActionsMenu: boolean; showLockedIcon: boolean; showProtectedWarning: boolean; spellcheck: boolean; @@ -173,7 +171,6 @@ export class NoteView extends PureComponent { lockText: 'Note Editing Disabled', noteStatus: undefined, noteLocked: this.controller.note.locked, - showActionsMenu: false, showLockedIcon: true, showProtectedWarning: false, spellcheck: true, @@ -319,7 +316,6 @@ export class NoteView extends PureComponent { async onAppLaunch() { await super.onAppLaunch(); this.streamItems(); - this.registerComponentManagerEventObserver(); } /** @override */ @@ -505,32 +501,6 @@ export class NoteView extends PureComponent { } } - setMenuState(menu: string, state: boolean) { - this.setState({ - [menu]: state, - }); - this.closeAllMenus(menu); - } - - toggleMenu = (menu: keyof State) => { - this.setMenuState(menu, !this.state[menu]); - this.application.getAppState().notes.setContextMenuOpen(false); - }; - - closeAllMenus = (exclude?: string) => { - if (!this.state.showActionsMenu) { - return; - } - const allMenus = ['showActionsMenu']; - const menuState: any = {}; - for (const candidate of allMenus) { - if (candidate !== exclude) { - menuState[candidate] = false; - } - } - this.setState(menuState); - }; - hasAvailableExtensions() { return ( this.application.actionsManager.extensionsInContextOfItem(this.note) @@ -646,10 +616,6 @@ export class NoteView extends PureComponent { document.getElementById(ElementIds.NoteTitleEditor)?.focus(); } - clickedTextArea = () => { - this.closeAllMenus(); - }; - onContentFocus = () => { this.application .getAppState() @@ -772,18 +738,6 @@ export class NoteView extends PureComponent { /** @components */ - registerComponentManagerEventObserver() { - this.removeComponentManagerObserver = - this.application.componentManager.addEventObserver((eventName, data) => { - if (eventName === ComponentManagerEvent.ViewerDidFocus) { - const viewer = data?.componentViewer; - if (viewer?.component.isEditor) { - this.closeAllMenus(); - } - } - }); - } - async reloadStackComponents() { const stackComponents = sortAlphabetically( this.application.componentManager @@ -1103,30 +1057,6 @@ export class NoteView extends PureComponent {
)} - {this.note && ( -
-
-
-
this.toggleMenu('showActionsMenu')} - > -
Actions
- {this.state.showActionsMenu && ( - - )} -
-
-
-
- )} - {!this.note.errorDecrypting && (
{ onChange={this.onTextAreaChange} value={this.state.editorText} readonly={this.state.noteLocked} - onClick={this.clickedTextArea} onFocus={this.onContentFocus} spellcheck={this.state.spellcheck} ref={(ref) => this.onSystemEditorLoad(ref)} diff --git a/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx b/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx new file mode 100644 index 000000000..52e8615d4 --- /dev/null +++ b/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx @@ -0,0 +1,299 @@ +import { WebApplication } from '@/ui_models/application'; +import { + calculateSubmenuStyle, + SubmenuStyle, +} from '@/utils/calculateSubmenuStyle'; +import { + Disclosure, + DisclosureButton, + DisclosurePanel, +} from '@reach/disclosure'; +import { Action, ListedAccount, SNNote } from '@standardnotes/snjs'; +import { Fragment, FunctionComponent } from 'preact'; +import { useCallback, useEffect, useRef, useState } from 'preact/hooks'; +import { Icon } from '../Icon'; + +type Props = { + application: WebApplication; + note: SNNote; + closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void; +}; + +type ListedMenuGroup = { + name: string; + account: ListedAccount; + actions: Action[]; +}; + +type ListedMenuItemProps = { + action: Action; + note: SNNote; + group: ListedMenuGroup; + application: WebApplication; + reloadMenuGroup: (group: ListedMenuGroup) => Promise; +}; + +const ListedMenuItem: FunctionComponent = ({ + action, + note, + application, + group, + reloadMenuGroup, +}) => { + const [isRunning, setIsRunning] = useState(false); + + const handleClick = async () => { + if (isRunning) { + return; + } + + setIsRunning(true); + + await application.actionsManager.runAction(action, note); + + setIsRunning(false); + + reloadMenuGroup(group); + }; + + return ( + + ); +}; + +type ListedActionsMenuProps = { + application: WebApplication; + note: SNNote; + recalculateMenuStyle: () => void; +}; + +const ListedActionsMenu: FunctionComponent = ({ + application, + note, + recalculateMenuStyle, +}) => { + const [menuGroups, setMenuGroups] = useState([]); + const [isFetchingAccounts, setIsFetchingAccounts] = useState(true); + + const reloadMenuGroup = async (group: ListedMenuGroup) => { + const updatedAccountInfo = await application.getListedAccountInfo( + group.account, + note.uuid + ); + + if (!updatedAccountInfo) { + return; + } + + const updatedGroup: ListedMenuGroup = { + name: updatedAccountInfo.display_name, + account: group.account, + actions: updatedAccountInfo.actions, + }; + + const updatedGroups = menuGroups.map((group) => { + if (updatedGroup.account.authorId === group.account.authorId) { + return updatedGroup; + } else { + return group; + } + }); + + setMenuGroups(updatedGroups); + }; + + useEffect(() => { + const fetchListedAccounts = async () => { + if (!application.hasAccount()) { + setIsFetchingAccounts(false); + return; + } + + try { + const listedAccountEntries = await application.getListedAccounts(); + + if (!listedAccountEntries.length) { + throw new Error('No Listed accounts found'); + } + + const menuGroups: ListedMenuGroup[] = []; + + await Promise.all( + listedAccountEntries.map(async (account) => { + const accountInfo = await application.getListedAccountInfo( + account, + note.uuid + ); + + if (accountInfo) { + menuGroups.push({ + name: accountInfo.display_name, + account, + actions: accountInfo.actions, + }); + } else { + menuGroups.push({ + name: account.authorId, + account, + actions: [], + }); + } + }) + ); + + setMenuGroups(menuGroups); + } catch (err) { + console.error(err); + } finally { + setIsFetchingAccounts(false); + setTimeout(() => { + recalculateMenuStyle(); + }); + } + }; + + fetchListedAccounts(); + }, [application, note.uuid, recalculateMenuStyle]); + + return ( + <> + {isFetchingAccounts && ( +
+
+
+ )} + {!isFetchingAccounts && menuGroups.length ? ( + <> + {menuGroups.map((group, index) => ( + +
+ {group.name} +
+ {group.actions.length ? ( + group.actions.map((action) => ( + + )) + ) : ( +
+ No actions available +
+ )} +
+ ))} + + ) : null} + {!isFetchingAccounts && !menuGroups.length ? ( +
+
+ No Listed accounts found +
+
+ ) : null} + + ); +}; + +export const ListedActionsOption: FunctionComponent = ({ + application, + note, + closeOnBlur, +}) => { + const menuRef = useRef(null); + const menuButtonRef = useRef(null); + + const [isMenuOpen, setIsMenuOpen] = useState(false); + const [menuStyle, setMenuStyle] = useState({ + right: 0, + bottom: 0, + maxHeight: 'auto', + }); + + const toggleListedMenu = () => { + if (!isMenuOpen) { + const menuPosition = calculateSubmenuStyle(menuButtonRef.current); + if (menuPosition) { + setMenuStyle(menuPosition); + } + } + + setIsMenuOpen(!isMenuOpen); + }; + + const recalculateMenuStyle = useCallback(() => { + const newMenuPosition = calculateSubmenuStyle( + menuButtonRef.current, + menuRef.current + ); + + if (newMenuPosition) { + setMenuStyle(newMenuPosition); + } + }, []); + + useEffect(() => { + if (isMenuOpen) { + setTimeout(() => { + recalculateMenuStyle(); + }); + } + }, [isMenuOpen, recalculateMenuStyle]); + + return ( + + +
+ + Listed actions +
+ +
+ + {isMenuOpen && ( + + )} + +
+ ); +}; diff --git a/app/assets/javascripts/components/NotesOptions/NotesOptions.tsx b/app/assets/javascripts/components/NotesOptions/NotesOptions.tsx index 323b12746..8a00573b2 100644 --- a/app/assets/javascripts/components/NotesOptions/NotesOptions.tsx +++ b/app/assets/javascripts/components/NotesOptions/NotesOptions.tsx @@ -18,6 +18,7 @@ import { MAX_MENU_SIZE_MULTIPLIER, BYTES_IN_ONE_MEGABYTE, } from '@/constants'; +import { ListedActionsOption } from './ListedActionsOption'; export type NotesOptionsProps = { application: WebApplication; @@ -602,6 +603,12 @@ export const NotesOptions = observer( )} {notes.length === 1 ? ( <> +
+
diff --git a/app/assets/javascripts/utils/calculateSubmenuStyle.tsx b/app/assets/javascripts/utils/calculateSubmenuStyle.tsx new file mode 100644 index 000000000..f6791f2a4 --- /dev/null +++ b/app/assets/javascripts/utils/calculateSubmenuStyle.tsx @@ -0,0 +1,77 @@ +import { + MAX_MENU_SIZE_MULTIPLIER, + MENU_MARGIN_FROM_APP_BORDER, +} from '@/constants'; + +export type SubmenuStyle = { + top?: number | 'auto'; + right?: number | 'auto'; + bottom: number | 'auto'; + left?: number | 'auto'; + visibility?: 'hidden' | 'visible'; + maxHeight: number | 'auto'; +}; + +export const calculateSubmenuStyle = ( + button: HTMLButtonElement | null, + menu?: HTMLDivElement | null +): SubmenuStyle | undefined => { + const defaultFontSize = window.getComputedStyle( + document.documentElement + ).fontSize; + const maxChangeEditorMenuSize = + parseFloat(defaultFontSize) * MAX_MENU_SIZE_MULTIPLIER; + const { clientWidth, clientHeight } = document.documentElement; + const buttonRect = button?.getBoundingClientRect(); + const buttonParentRect = button?.parentElement?.getBoundingClientRect(); + const menuBoundingRect = menu?.getBoundingClientRect(); + const footerElementRect = document + .getElementById('footer-bar') + ?.getBoundingClientRect(); + const footerHeightInPx = footerElementRect?.height ?? 0; + + let position: SubmenuStyle = { + bottom: 'auto', + maxHeight: 'auto', + }; + + if (buttonRect && buttonParentRect) { + let positionBottom = + clientHeight - buttonRect.bottom - buttonRect.height / 2; + + if (positionBottom < footerHeightInPx) { + positionBottom = footerHeightInPx + MENU_MARGIN_FROM_APP_BORDER; + } + + position = { + bottom: positionBottom, + visibility: 'hidden', + maxHeight: 'auto', + }; + + if (buttonRect.right + maxChangeEditorMenuSize > clientWidth) { + position.right = clientWidth - buttonRect.left; + } else { + position.left = buttonRect.right; + } + } + + if (menuBoundingRect?.height && buttonRect && position.bottom !== 'auto') { + position.visibility = 'visible'; + + if (menuBoundingRect.y < MENU_MARGIN_FROM_APP_BORDER) { + position.bottom = + position.bottom + menuBoundingRect.y - MENU_MARGIN_FROM_APP_BORDER * 2; + } + + if (footerElementRect && menuBoundingRect.height > footerElementRect.y) { + position.bottom = footerElementRect.height + MENU_MARGIN_FROM_APP_BORDER; + position.maxHeight = + clientHeight - + footerElementRect.height - + MENU_MARGIN_FROM_APP_BORDER * 2; + } + } + + return position; +}; diff --git a/app/assets/stylesheets/_editor.scss b/app/assets/stylesheets/_editor.scss index 61629478a..28ca04fe8 100644 --- a/app/assets/stylesheets/_editor.scss +++ b/app/assets/stylesheets/_editor.scss @@ -34,7 +34,7 @@ $heading-height: 75px; padding-bottom: 10px; padding-right: 14px; - border-bottom: none; + border-bottom: 1px solid var(--sn-stylekit-border-color); z-index: $z-index-editor-title-bar; height: auto; @@ -118,7 +118,6 @@ $heading-height: 75px; border: none; outline: none; padding: 15px; - padding-top: 11px; font-size: var(--sn-stylekit-font-size-editor); resize: none; } diff --git a/app/assets/stylesheets/_sn.scss b/app/assets/stylesheets/_sn.scss index 10b7171b4..29094ef70 100644 --- a/app/assets/stylesheets/_sn.scss +++ b/app/assets/stylesheets/_sn.scss @@ -296,6 +296,10 @@ margin-top: 0; } +.mt-0\.5 { + margin-top: 0.125rem; +} + .mt-2\.5 { margin-top: 0.625rem; } @@ -435,6 +439,10 @@ min-height: 1.5rem; } +.min-h-16 { + min-height: 4rem; +} + .max-h-5 { max-height: 1.25rem; } From 5df3e596045deeaeda51e996a74ef5a33d06ba54 Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Wed, 23 Feb 2022 20:55:26 +0530 Subject: [PATCH 03/17] fix: render change editor menu only if it is open (#894) --- .../components/ChangeEditorButton.tsx | 24 ++++++----- .../NotesOptions/ChangeEditorOption.tsx | 26 ++++++------ .../changeEditor/ChangeEditorMenu.tsx | 40 +++---------------- .../changeEditor/createEditorMenuGroups.ts | 14 +++++-- 4 files changed, 44 insertions(+), 60 deletions(-) diff --git a/app/assets/javascripts/components/ChangeEditorButton.tsx b/app/assets/javascripts/components/ChangeEditorButton.tsx index f2481f554..715dd94d7 100644 --- a/app/assets/javascripts/components/ChangeEditorButton.tsx +++ b/app/assets/javascripts/components/ChangeEditorButton.tsx @@ -49,8 +49,8 @@ export const ChangeEditorButton: FunctionComponent = observer( const [currentEditor, setCurrentEditor] = useState(); useEffect(() => { - setEditorMenuGroups(createEditorMenuGroups(editors)); - }, [editors]); + setEditorMenuGroups(createEditorMenuGroups(application, editors)); + }, [application, editors]); useEffect(() => { if (note) { @@ -121,15 +121,17 @@ export const ChangeEditorButton: FunctionComponent = observer( className="sn-dropdown sn-dropdown--animated min-w-68 max-h-120 max-w-xs flex flex-col overflow-y-auto fixed" onBlur={closeOnBlur} > - + {open && ( + + )}
diff --git a/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx b/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx index 58074efeb..3abf7989e 100644 --- a/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx +++ b/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx @@ -39,7 +39,7 @@ type AccordionMenuGroup = { export type EditorMenuItem = { name: string; component?: SNComponent; - isPremiumFeature?: boolean; + isEntitled: boolean; }; export type EditorMenuGroup = AccordionMenuGroup; @@ -162,8 +162,8 @@ export const ChangeEditorOption: FunctionComponent = ({ ); useEffect(() => { - setEditorMenuGroups(createEditorMenuGroups(editors)); - }, [editors]); + setEditorMenuGroups(createEditorMenuGroups(application, editors)); + }, [application, editors]); useEffect(() => { setSelectedEditor(application.componentManager.editorForNote(note)); @@ -248,15 +248,17 @@ export const ChangeEditorOption: FunctionComponent = ({ }} className="sn-dropdown flex flex-col max-h-120 min-w-68 fixed overflow-y-auto" > - + {changeEditorMenuOpen && ( + + )} ); diff --git a/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx b/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx index 54d0dc429..ac4a0631d 100644 --- a/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx +++ b/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx @@ -11,7 +11,6 @@ import { STRING_EDIT_LOCKED_ATTEMPT } from '@/strings'; import { WebApplication } from '@/ui_models/application'; import { ComponentArea, - FeatureStatus, ItemMutator, NoteMutator, PrefKey, @@ -48,28 +47,6 @@ export const ChangeEditorMenu: FunctionComponent = ({ }) => { const premiumModal = usePremiumModal(); - const isEntitledToEditor = useCallback( - (item: EditorMenuItem) => { - const isPlainEditor = !item.component; - - if (item.isPremiumFeature) { - return false; - } - - if (isPlainEditor) { - return true; - } - - if (item.component) { - return ( - application.getFeatureStatus(item.component.identifier) === - FeatureStatus.Entitled - ); - } - }, - [application] - ); - const isSelectedEditor = useCallback( (item: EditorMenuItem) => { if (currentEditor) { @@ -163,6 +140,11 @@ export const ChangeEditorMenu: FunctionComponent = ({ }; const selectEditor = async (itemToBeSelected: EditorMenuItem) => { + if (!itemToBeSelected.isEntitled) { + premiumModal.activate(itemToBeSelected.name); + return; + } + const areBothEditorsPlain = !currentEditor && !itemToBeSelected.component; if (areBothEditorsPlain) { @@ -184,14 +166,6 @@ export const ChangeEditorMenu: FunctionComponent = ({ } } - if ( - itemToBeSelected.isPremiumFeature || - !isEntitledToEditor(itemToBeSelected) - ) { - premiumModal.activate(itemToBeSelected.name); - shouldSelectEditor = false; - } - if (shouldSelectEditor) { selectComponent(itemToBeSelected.component ?? null, note); } @@ -238,9 +212,7 @@ export const ChangeEditorMenu: FunctionComponent = ({ >
{item.name} - {(item.isPremiumFeature || !isEntitledToEditor(item)) && ( - - )} + {!item.isEntitled && }
); diff --git a/app/assets/javascripts/components/NotesOptions/changeEditor/createEditorMenuGroups.ts b/app/assets/javascripts/components/NotesOptions/changeEditor/createEditorMenuGroups.ts index f73ead3a1..2a9b16907 100644 --- a/app/assets/javascripts/components/NotesOptions/changeEditor/createEditorMenuGroups.ts +++ b/app/assets/javascripts/components/NotesOptions/changeEditor/createEditorMenuGroups.ts @@ -1,10 +1,11 @@ +import { WebApplication } from '@/ui_models/application'; import { ComponentArea, FeatureDescription, GetFeatures, NoteType, } from '@standardnotes/features'; -import { ContentType, SNComponent } from '@standardnotes/snjs'; +import { ContentType, FeatureStatus, SNComponent } from '@standardnotes/snjs'; import { EditorMenuItem, EditorMenuGroup } from '../ChangeEditorOption'; export const PLAIN_EDITOR_NAME = 'Plain Editor'; @@ -31,11 +32,15 @@ const getEditorGroup = ( return 'others'; }; -export const createEditorMenuGroups = (editors: SNComponent[]) => { +export const createEditorMenuGroups = ( + application: WebApplication, + editors: SNComponent[] +) => { const editorItems: Record = { plain: [ { name: PLAIN_EDITOR_NAME, + isEntitled: true, }, ], 'rich-text': [], @@ -61,7 +66,7 @@ export const createEditorMenuGroups = (editors: SNComponent[]) => { ) { editorItems[getEditorGroup(editorFeature)].push({ name: editorFeature.name as string, - isPremiumFeature: true, + isEntitled: false, }); } }); @@ -70,6 +75,9 @@ export const createEditorMenuGroups = (editors: SNComponent[]) => { const editorItem: EditorMenuItem = { name: editor.name, component: editor, + isEntitled: + application.getFeatureStatus(editor.identifier) === + FeatureStatus.Entitled, }; editorItems[getEditorGroup(editor.package_info)].push(editorItem); From 7abad65a510f76a33587ba93067c712954ed55ae Mon Sep 17 00:00:00 2001 From: Mo Date: Wed, 23 Feb 2022 11:27:03 -0600 Subject: [PATCH 04/17] fix: saving status while fully offline --- app/assets/stylesheets/_editor.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/_editor.scss b/app/assets/stylesheets/_editor.scss index 28ca04fe8..5548a570e 100644 --- a/app/assets/stylesheets/_editor.scss +++ b/app/assets/stylesheets/_editor.scss @@ -66,8 +66,8 @@ $heading-height: 75px; #save-status-container { position: relative; - min-width: 15ch; - max-width: 15ch; + min-width: 16ch; + max-width: 16ch; overflow: visible; margin-right: 20px; } From 3e14a77d62fc390bb87c6164770c2ee2c2639d4c Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Wed, 23 Feb 2022 23:06:37 +0530 Subject: [PATCH 05/17] feat: add icon to listed group header (#895) --- .../components/NotesOptions/ListedActionsOption.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx b/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx index 52e8615d4..a3eb8caeb 100644 --- a/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx +++ b/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx @@ -183,11 +183,11 @@ const ListedActionsMenu: FunctionComponent = ({ {menuGroups.map((group, index) => (
- {group.name} + {group.name}
{group.actions.length ? ( group.actions.map((action) => ( From f9fafec11a9e2f32b25b144d220dd79e21315c34 Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Thu, 24 Feb 2022 19:12:58 +0530 Subject: [PATCH 06/17] feat: make listed menu sorting consistent (#896) --- .../components/NotesOptions/ListedActionsOption.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx b/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx index a3eb8caeb..044939f46 100644 --- a/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx +++ b/app/assets/javascripts/components/NotesOptions/ListedActionsOption.tsx @@ -157,7 +157,14 @@ const ListedActionsMenu: FunctionComponent = ({ }) ); - setMenuGroups(menuGroups); + setMenuGroups( + menuGroups.sort((a, b) => { + return a.name.toString().toLowerCase() < + b.name.toString().toLowerCase() + ? -1 + : 1; + }) + ); } catch (err) { console.error(err); } finally { From 7fe0873bbb570e2557a505175d9a3cb3dcdfb24a Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Thu, 24 Feb 2022 21:28:39 +0530 Subject: [PATCH 07/17] feat: redirect subscribers to dashboard instead of plans page (#897) --- .../components/ApplicationView.tsx | 5 +++- .../components/Premium/usePremiumModal.tsx | 24 +++++++++++++------ .../components/PremiumFeaturesModal.tsx | 16 +++++++++---- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/app/assets/javascripts/components/ApplicationView.tsx b/app/assets/javascripts/components/ApplicationView.tsx index 36b95f40e..7ba447673 100644 --- a/app/assets/javascripts/components/ApplicationView.tsx +++ b/app/assets/javascripts/components/ApplicationView.tsx @@ -207,7 +207,10 @@ export class ApplicationView extends PureComponent { const renderAppContents = !this.state.needsUnlock && this.state.launched; return ( - +
{renderAppContents && (
{ }; interface Props { - state: FeaturesState; + application: WebApplication; + appState: AppState; } export const PremiumModalProvider: FunctionalComponent = observer( - ({ state, children }) => { - const featureName = state._premiumAlertFeatureName; - const activate = state.showPremiumAlert; - const close = state.closePremiumAlert; + ({ application, appState, children }) => { + const featureName = appState.features._premiumAlertFeatureName; + const activate = appState.features.showPremiumAlert; + const close = appState.features.closePremiumAlert; const showModal = !!featureName; + const hasSubscription = Boolean( + appState.subscription.userSubscription && + !appState.subscription.isUserSubscriptionExpired && + !appState.subscription.isUserSubscriptionCanceled + ); + return ( <> {showModal && ( )} diff --git a/app/assets/javascripts/components/PremiumFeaturesModal.tsx b/app/assets/javascripts/components/PremiumFeaturesModal.tsx index e61e8eab1..a1601ea8c 100644 --- a/app/assets/javascripts/components/PremiumFeaturesModal.tsx +++ b/app/assets/javascripts/components/PremiumFeaturesModal.tsx @@ -7,22 +7,30 @@ import { FunctionalComponent } from 'preact'; import { Icon } from './Icon'; import { PremiumIllustration } from '@standardnotes/stylekit'; import { useRef } from 'preact/hooks'; +import { WebApplication } from '@/ui_models/application'; +import { openSubscriptionDashboard } from '@/hooks/manageSubscription'; type Props = { + application: WebApplication; featureName: string; + hasSubscription: boolean; onClose: () => void; showModal: boolean; }; export const PremiumFeaturesModal: FunctionalComponent = ({ + application, featureName, + hasSubscription, onClose, showModal, }) => { const plansButtonRef = useRef(null); - const onClickPlans = () => { - if (window._plans_url) { + const handleClick = () => { + if (hasSubscription) { + openSubscriptionDashboard(application); + } else if (window._plans_url) { window.location.assign(window._plans_url); } }; @@ -61,11 +69,11 @@ export const PremiumFeaturesModal: FunctionalComponent = ({
From c3d849d20415fa48f5f24c67508b274d29642402 Mon Sep 17 00:00:00 2001 From: Mo Date: Thu, 24 Feb 2022 12:57:32 -0600 Subject: [PATCH 08/17] chore: ugprade snjs deps (#898) --- .env.sample | 9 +- app/assets/javascripts/app.tsx | 38 ++--- .../components/AccountMenu/SignIn.tsx | 6 +- .../components/PremiumFeaturesModal.tsx | 4 +- .../RevisionContentLocked.tsx | 4 +- .../javascripts/hooks/manageSubscription.ts | 4 +- .../account/subscription/NoSubscription.tsx | 31 ++-- .../purchaseFlow/PurchaseFlowWrapper.tsx | 4 +- .../javascripts/services/errorReporting.ts | 4 +- app/assets/javascripts/startApplication.ts | 5 +- .../ui_models/app_state/account_menu_state.ts | 6 +- .../ui_models/app_state/app_state.ts | 2 +- .../ui_models/app_state/features_state.ts | 2 +- .../javascripts/ui_models/application.ts | 25 +-- .../ui_models/application_group.ts | 2 + app/views/application/app.html.erb | 15 +- index.html | 28 ++-- package.json | 10 +- yarn.lock | 146 ++++++++---------- 19 files changed, 163 insertions(+), 182 deletions(-) diff --git a/.env.sample b/.env.sample index 195dd62c9..42ed60a38 100644 --- a/.env.sample +++ b/.env.sample @@ -2,21 +2,22 @@ RAILS_ENV=development PORT=3001 WEB_CONCURRENCY=0 RAILS_LOG_TO_STDOUT=true + # Log Level options: "INFO" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "FATAL" RAILS_LOG_LEVEL=INFO + RAILS_SERVE_STATIC_FILES=true SECRET_KEY_BASE=test +BUGSNAG_API_KEY= + APP_HOST=http://localhost:3001 PURCHASE_URL=https://standardnotes.com/purchase PLANS_URL=https://standardnotes.com/plans DASHBOARD_URL=http://standardnotes.com/dashboard - DEFAULT_SYNC_SERVER=http://localhost:3000 +WEBSOCKET_URL=wss://sockets-dev.standardnotes.com -# Development options -DEV_DEFAULT_SYNC_SERVER=https://api.standardnotes.com ENABLE_UNFINISHED_FEATURES=false -DEV_WEBSOCKET_URL=wss://sockets-dev.standardnotes.com # NewRelic (Optional) NEW_RELIC_ENABLED=false diff --git a/app/assets/javascripts/app.tsx b/app/assets/javascripts/app.tsx index d83d12c0e..07beabdc2 100644 --- a/app/assets/javascripts/app.tsx +++ b/app/assets/javascripts/app.tsx @@ -2,25 +2,18 @@ declare global { interface Window { - // eslint-disable-next-line camelcase - _bugsnag_api_key?: string; - // eslint-disable-next-line camelcase - _purchase_url?: string; - // eslint-disable-next-line camelcase - _plans_url?: string; - // eslint-disable-next-line camelcase - _dashboard_url?: string; - // eslint-disable-next-line camelcase - _default_sync_server: string; - // eslint-disable-next-line camelcase - _enable_unfinished_features: boolean; - // eslint-disable-next-line camelcase - _websocket_url: string; + bugsnagApiKey?: string; + dashboardUrl?: string; + defaultFilesHost: string; + defaultSyncServer: string; + devAccountEmail?: string; + devAccountPassword?: string; + devAccountServer?: string; + enabledUnfinishedFeatures: boolean; + plansUrl?: string; + purchaseUrl?: string; startApplication?: StartApplication; - - _devAccountEmail?: string; - _devAccountPassword?: string; - _devAccountServer?: string; + websocketUrl: string; } } @@ -37,6 +30,7 @@ import { isDev } from './utils'; const startApplication: StartApplication = async function startApplication( defaultSyncServerHost: string, + defaultFilesHostHost: string, bridge: Bridge, enableUnfinishedFeatures: boolean, webSocketUrl: string @@ -46,6 +40,7 @@ const startApplication: StartApplication = async function startApplication( const mainApplicationGroup = new ApplicationGroup( defaultSyncServerHost, + defaultFilesHostHost, bridge, enableUnfinishedFeatures ? Runtime.Dev : Runtime.Prod, webSocketUrl @@ -79,10 +74,11 @@ const startApplication: StartApplication = async function startApplication( if (IsWebPlatform) { startApplication( - window._default_sync_server, + window.defaultSyncServer, + window.defaultFilesHost, new BrowserBridge(WebAppVersion), - window._enable_unfinished_features, - window._websocket_url + window.enabledUnfinishedFeatures, + window.websocketUrl ); } else { window.startApplication = startApplication; diff --git a/app/assets/javascripts/components/AccountMenu/SignIn.tsx b/app/assets/javascripts/components/AccountMenu/SignIn.tsx index 6c0469840..bc949f3ae 100644 --- a/app/assets/javascripts/components/AccountMenu/SignIn.tsx +++ b/app/assets/javascripts/components/AccountMenu/SignIn.tsx @@ -37,9 +37,9 @@ export const SignInPane: FunctionComponent = observer( if (emailInputRef?.current) { emailInputRef.current?.focus(); } - if (isDev && window._devAccountEmail) { - setEmail(window._devAccountEmail); - setPassword(window._devAccountPassword as string); + if (isDev && window.devAccountEmail) { + setEmail(window.devAccountEmail); + setPassword(window.devAccountPassword as string); } }, []); diff --git a/app/assets/javascripts/components/PremiumFeaturesModal.tsx b/app/assets/javascripts/components/PremiumFeaturesModal.tsx index a1601ea8c..c261e8231 100644 --- a/app/assets/javascripts/components/PremiumFeaturesModal.tsx +++ b/app/assets/javascripts/components/PremiumFeaturesModal.tsx @@ -30,8 +30,8 @@ export const PremiumFeaturesModal: FunctionalComponent = ({ const handleClick = () => { if (hasSubscription) { openSubscriptionDashboard(application); - } else if (window._plans_url) { - window.location.assign(window._plans_url); + } else if (window.plansUrl) { + window.location.assign(window.plansUrl); } }; diff --git a/app/assets/javascripts/components/RevisionHistoryModal/RevisionContentLocked.tsx b/app/assets/javascripts/components/RevisionHistoryModal/RevisionContentLocked.tsx index 33fc75c5c..3f73c3f23 100644 --- a/app/assets/javascripts/components/RevisionHistoryModal/RevisionContentLocked.tsx +++ b/app/assets/javascripts/components/RevisionHistoryModal/RevisionContentLocked.tsx @@ -49,8 +49,8 @@ export const RevisionContentLocked: FunctionComponent<{ type="primary" label="Discover plans" onClick={() => { - if (window._plans_url) { - window.location.assign(window._plans_url); + if (window.plansUrl) { + window.location.assign(window.plansUrl); } }} /> diff --git a/app/assets/javascripts/hooks/manageSubscription.ts b/app/assets/javascripts/hooks/manageSubscription.ts index 5cf561035..8af7197a5 100644 --- a/app/assets/javascripts/hooks/manageSubscription.ts +++ b/app/assets/javascripts/hooks/manageSubscription.ts @@ -5,8 +5,6 @@ export function openSubscriptionDashboard(application: SNApplication): void { if (!token) { return; } - window.open( - `${window._dashboard_url}?subscription_token=${token}` - ); + window.open(`${window.dashboardUrl}?subscription_token=${token}`); }); } diff --git a/app/assets/javascripts/preferences/panes/account/subscription/NoSubscription.tsx b/app/assets/javascripts/preferences/panes/account/subscription/NoSubscription.tsx index b2196a42f..9c2baa668 100644 --- a/app/assets/javascripts/preferences/panes/account/subscription/NoSubscription.tsx +++ b/app/assets/javascripts/preferences/panes/account/subscription/NoSubscription.tsx @@ -1,21 +1,24 @@ -import { FunctionalComponent } from "preact"; +import { FunctionalComponent } from 'preact'; import { LinkButton, Text } from '@/preferences/components'; import { Button } from '@/components/Button'; -import { WebApplication } from "@/ui_models/application"; -import { useState } from "preact/hooks"; -import { loadPurchaseFlowUrl } from "@/purchaseFlow/PurchaseFlowWrapper"; +import { WebApplication } from '@/ui_models/application'; +import { useState } from 'preact/hooks'; +import { loadPurchaseFlowUrl } from '@/purchaseFlow/PurchaseFlowWrapper'; export const NoSubscription: FunctionalComponent<{ application: WebApplication; }> = ({ application }) => { const [isLoadingPurchaseFlow, setIsLoadingPurchaseFlow] = useState(false); - const [purchaseFlowError, setPurchaseFlowError] = useState(undefined); + const [purchaseFlowError, setPurchaseFlowError] = useState< + string | undefined + >(undefined); const onPurchaseClick = async () => { - const errorMessage = 'There was an error when attempting to redirect you to the subscription page.'; + const errorMessage = + 'There was an error when attempting to redirect you to the subscription page.'; setIsLoadingPurchaseFlow(true); try { - if (!await loadPurchaseFlowUrl(application)) { + if (!(await loadPurchaseFlowUrl(application))) { setPurchaseFlowError(errorMessage); } } catch (e) { @@ -29,29 +32,25 @@ export const NoSubscription: FunctionalComponent<{ <> You don't have a Standard Notes subscription yet. {isLoadingPurchaseFlow && ( - - Redirecting you to the subscription page... - + Redirecting you to the subscription page... )} {purchaseFlowError && ( - - {purchaseFlowError} - + {purchaseFlowError} )}
- {application.hasAccount() && + {application.hasAccount() && (
); diff --git a/app/assets/javascripts/purchaseFlow/PurchaseFlowWrapper.tsx b/app/assets/javascripts/purchaseFlow/PurchaseFlowWrapper.tsx index d3fb5f302..3e77e77e5 100644 --- a/app/assets/javascripts/purchaseFlow/PurchaseFlowWrapper.tsx +++ b/app/assets/javascripts/purchaseFlow/PurchaseFlowWrapper.tsx @@ -16,11 +16,11 @@ export const getPurchaseFlowUrl = async ( const currentUrl = window.location.origin; const successUrl = isDesktopApplication() ? `standardnotes://` : currentUrl; if (application.noAccount()) { - return `${window._purchase_url}/offline?&success_url=${successUrl}`; + return `${window.purchaseUrl}/offline?&success_url=${successUrl}`; } const token = await application.getNewSubscriptionToken(); if (token) { - return `${window._purchase_url}?subscription_token=${token}&success_url=${successUrl}`; + return `${window.purchaseUrl}?subscription_token=${token}&success_url=${successUrl}`; } return undefined; }; diff --git a/app/assets/javascripts/services/errorReporting.ts b/app/assets/javascripts/services/errorReporting.ts index e265d2e20..577769740 100644 --- a/app/assets/javascripts/services/errorReporting.ts +++ b/app/assets/javascripts/services/errorReporting.ts @@ -25,7 +25,7 @@ export function startErrorReporting(): void { */ isNullOrUndefined(disableErrorReporting) || disableErrorReporting || - !window._bugsnag_api_key + !window.bugsnagApiKey ) { SNLog.onError = console.error; return; @@ -41,7 +41,7 @@ export function startErrorReporting(): void { } Bugsnag.start({ - apiKey: window._bugsnag_api_key, + apiKey: window.bugsnagApiKey, appType: isDesktopApplication() ? 'desktop' : 'web', appVersion: getDesktopVersion() || WebAppVersion, collectUserIp: false, diff --git a/app/assets/javascripts/startApplication.ts b/app/assets/javascripts/startApplication.ts index 334973948..11afdfc4c 100644 --- a/app/assets/javascripts/startApplication.ts +++ b/app/assets/javascripts/startApplication.ts @@ -1,8 +1,9 @@ -import { Bridge } from "./services/bridge"; +import { Bridge } from './services/bridge'; export type StartApplication = ( defaultSyncServerHost: string, + defaultFilesHostHost: string, bridge: Bridge, enableUnfinishedFeatures: boolean, - webSocketUrl: string, + webSocketUrl: string ) => Promise; diff --git a/app/assets/javascripts/ui_models/app_state/account_menu_state.ts b/app/assets/javascripts/ui_models/app_state/account_menu_state.ts index dbf7c5389..8360511b5 100644 --- a/app/assets/javascripts/ui_models/app_state/account_menu_state.ts +++ b/app/assets/javascripts/ui_models/app_state/account_menu_state.ts @@ -75,9 +75,9 @@ export class AccountMenuState { this.appEventListeners.push( this.application.addEventObserver(async () => { runInAction(() => { - if (isDev && window._devAccountServer) { - this.setServer(window._devAccountServer); - this.application.setCustomHost(window._devAccountServer); + if (isDev && window.devAccountServer) { + this.setServer(window.devAccountServer); + this.application.setCustomHost(window.devAccountServer); } else { this.setServer(this.application.getHost()); } diff --git a/app/assets/javascripts/ui_models/app_state/app_state.ts b/app/assets/javascripts/ui_models/app_state/app_state.ts index f406fec30..88f7a6ccc 100644 --- a/app/assets/javascripts/ui_models/app_state/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state/app_state.ts @@ -62,7 +62,7 @@ type ObserverCallback = (event: AppStateEvent, data?: any) => Promise; export class AppState { readonly enableUnfinishedFeatures: boolean = - window?._enable_unfinished_features; + window?.enabledUnfinishedFeatures; application: WebApplication; observers: ObserverCallback[] = []; diff --git a/app/assets/javascripts/ui_models/app_state/features_state.ts b/app/assets/javascripts/ui_models/app_state/features_state.ts index 25ad9026f..bc27ff200 100644 --- a/app/assets/javascripts/ui_models/app_state/features_state.ts +++ b/app/assets/javascripts/ui_models/app_state/features_state.ts @@ -25,7 +25,7 @@ export const SMART_TAGS_FEATURE_NAME = 'Smart Tags'; */ export class FeaturesState { readonly enableUnfinishedFeatures: boolean = - window?._enable_unfinished_features; + window?.enabledUnfinishedFeatures; _hasFolders = false; _hasSmartTags = false; diff --git a/app/assets/javascripts/ui_models/application.ts b/app/assets/javascripts/ui_models/application.ts index 32b5f24a5..54254e3fe 100644 --- a/app/assets/javascripts/ui_models/application.ts +++ b/app/assets/javascripts/ui_models/application.ts @@ -48,23 +48,24 @@ export class WebApplication extends SNApplication { platform: Platform, identifier: string, defaultSyncServerHost: string, + defaultFilesHostHost: string, public bridge: Bridge, webSocketUrl: string, runtime: Runtime ) { - super( - bridge.environment, - platform, - deviceInterface, - WebCrypto, - new AlertService(), + super({ + environment: bridge.environment, + platform: platform, + deviceInterface: deviceInterface, + crypto: WebCrypto, + alertService: new AlertService(), identifier, - [], - defaultSyncServerHost, - bridge.appVersion, - webSocketUrl, - runtime - ); + defaultHost: defaultSyncServerHost, + defaultFilesHost: defaultFilesHostHost, + appVersion: bridge.appVersion, + webSocketUrl: webSocketUrl, + runtime, + }); deviceInterface.setApplication(this); this.noteControllerGroup = new NoteGroupController(this); this.iconsController = new IconsController(); diff --git a/app/assets/javascripts/ui_models/application_group.ts b/app/assets/javascripts/ui_models/application_group.ts index d12fdc0c4..5c74699bc 100644 --- a/app/assets/javascripts/ui_models/application_group.ts +++ b/app/assets/javascripts/ui_models/application_group.ts @@ -20,6 +20,7 @@ import { ThemeManager } from '@/services/themeManager'; export class ApplicationGroup extends SNApplicationGroup { constructor( private defaultSyncServerHost: string, + private defaultFilesHostHost: string, private bridge: Bridge, private runtime: Runtime, private webSocketUrl: string @@ -50,6 +51,7 @@ export class ApplicationGroup extends SNApplicationGroup { platform, descriptor.identifier, this.defaultSyncServerHost, + this.defaultFilesHostHost, this.bridge, this.webSocketUrl, this.runtime diff --git a/app/views/application/app.html.erb b/app/views/application/app.html.erb index 9045c0643..582011651 100644 --- a/app/views/application/app.html.erb +++ b/app/views/application/app.html.erb @@ -31,13 +31,14 @@ <% if Rails.env.development? %> diff --git a/index.html b/index.html index dc8ed5e44..f2028cfeb 100644 --- a/index.html +++ b/index.html @@ -29,10 +29,11 @@ diff --git a/package.json b/package.json index 1c4e0eb67..848002033 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@reach/disclosure": "^0.16.2", "@reach/visually-hidden": "^0.16.0", "@svgr/webpack": "^6.2.1", - "@types/jest": "^27.4.0", + "@types/jest": "^27.4.1", "@types/lodash": "^4.14.178", "@types/react": "^17.0.39", "@typescript-eslint/eslint-plugin": "^5.12.1", @@ -76,11 +76,11 @@ "@reach/dialog": "^0.16.2", "@reach/listbox": "^0.16.2", "@reach/tooltip": "^0.16.2", - "@standardnotes/components": "1.7.5", - "@standardnotes/features": "1.32.11", - "@standardnotes/snjs": "2.63.1", + "@standardnotes/components": "1.7.6", + "@standardnotes/features": "1.32.12", + "@standardnotes/snjs": "2.63.5", "@standardnotes/settings": "^1.11.3", - "@standardnotes/sncrypto-web": "1.7.0", + "@standardnotes/sncrypto-web": "1.7.1", "mobx": "^6.4.1", "mobx-react-lite": "^3.3.0", "preact": "^10.6.6", diff --git a/yarn.lock b/yarn.lock index aab7acb6f..e352a294f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2366,80 +2366,80 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@standardnotes/auth@^3.16.4": - version "3.16.4" - resolved "https://registry.yarnpkg.com/@standardnotes/auth/-/auth-3.16.4.tgz#6293bd67cdc4055229f1d520b6f44b39c6053a7a" - integrity sha512-2tHsDnwQgGD3pOzKuSjo4yj8hLjATb70jzFnEWoEpyCdHTuGys9qSBElfi672hU4vg+/nXaHpdVUuD5DPzLaXg== +"@standardnotes/auth@^3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@standardnotes/auth/-/auth-3.16.5.tgz#54e0ea92bdc124c22f1d064d7a209504108e28e0" + integrity sha512-lEKPs6n3Jor79fOia/88SiEST67FFmCBTLthE1dJtl+Vo8URRjh9VLO5HYfbjEqH3bgffhR6m8EGJGPdzz+NQQ== dependencies: - "@standardnotes/common" "^1.14.0" + "@standardnotes/common" "^1.14.1" jsonwebtoken "^8.5.1" -"@standardnotes/common@^1.14.0": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@standardnotes/common/-/common-1.14.0.tgz#c3b8e06fb8120524da8d135f2dc594998e5a5c3a" - integrity sha512-QA8JhWty7y/N62jdLyWuXzsVvDDeFwcQAH/DB/g5Mmaqlz9VlKcsbRmVl4wHLG3ur6n5Qj68aOhzCQd0p7f/WA== +"@standardnotes/common@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@standardnotes/common/-/common-1.14.1.tgz#4322001eea59a7bb427007902bfdec5b57cfc64d" + integrity sha512-nRzLVMBk1L8aft6tVhK/ieDWa/rsRUzZzuclv94Mn1g0AJcqEqM0weziNIAfemdMIWpoZyhseJELD6pkWqQQeg== -"@standardnotes/components@1.7.5": - version "1.7.5" - resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.5.tgz#2f199350779a8f99e9e536223d318b822bdf369f" - integrity sha512-7nyrrcgPAkCf6pjbAIO8qOM+22KQU0jMCIDX3b4GAS1jXM7DJDy5Frnk3oMHd9NeFhnbf0TQH4Nz4uEeid6/HA== +"@standardnotes/components@1.7.6": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.6.tgz#6dcce572b32580a6df9091422d96c9c0b6917174" + integrity sha512-5lSYNKpO1tQRD6PMOs0IVTmPhfUh33+h6HQZdbWyCmjUk99QE86cI6IC8LnPh5rjHKG+jkfwgVzBKrR3QS/eQw== -"@standardnotes/domain-events@^2.23.14": - version "2.23.14" - resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.14.tgz#733e340c6d42935c90858380d7721150d1804574" - integrity sha512-DRPD0lGdVn/tbVyl97QGyyAcdUZd4qsETICCO882mG33HBN8Yc7st176U+izu3T5W3dlnTqE+MJUASj3UxVCvw== +"@standardnotes/domain-events@^2.23.15": + version "2.23.15" + resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.15.tgz#ce568fb5d30b220d49a70878efbc9bbee769bdf5" + integrity sha512-wJAoad9oXmAz39KZwYowiYny1dnHX/AJXdCdLwKxpJErh0h+VQhEhT2bPnqdIxJ90MTvn9jALhKM9AGlMEl+Aw== dependencies: - "@standardnotes/auth" "^3.16.4" - "@standardnotes/features" "^1.32.11" + "@standardnotes/auth" "^3.16.5" + "@standardnotes/features" "^1.32.12" -"@standardnotes/features@1.32.11", "@standardnotes/features@^1.32.11": - version "1.32.11" - resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.32.11.tgz#43417e541bdf0ce8a10dfd68e8073fc1338f1888" - integrity sha512-ZheQibMz4t2A6LKWcTDDGc5760AnPLFnHFwsSp0O8YydI3yz+qjm3pFF8XNeAEwgSvOX1W1nlX3E/X5tCp5LgQ== +"@standardnotes/features@1.32.12", "@standardnotes/features@^1.32.12": + version "1.32.12" + resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.32.12.tgz#20b52fa5b0c7c29feea9d9ebb12a10f87cb7ec75" + integrity sha512-Xs5Ss8DWNLFWIMibFMO5GKGv/je7SAYr3lR6NvyQgKl4+bBxAVKqLgccWLodAXrNuOFoGAXBbG9R8PsFfYKlYw== dependencies: - "@standardnotes/auth" "^3.16.4" - "@standardnotes/common" "^1.14.0" + "@standardnotes/auth" "^3.16.5" + "@standardnotes/common" "^1.14.1" -"@standardnotes/services@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.1.0.tgz#42f743f58fb4ab85627368ae6bcdf513079ef708" - integrity sha512-r4lqUO30iHmjWodUTv+2D8xeCgpYFvJrNzR/pBIlZsAKMSjskxPyIUvBdQvHWs0o4vjf7ZedhpEwi68XwUqO3w== +"@standardnotes/services@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.1.1.tgz#96065a8144c6f0d7695d7aedb0e10b8a9341a1b0" + integrity sha512-wM15yy3fjzlyVQWi0t9l0CZCSTMzBYQMrZBaBItSnN7P76zDa1MvQ9g7yWyC91nYGCgihI+nmDdArle88/4gWw== dependencies: - "@standardnotes/common" "^1.14.0" - "@standardnotes/utils" "^1.1.1" + "@standardnotes/common" "^1.14.1" + "@standardnotes/utils" "^1.1.2" "@standardnotes/settings@^1.11.3": version "1.11.3" resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.11.3.tgz#f7735da40807dab6eaf81cc82d8d30f5461d26d5" integrity sha512-95nqPYIZt57HMrymf4FTMDHOibM13AmV/8JEj7mPbIqcNKvVD486BURsaqpoBgkqB4Q43LbT8dfTrBPDgmIdxg== -"@standardnotes/sncrypto-common@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.7.0.tgz#6ad96afeaa031c26e45cbaf527bb511b803f998d" - integrity sha512-Dke13reJMLQFXa7y9EqZYEeZG5Ouy+32qWEsQISLjLRPrTuNwyNXee2mdPh6c9uNZxOQwrdHxVGfqzJ2iy3RpQ== +"@standardnotes/sncrypto-common@^1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.7.1.tgz#2feead118e83b605696b2bc46a0986cbf577f855" + integrity sha512-KAT/bZdbgLzDG8gOeuV07ObnYVE3kBoIK3dtRwlRfal3+BuiXE6JxaSblsophjTLG4i38/sBZ0Ex+UTZoebkug== -"@standardnotes/sncrypto-web@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-web/-/sncrypto-web-1.7.0.tgz#e3a6e69019210f375ccf8b9abb789c7dd7147cf6" - integrity sha512-7NM1QJjtdvmUlBeQLjZukg5LovKKhoM8oX/FLOnBgl04TqDSGtvx+HDncm+laCnHZkAJ6VCSmUUxgfs1sQzyPw== +"@standardnotes/sncrypto-web@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-web/-/sncrypto-web-1.7.1.tgz#8ccbd212a0afd4036d6048bd423b11f68fdafa38" + integrity sha512-oDAS8l6tWiCQNPxnI9i9P/5fud9jFIDz8/6MKeg+xsQ+HD+OUPES4c9a/5oz4ItY5gnYmYrEFLowv22gYFeKYg== dependencies: - "@standardnotes/sncrypto-common" "^1.7.0" + "@standardnotes/sncrypto-common" "^1.7.1" buffer "^6.0.3" libsodium-wrappers "^0.7.9" -"@standardnotes/snjs@2.63.1": - version "2.63.1" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.63.1.tgz#0759be39e77304fcca11ea902aa9be7bb737e756" - integrity sha512-d32CE7/yS+qEGlOfHTDc0NPzCFXPaK2zxlCi/j68R9lT/3LuV/uc1o9eNK9a5Fgcbtbk55vbW0rUYjQQVwUF8A== +"@standardnotes/snjs@2.63.5": + version "2.63.5" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.63.5.tgz#eb5fab274bc576a610033d894a3853f116a5e584" + integrity sha512-vhmqsRJn6UXJW1DK6jF0awTXEI/EYt1jzk7t5xpwLSThVM12LgPi/5u2KGPg1Ke7HHq2pejU/3AWNx7cbzXujw== dependencies: - "@standardnotes/auth" "^3.16.4" - "@standardnotes/common" "^1.14.0" - "@standardnotes/domain-events" "^2.23.14" - "@standardnotes/features" "^1.32.11" - "@standardnotes/services" "^1.1.0" + "@standardnotes/auth" "^3.16.5" + "@standardnotes/common" "^1.14.1" + "@standardnotes/domain-events" "^2.23.15" + "@standardnotes/features" "^1.32.12" + "@standardnotes/services" "^1.1.1" "@standardnotes/settings" "^1.11.3" - "@standardnotes/sncrypto-common" "^1.7.0" - "@standardnotes/utils" "^1.1.1" + "@standardnotes/sncrypto-common" "^1.7.1" + "@standardnotes/utils" "^1.1.2" "@standardnotes/stylekit@5.9.0": version "5.9.0" @@ -2451,12 +2451,12 @@ "@svgr/webpack" "^6.2.1" prop-types "^15.7.2" -"@standardnotes/utils@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@standardnotes/utils/-/utils-1.1.1.tgz#a936edd328b4e10b43b11ffc8b1626a499fa6659" - integrity sha512-LaB1Y4arvwuABT0fybJ9At6pPEAwsDooaldYPuvqyfQAWdeqRCBMHxRDCX6yunrrwBwk7UoTie9MRw6DF1igwg== +"@standardnotes/utils@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@standardnotes/utils/-/utils-1.1.2.tgz#5bc1919a3a90c61a34354275d9129f71a23ee34d" + integrity sha512-D39U3S1XJIeLCRYnI98sBVWx0VcVYTfBNZTLU2K0ICRg2fvszQvyLRlFA4U7wf9x0QXsqVjORxAVcIiC5UoQPA== dependencies: - "@standardnotes/common" "^1.14.0" + "@standardnotes/common" "^1.14.1" dompurify "^2.3.4" lodash "^4.17.19" @@ -2720,12 +2720,12 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^27.4.0": - version "27.4.0" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed" - integrity sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ== +"@types/jest@^27.4.1": + version "27.4.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d" + integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw== dependencies: - jest-diff "^27.0.0" + jest-matcher-utils "^27.0.0" pretty-format "^27.0.0" "@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": @@ -4395,11 +4395,6 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== -diff-sequences@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5" - integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww== - diff-sequences@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" @@ -6279,16 +6274,6 @@ jest-config@^27.5.1: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^27.0.0: - version "27.4.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.2.tgz#786b2a5211d854f848e2dcc1e324448e9481f36f" - integrity sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q== - dependencies: - chalk "^4.0.0" - diff-sequences "^27.4.0" - jest-get-type "^27.4.0" - pretty-format "^27.4.2" - jest-diff@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" @@ -6342,11 +6327,6 @@ jest-environment-node@^27.5.1: jest-mock "^27.5.1" jest-util "^27.5.1" -jest-get-type@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5" - integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== - jest-get-type@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" @@ -6403,7 +6383,7 @@ jest-leak-detector@^27.5.1: jest-get-type "^27.5.1" pretty-format "^27.5.1" -jest-matcher-utils@^27.5.1: +jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== @@ -7922,7 +7902,7 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" -pretty-format@^27.0.0, pretty-format@^27.4.2: +pretty-format@^27.0.0: version "27.4.2" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.2.tgz#e4ce92ad66c3888423d332b40477c87d1dac1fb8" integrity sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw== From 4db8ca8bddbf19cac0d099b6f1f3e4552d9b63ca Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Fri, 25 Feb 2022 19:11:21 +0530 Subject: [PATCH 09/17] feat: use improved style calculation for change editor submenu (#899) --- .../NotesOptions/ChangeEditorOption.tsx | 141 ++---------------- 1 file changed, 16 insertions(+), 125 deletions(-) diff --git a/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx b/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx index 3abf7989e..7f35a9f2d 100644 --- a/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx +++ b/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx @@ -1,10 +1,6 @@ import { KeyboardKey } from '@/services/ioService'; import { WebApplication } from '@/ui_models/application'; import { AppState } from '@/ui_models/app_state'; -import { - MENU_MARGIN_FROM_APP_BORDER, - MAX_MENU_SIZE_MULTIPLIER, -} from '@/constants'; import { Disclosure, DisclosureButton, @@ -21,6 +17,10 @@ import { useEffect, useRef, useState } from 'preact/hooks'; import { Icon } from '../Icon'; import { createEditorMenuGroups } from './changeEditor/createEditorMenuGroups'; import { ChangeEditorMenu } from './changeEditor/ChangeEditorMenu'; +import { + calculateSubmenuStyle, + SubmenuStyle, +} from '@/utils/calculateSubmenuStyle'; type ChangeEditorOptionProps = { appState: AppState; @@ -44,92 +44,6 @@ export type EditorMenuItem = { export type EditorMenuGroup = AccordionMenuGroup; -type MenuPositionStyle = { - top?: number | 'auto'; - right?: number | 'auto'; - bottom: number | 'auto'; - left?: number | 'auto'; - visibility?: 'hidden' | 'visible'; -}; - -const calculateMenuPosition = ( - button: HTMLButtonElement | null, - menu?: HTMLDivElement | null -): MenuPositionStyle | undefined => { - const defaultFontSize = window.getComputedStyle( - document.documentElement - ).fontSize; - - const maxChangeEditorMenuSize = - parseFloat(defaultFontSize) * MAX_MENU_SIZE_MULTIPLIER; - - const { clientWidth, clientHeight } = document.documentElement; - - const buttonRect = button?.getBoundingClientRect(); - - const buttonParentRect = button?.parentElement?.getBoundingClientRect(); - - const menuBoundingRect = menu?.getBoundingClientRect(); - - const footerElementRect = document - .getElementById('footer-bar') - ?.getBoundingClientRect(); - - const footerHeightInPx = footerElementRect?.height ?? 0; - - let position: MenuPositionStyle = { - bottom: 'auto', - }; - - if (buttonRect && buttonParentRect) { - let positionBottom = - clientHeight - buttonRect.bottom - buttonRect.height / 2; - - if (positionBottom < footerHeightInPx) { - positionBottom = footerHeightInPx + MENU_MARGIN_FROM_APP_BORDER; - } - - if (buttonRect.right + maxChangeEditorMenuSize > clientWidth) { - position = { - bottom: positionBottom, - right: clientWidth - buttonRect.left, - visibility: 'hidden', - }; - } else { - position = { - bottom: positionBottom, - left: buttonRect.right, - visibility: 'hidden', - }; - } - } - - if (menuBoundingRect && menuBoundingRect.height && buttonRect) { - if (menuBoundingRect.y < MENU_MARGIN_FROM_APP_BORDER) { - if ( - buttonRect.right + maxChangeEditorMenuSize > - document.documentElement.clientWidth - ) { - return { - ...position, - top: MENU_MARGIN_FROM_APP_BORDER + buttonRect.top - buttonRect.height, - bottom: 'auto', - visibility: 'visible', - }; - } else { - return { - ...position, - top: MENU_MARGIN_FROM_APP_BORDER, - bottom: 'auto', - visibility: 'visible', - }; - } - } - } - - return position; -}; - export const ChangeEditorOption: FunctionComponent = ({ application, closeOnBlur, @@ -137,14 +51,11 @@ export const ChangeEditorOption: FunctionComponent = ({ }) => { const [changeEditorMenuOpen, setChangeEditorMenuOpen] = useState(false); const [changeEditorMenuVisible, setChangeEditorMenuVisible] = useState(false); - const [changeEditorMenuMaxHeight, setChangeEditorMenuMaxHeight] = useState< - number | 'auto' - >('auto'); - const [changeEditorMenuPosition, setChangeEditorMenuPosition] = - useState({ - right: 0, - bottom: 0, - }); + const [menuStyle, setMenuStyle] = useState({ + right: 0, + bottom: 0, + maxHeight: 'auto', + }); const changeEditorMenuRef = useRef(null); const changeEditorButtonRef = useRef(null); const [editors] = useState(() => @@ -171,9 +82,9 @@ export const ChangeEditorOption: FunctionComponent = ({ const toggleChangeEditorMenu = () => { if (!changeEditorMenuOpen) { - const menuPosition = calculateMenuPosition(changeEditorButtonRef.current); - if (menuPosition) { - setChangeEditorMenuPosition(menuPosition); + const menuStyle = calculateSubmenuStyle(changeEditorButtonRef.current); + if (menuStyle) { + setMenuStyle(menuStyle); } } @@ -183,32 +94,13 @@ export const ChangeEditorOption: FunctionComponent = ({ useEffect(() => { if (changeEditorMenuOpen) { setTimeout(() => { - const newMenuPosition = calculateMenuPosition( + const newMenuStyle = calculateSubmenuStyle( changeEditorButtonRef.current, changeEditorMenuRef.current ); - if (newMenuPosition) { - const { clientHeight } = document.documentElement; - const footerElementRect = document - .getElementById('footer-bar') - ?.getBoundingClientRect(); - const footerHeightInPx = footerElementRect?.height; - - if ( - footerHeightInPx && - newMenuPosition.top && - newMenuPosition.top !== 'auto' - ) { - setChangeEditorMenuMaxHeight( - clientHeight - - newMenuPosition.top - - footerHeightInPx - - MENU_MARGIN_FROM_APP_BORDER - ); - } - - setChangeEditorMenuPosition(newMenuPosition); + if (newMenuStyle) { + setMenuStyle(newMenuStyle); setChangeEditorMenuVisible(true); } }); @@ -242,8 +134,7 @@ export const ChangeEditorOption: FunctionComponent = ({ } }} style={{ - ...changeEditorMenuPosition, - maxHeight: changeEditorMenuMaxHeight, + ...menuStyle, position: 'fixed', }} className="sn-dropdown flex flex-col max-h-120 min-w-68 fixed overflow-y-auto" From 16fc3eb52108f3d0bba3f1cb007c150c179be29d Mon Sep 17 00:00:00 2001 From: Mo Date: Sun, 27 Feb 2022 13:18:21 -0600 Subject: [PATCH 10/17] refactor: smart tags to views (#902) * refactor: smart tags to views * chore: upgrade snjs --- .../javascripts/components/Navigation.tsx | 4 +- .../javascripts/components/NotesList.tsx | 4 +- .../{SmartTagsList.tsx => SmartViewsList.tsx} | 14 +- ...agsListItem.tsx => SmartViewsListItem.tsx} | 69 +++---- ...tTagsSection.tsx => SmartViewsSection.tsx} | 6 +- .../components/Tags/TagContextMenu.tsx | 3 +- .../ui_models/app_state/app_state.ts | 21 ++- .../ui_models/app_state/features_state.ts | 14 +- .../ui_models/app_state/notes_view_state.ts | 19 +- .../ui_models/app_state/tags_state.ts | 73 ++++---- package.json | 12 +- yarn.lock | 168 +++++++++++------- 12 files changed, 237 insertions(+), 170 deletions(-) rename app/assets/javascripts/components/Tags/{SmartTagsList.tsx => SmartViewsList.tsx} (57%) rename app/assets/javascripts/components/Tags/{SmartTagsListItem.tsx => SmartViewsListItem.tsx} (71%) rename app/assets/javascripts/components/Tags/{SmartTagsSection.tsx => SmartViewsSection.tsx} (61%) diff --git a/app/assets/javascripts/components/Navigation.tsx b/app/assets/javascripts/components/Navigation.tsx index dc21f56ec..d5b235b04 100644 --- a/app/assets/javascripts/components/Navigation.tsx +++ b/app/assets/javascripts/components/Navigation.tsx @@ -1,4 +1,4 @@ -import { SmartTagsSection } from '@/components/Tags/SmartTagsSection'; +import { SmartViewsSection } from '@/components/Tags/SmartViewsSection'; import { TagsSection } from '@/components/Tags/TagsSection'; import { WebApplication } from '@/ui_models/application'; import { PANEL_NAME_NAVIGATION } from '@/constants'; @@ -65,7 +65,7 @@ export const Navigation: FunctionComponent = observer(
- +
diff --git a/app/assets/javascripts/components/NotesList.tsx b/app/assets/javascripts/components/NotesList.tsx index 446b62891..69b1f1c0d 100644 --- a/app/assets/javascripts/components/NotesList.tsx +++ b/app/assets/javascripts/components/NotesList.tsx @@ -2,7 +2,7 @@ import { WebApplication } from '@/ui_models/application'; import { KeyboardKey } from '@/services/ioService'; import { AppState } from '@/ui_models/app_state'; import { DisplayOptions } from '@/ui_models/app_state/notes_view_state'; -import { SNNote } from '@standardnotes/snjs'; +import { SNNote, SNTag } from '@standardnotes/snjs'; import { observer } from 'mobx-react-lite'; import { FunctionComponent } from 'preact'; import { NotesListItem } from './NotesListItem'; @@ -42,7 +42,7 @@ export const NotesList: FunctionComponent = observer( return []; } const tags = appState.getNoteTags(note); - if (!selectedTag.isSmartTag && tags.length === 1) { + if (selectedTag instanceof SNTag && tags.length === 1) { return []; } return tags.map((tag) => tag.title).sort(); diff --git a/app/assets/javascripts/components/Tags/SmartTagsList.tsx b/app/assets/javascripts/components/Tags/SmartViewsList.tsx similarity index 57% rename from app/assets/javascripts/components/Tags/SmartTagsList.tsx rename to app/assets/javascripts/components/Tags/SmartViewsList.tsx index 77b06eec8..16526d087 100644 --- a/app/assets/javascripts/components/Tags/SmartTagsList.tsx +++ b/app/assets/javascripts/components/Tags/SmartViewsList.tsx @@ -1,23 +1,23 @@ import { AppState } from '@/ui_models/app_state'; import { observer } from 'mobx-react-lite'; import { FunctionComponent } from 'preact'; -import { SmartTagsListItem } from './SmartTagsListItem'; +import { SmartViewsListItem } from './SmartViewsListItem'; type Props = { appState: AppState; }; -export const SmartTagsList: FunctionComponent = observer( +export const SmartViewsList: FunctionComponent = observer( ({ appState }) => { - const allTags = appState.tags.smartTags; + const allViews = appState.tags.smartViews; return ( <> - {allTags.map((tag) => { + {allViews.map((view) => { return ( - diff --git a/app/assets/javascripts/components/Tags/SmartTagsListItem.tsx b/app/assets/javascripts/components/Tags/SmartViewsListItem.tsx similarity index 71% rename from app/assets/javascripts/components/Tags/SmartTagsListItem.tsx rename to app/assets/javascripts/components/Tags/SmartViewsListItem.tsx index d6405fd7d..cb52f78cc 100644 --- a/app/assets/javascripts/components/Tags/SmartTagsListItem.tsx +++ b/app/assets/javascripts/components/Tags/SmartViewsListItem.tsx @@ -2,13 +2,18 @@ import { Icon } from '@/components/Icon'; import { FeaturesState } from '@/ui_models/app_state/features_state'; import { TagsState } from '@/ui_models/app_state/tags_state'; import '@reach/tooltip/styles.css'; -import { SNSmartTag, IconType } from '@standardnotes/snjs'; +import { + SmartView, + SystemViewId, + IconType, + isSystemView, +} from '@standardnotes/snjs'; import { observer } from 'mobx-react-lite'; import { FunctionComponent } from 'preact'; import { useCallback, useEffect, useRef, useState } from 'preact/hooks'; type Props = { - tag: SNSmartTag; + view: SmartView; tagsState: TagsState; features: FeaturesState; }; @@ -16,40 +21,40 @@ type Props = { const PADDING_BASE_PX = 14; const PADDING_PER_LEVEL_PX = 21; -const smartTagIconType = (tag: SNSmartTag): IconType => { - if (tag.isAllTag) { +const smartViewIconType = (view: SmartView): IconType => { + if (view.uuid === SystemViewId.AllNotes) { return 'notes'; } - if (tag.isArchiveTag) { + if (view.uuid === SystemViewId.ArchivedNotes) { return 'archive'; } - if (tag.isTrashTag) { + if (view.uuid === SystemViewId.TrashedNotes) { return 'trash'; } return 'hashtag'; }; -export const SmartTagsListItem: FunctionComponent = observer( - ({ tag, tagsState, features }) => { - const [title, setTitle] = useState(tag.title || ''); +export const SmartViewsListItem: FunctionComponent = observer( + ({ view, tagsState }) => { + const [title, setTitle] = useState(view.title || ''); const inputRef = useRef(null); const level = 0; - const isSelected = tagsState.selected === tag; - const isEditing = tagsState.editingTag === tag; + const isSelected = tagsState.selected === view; + const isEditing = tagsState.editingTag === view; useEffect(() => { - setTitle(tag.title || ''); - }, [setTitle, tag]); + setTitle(view.title || ''); + }, [setTitle, view]); const selectCurrentTag = useCallback(() => { - tagsState.selected = tag; - }, [tagsState, tag]); + tagsState.selected = view; + }, [tagsState, view]); const onBlur = useCallback(() => { - tagsState.save(tag, title); - setTitle(tag.title); - }, [tagsState, tag, title, setTitle]); + tagsState.save(view, title); + setTitle(view.title); + }, [tagsState, view, title, setTitle]); const onInput = useCallback( (e: Event) => { @@ -76,19 +81,19 @@ export const SmartTagsListItem: FunctionComponent = observer( }, [inputRef, isEditing]); const onClickRename = useCallback(() => { - tagsState.editingTag = tag; - }, [tagsState, tag]); + tagsState.editingTag = view; + }, [tagsState, view]); const onClickSave = useCallback(() => { inputRef.current?.blur(); }, [inputRef]); const onClickDelete = useCallback(() => { - tagsState.remove(tag, true); - }, [tagsState, tag]); + tagsState.remove(view, true); + }, [tagsState, view]); - const isFaded = !tag.isAllTag; - const iconType = smartTagIconType(tag); + const isFaded = false; + const iconType = smartViewIconType(view); return ( <> @@ -101,7 +106,7 @@ export const SmartTagsListItem: FunctionComponent = observer( paddingLeft: `${level * PADDING_PER_LEVEL_PX + PADDING_BASE_PX}px`, }} > - {!tag.errorDecrypting ? ( + {!view.errorDecrypting ? (
= observer( = observer( ref={inputRef} />
- {tag.isAllTag && tagsState.allNotesCount} + {view.uuid === SystemViewId.AllNotes && tagsState.allNotesCount}
) : null} - {!tag.isSystemSmartTag && ( + {!isSystemView(view) && (
- {tag.conflictOf && ( + {view.conflictOf && (
- Conflicted Copy {tag.conflictOf} + Conflicted Copy {view.conflictOf}
)} - {tag.errorDecrypting && !tag.waitingForKey && ( + {view.errorDecrypting && !view.waitingForKey && (
Missing Keys
)} - {tag.errorDecrypting && tag.waitingForKey && ( + {view.errorDecrypting && view.waitingForKey && (
Waiting For Keys
diff --git a/app/assets/javascripts/components/Tags/SmartTagsSection.tsx b/app/assets/javascripts/components/Tags/SmartViewsSection.tsx similarity index 61% rename from app/assets/javascripts/components/Tags/SmartTagsSection.tsx rename to app/assets/javascripts/components/Tags/SmartViewsSection.tsx index 2032aa6ce..6aedcd1f5 100644 --- a/app/assets/javascripts/components/Tags/SmartTagsSection.tsx +++ b/app/assets/javascripts/components/Tags/SmartViewsSection.tsx @@ -1,17 +1,17 @@ import { AppState } from '@/ui_models/app_state'; import { observer } from 'mobx-react-lite'; import { FunctionComponent } from 'preact'; -import { SmartTagsList } from './SmartTagsList'; +import { SmartViewsList } from './SmartViewsList'; type Props = { appState: AppState; }; -export const SmartTagsSection: FunctionComponent = observer( +export const SmartViewsSection: FunctionComponent = observer( ({ appState }) => { return (
- +
); } diff --git a/app/assets/javascripts/components/Tags/TagContextMenu.tsx b/app/assets/javascripts/components/Tags/TagContextMenu.tsx index 51054d34e..04c2a5ca6 100644 --- a/app/assets/javascripts/components/Tags/TagContextMenu.tsx +++ b/app/assets/javascripts/components/Tags/TagContextMenu.tsx @@ -7,6 +7,7 @@ import { Menu } from '../menu/Menu'; import { MenuItem, MenuItemType } from '../menu/MenuItem'; import { usePremiumModal } from '../Premium'; import { useCloseOnBlur } from '../utils'; +import { SNTag } from '@standardnotes/snjs'; type Props = { appState: AppState; @@ -17,7 +18,7 @@ export const TagsContextMenu: FunctionComponent = observer( const premiumModal = usePremiumModal(); const selectedTag = appState.tags.selected; - if (!selectedTag) { + if (!selectedTag || !(selectedTag instanceof SNTag)) { return null; } diff --git a/app/assets/javascripts/ui_models/app_state/app_state.ts b/app/assets/javascripts/ui_models/app_state/app_state.ts index 88f7a6ccc..2e86701e9 100644 --- a/app/assets/javascripts/ui_models/app_state/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state/app_state.ts @@ -11,8 +11,9 @@ import { PayloadSource, PrefKey, SNNote, - SNSmartTag, + SmartView, SNTag, + SystemViewId, } from '@standardnotes/snjs'; import pull from 'lodash/pull'; import { @@ -241,7 +242,9 @@ export class AppState { const selectedTag = this.selectedTag; const activeRegularTagUuid = - selectedTag && !selectedTag.isSmartTag ? selectedTag.uuid : undefined; + selectedTag && selectedTag instanceof SNTag + ? selectedTag.uuid + : undefined; await this.application.noteControllerGroup.createNoteView( undefined, @@ -313,11 +316,11 @@ export class AppState { ); } - public get selectedTag(): SNTag | SNSmartTag | undefined { + public get selectedTag(): SNTag | SmartView | undefined { return this.tags.selected; } - public set selectedTag(tag: SNTag | SNSmartTag | undefined) { + public set selectedTag(tag: SNTag | SmartView | undefined) { this.tags.selected = tag; } @@ -341,13 +344,19 @@ export class AppState { this.closeNoteController(noteController); } else if ( note.trashed && - !selectedTag?.isTrashTag && + !( + selectedTag instanceof SmartView && + selectedTag.uuid === SystemViewId.TrashedNotes + ) && !this.searchOptions.includeTrashed ) { this.closeNoteController(noteController); } else if ( note.archived && - !selectedTag?.isArchiveTag && + !( + selectedTag instanceof SmartView && + selectedTag.uuid === SystemViewId.ArchivedNotes + ) && !this.searchOptions.includeArchived && !this.application.getPreference(PrefKey.NotesShowArchived, false) ) { diff --git a/app/assets/javascripts/ui_models/app_state/features_state.ts b/app/assets/javascripts/ui_models/app_state/features_state.ts index bc27ff200..bebd3f14f 100644 --- a/app/assets/javascripts/ui_models/app_state/features_state.ts +++ b/app/assets/javascripts/ui_models/app_state/features_state.ts @@ -28,19 +28,19 @@ export class FeaturesState { window?.enabledUnfinishedFeatures; _hasFolders = false; - _hasSmartTags = false; + _hasSmartViews = false; _premiumAlertFeatureName: string | undefined; private unsub: () => void; constructor(private application: WebApplication) { this._hasFolders = this.hasNativeFolders(); - this._hasSmartTags = this.hasNativeSmartTags(); + this._hasSmartViews = this.hasNativeSmartViews(); this._premiumAlertFeatureName = undefined; makeObservable(this, { _hasFolders: observable, - _hasSmartTags: observable, + _hasSmartViews: observable, hasFolders: computed, _premiumAlertFeatureName: observable, showPremiumAlert: action, @@ -56,7 +56,7 @@ export class FeaturesState { case ApplicationEvent.Launched: runInAction(() => { this._hasFolders = this.hasNativeFolders(); - this._hasSmartTags = this.hasNativeSmartTags(); + this._hasSmartViews = this.hasNativeSmartViews(); }); break; default: @@ -73,8 +73,8 @@ export class FeaturesState { return this._hasFolders; } - public get hasSmartTags(): boolean { - return this._hasSmartTags; + public get hasSmartViews(): boolean { + return this._hasSmartViews; } public async showPremiumAlert(featureName: string): Promise { @@ -94,7 +94,7 @@ export class FeaturesState { return status === FeatureStatus.Entitled; } - private hasNativeSmartTags(): boolean { + private hasNativeSmartViews(): boolean { const status = this.application.getFeatureStatus( FeatureIdentifier.SmartFilters ); diff --git a/app/assets/javascripts/ui_models/app_state/notes_view_state.ts b/app/assets/javascripts/ui_models/app_state/notes_view_state.ts index ec26fc710..c22e3ce1c 100644 --- a/app/assets/javascripts/ui_models/app_state/notes_view_state.ts +++ b/app/assets/javascripts/ui_models/app_state/notes_view_state.ts @@ -5,8 +5,10 @@ import { findInArray, NotesDisplayCriteria, PrefKey, + SmartView, SNNote, SNTag, + SystemViewId, UuidString, } from '@standardnotes/snjs'; import { @@ -79,7 +81,10 @@ export class NotesViewState { const discarded = activeNote.deleted || activeNote.trashed; if ( discarded && - !this.appState?.selectedTag?.isTrashTag && + !( + this.appState.selectedTag instanceof SmartView && + this.appState.selectedTag?.uuid === SystemViewId.TrashedNotes + ) && !this.appState?.searchOptions.includeTrashed ) { this.selectNextOrCreateNew(); @@ -116,7 +121,8 @@ export class NotesViewState { this.reloadNotes(); if ( this.notes.length === 0 && - this.appState.selectedTag?.isAllTag && + this.appState.selectedTag instanceof SmartView && + this.appState.selectedTag.uuid === SystemViewId.AllNotes && this.noteFilterText === '' && !this.appState.notes.activeNoteController ) { @@ -246,7 +252,8 @@ export class NotesViewState { const criteria = NotesDisplayCriteria.Create({ sortProperty: this.displayOptions.sortBy as CollectionSort, sortDirection: this.displayOptions.sortReverse ? 'asc' : 'dsc', - tags: tag ? [tag] : [], + tags: tag instanceof SNTag ? [tag] : [], + views: tag instanceof SmartView ? [tag] : [], includeArchived, includeTrashed, includePinned: !this.displayOptions.hidePinned, @@ -353,7 +360,11 @@ export class NotesViewState { createPlaceholderNote = () => { const selectedTag = this.appState.selectedTag; - if (selectedTag && selectedTag.isSmartTag && !selectedTag.isAllTag) { + if ( + selectedTag && + selectedTag instanceof SmartView && + selectedTag.uuid !== SystemViewId.AllNotes + ) { return; } return this.createNewNote(); 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 4ba4c12b6..05dac66bb 100644 --- a/app/assets/javascripts/ui_models/app_state/tags_state.ts +++ b/app/assets/javascripts/ui_models/app_state/tags_state.ts @@ -9,10 +9,11 @@ import { ContentType, MessageData, SNApplication, - SNSmartTag, + SmartView, SNTag, TagMutator, UuidString, + isSystemView, } from '@standardnotes/snjs'; import { action, @@ -25,7 +26,7 @@ import { import { WebApplication } from '../application'; import { FeaturesState, SMART_TAGS_FEATURE_NAME } from './features_state'; -type AnyTag = SNTag | SNSmartTag; +type AnyTag = SNTag | SmartView; const rootTags = (application: SNApplication): SNTag[] => { const hasNoParent = (tag: SNTag) => !application.getTagParent(tag); @@ -71,11 +72,11 @@ const isValidFutureSiblings = ( export class TagsState { tags: SNTag[] = []; - smartTags: SNSmartTag[] = []; + smartViews: SmartView[] = []; allNotesCount_ = 0; selected_: AnyTag | undefined; previouslySelected_: AnyTag | undefined; - editing_: SNTag | undefined; + editing_: SNTag | SmartView | undefined; addingSubtagTo: SNTag | undefined; contextMenuOpen = false; @@ -100,12 +101,12 @@ export class TagsState { this.editing_ = undefined; this.addingSubtagTo = undefined; - this.smartTags = this.application.getSmartTags(); - this.selected_ = this.smartTags[0]; + this.smartViews = this.application.getSmartViews(); + this.selected_ = this.smartViews[0]; makeObservable(this, { tags: observable.ref, - smartTags: observable.ref, + smartViews: observable.ref, hasAtLeastOneFolder: computed, allNotesCount_: observable, allNotesCount: computed, @@ -144,28 +145,28 @@ export class TagsState { appEventListeners.push( this.application.streamItems( - [ContentType.Tag, ContentType.SmartTag], + [ContentType.Tag, ContentType.SmartView], (items) => { runInAction(() => { - this.tags = this.application.getDisplayableItems( + this.tags = this.application.getDisplayableItems( ContentType.Tag - ) as SNTag[]; - this.smartTags = this.application.getSmartTags(); + ); + this.smartViews = this.application.getSmartViews(); const selectedTag = this.selected_; - if (selectedTag) { + if (selectedTag && !isSystemView(selectedTag as SmartView)) { const matchingTag = items.find( (candidate) => candidate.uuid === selectedTag.uuid - ); + ) as AnyTag; if (matchingTag) { if (matchingTag.deleted) { - this.selected_ = this.smartTags[0]; + this.selected_ = this.smartViews[0]; } else { - this.selected_ = matchingTag as AnyTag; + this.selected_ = matchingTag; } } } else { - this.selected_ = this.smartTags[0]; + this.selected_ = this.smartViews[0]; } }); } @@ -193,7 +194,9 @@ export class TagsState { return; } - const createdTag = await this.application.createTagOrSmartTag(title); + const createdTag = (await this.application.createTagOrSmartView( + title + )) as SNTag; const futureSiblings = this.application.getTagChildren(parent); @@ -294,7 +297,10 @@ export class TagsState { } public get allLocalRootTags(): SNTag[] { - if (this.editing_ && this.application.isTemplateItem(this.editing_)) { + if ( + this.editing_ instanceof SNTag && + this.application.isTemplateItem(this.editing_) + ) { return [this.editing_, ...this.rootTags]; } return this.rootTags; @@ -309,9 +315,7 @@ export class TagsState { return []; } - const children = this.application - .getTagChildren(tag) - .filter((tag) => !tag.isSmartTag); + const children = this.application.getTagChildren(tag); const childrenUuids = children.map((childTag) => childTag.uuid); const childrenTags = this.tags.filter((tag) => @@ -414,11 +418,11 @@ export class TagsState { return this.selected_?.uuid; } - public get editingTag(): SNTag | undefined { + public get editingTag(): SNTag | SmartView | undefined { return this.editing_; } - public set editingTag(editingTag: SNTag | undefined) { + public set editingTag(editingTag: SNTag | SmartView | undefined) { this.editing_ = editingTag; this.selected = editingTag; } @@ -442,11 +446,11 @@ export class TagsState { public undoCreateNewTag() { this.editing_ = undefined; - const previousTag = this.previouslySelected_ || this.smartTags[0]; + const previousTag = this.previouslySelected_ || this.smartViews[0]; this.selected = previousTag; } - public async remove(tag: SNTag, userTriggered: boolean) { + public async remove(tag: SNTag | SmartView, userTriggered: boolean) { let shouldDelete = !userTriggered; if (userTriggered) { shouldDelete = await confirmDialog({ @@ -456,16 +460,17 @@ export class TagsState { } if (shouldDelete) { this.application.deleteItem(tag); - this.selected = this.smartTags[0]; + this.selected = this.smartViews[0]; } } - public async save(tag: SNTag, newTitle: string) { + public async save(tag: SNTag | SmartView, newTitle: string) { const hasEmptyTitle = newTitle.length === 0; const hasNotChangedTitle = newTitle === tag.title; const isTemplateChange = this.application.isTemplateItem(tag); - const siblings = tagSiblings(this.application, tag); + const siblings = + tag instanceof SNTag ? tagSiblings(this.application, tag) : []; const hasDuplicatedTitle = siblings.some( (other) => other.title.toLowerCase() === newTitle.toLowerCase() ); @@ -492,16 +497,16 @@ export class TagsState { } if (isTemplateChange) { - const isSmartTagTitle = this.application.isSmartTagTitle(newTitle); + const isSmartViewTitle = this.application.isSmartViewTitle(newTitle); - if (isSmartTagTitle) { - if (!this.features.hasSmartTags) { + if (isSmartViewTitle) { + if (!this.features.hasSmartViews) { await this.features.showPremiumAlert(SMART_TAGS_FEATURE_NAME); return; } } - const insertedTag = await this.application.createTagOrSmartTag(newTitle); + const insertedTag = await this.application.createTagOrSmartView(newTitle); this.application.sync(); runInAction(() => { this.selected = insertedTag as SNTag; @@ -529,7 +534,7 @@ export class TagsState { if ( item.content_type === ContentType.Tag || - item.content_type === ContentType.SmartTag + item.content_type === ContentType.SmartView ) { const matchingTag = this.application.findItem(item.uuid); @@ -539,7 +544,7 @@ export class TagsState { } } } else if (action === ComponentAction.ClearSelection) { - this.selected = this.smartTags[0]; + this.selected = this.smartViews[0]; } } diff --git a/package.json b/package.json index 848002033..e5cf44306 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@reach/visually-hidden": "^0.16.0", "@svgr/webpack": "^6.2.1", "@types/jest": "^27.4.1", - "@types/lodash": "^4.14.178", + "@types/lodash": "^4.14.179", "@types/react": "^17.0.39", "@typescript-eslint/eslint-plugin": "^5.12.1", "@typescript-eslint/parser": "^5.12.1", @@ -40,9 +40,9 @@ "copy-webpack-plugin": "^10.2.4", "css-loader": "^6.6.0", "dotenv": "^16.0.0", - "eslint": "^8.9.0", + "eslint": "^8.10.0", "eslint-config-prettier": "^8.4.0", - "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react": "^7.29.2", "eslint-plugin-react-hooks": "^4.3.0", "file-loader": "^6.2.0", "html-webpack-plugin": "^5.5.0", @@ -77,11 +77,11 @@ "@reach/listbox": "^0.16.2", "@reach/tooltip": "^0.16.2", "@standardnotes/components": "1.7.6", - "@standardnotes/features": "1.32.12", - "@standardnotes/snjs": "2.63.5", + "@standardnotes/features": "1.33.1", + "@standardnotes/snjs": "2.65.3", "@standardnotes/settings": "^1.11.3", "@standardnotes/sncrypto-web": "1.7.1", - "mobx": "^6.4.1", + "mobx": "^6.4.2", "mobx-react-lite": "^3.3.0", "preact": "^10.6.6", "qrcode.react": "^1.0.1", diff --git a/yarn.lock b/yarn.lock index e352a294f..462ccdce8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1804,10 +1804,10 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz#9283c9ce5b289a3c4f61c12757469e59377f81f3" integrity sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA== -"@eslint/eslintrc@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.1.0.tgz#583d12dbec5d4f22f333f9669f7d0b7c7815b4d3" - integrity sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg== +"@eslint/eslintrc@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a" + integrity sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -2366,47 +2366,65 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@standardnotes/auth@^3.16.5": - version "3.16.5" - resolved "https://registry.yarnpkg.com/@standardnotes/auth/-/auth-3.16.5.tgz#54e0ea92bdc124c22f1d064d7a209504108e28e0" - integrity sha512-lEKPs6n3Jor79fOia/88SiEST67FFmCBTLthE1dJtl+Vo8URRjh9VLO5HYfbjEqH3bgffhR6m8EGJGPdzz+NQQ== +"@standardnotes/applications@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@standardnotes/applications/-/applications-1.1.1.tgz#c57b9e192436d43963b36919ab44d1c626838151" + integrity sha512-C3K1dzjLG/kG4BCXMhCaL5xBnLXIaElkxZRxmg3Xrnh2XqtO7IbEsrjii8VxdYvjbhCEriFXLgghcSyHujaTTA== dependencies: - "@standardnotes/common" "^1.14.1" + "@standardnotes/common" "^1.15.1" + +"@standardnotes/auth@^3.17.1": + version "3.17.1" + resolved "https://registry.yarnpkg.com/@standardnotes/auth/-/auth-3.17.1.tgz#eda5f3e156c990c59407ce5a17f043a5caefe5f9" + integrity sha512-A3y20NeXa5MU5jxTlM1rxD6eMWe6K7WdWsANIiJceuFUx2jisX2esZyJluGZ2Pi3dwhMuOzmoX8iRgk3eUmkgg== + dependencies: + "@standardnotes/common" "^1.15.1" jsonwebtoken "^8.5.1" -"@standardnotes/common@^1.14.1": - version "1.14.1" - resolved "https://registry.yarnpkg.com/@standardnotes/common/-/common-1.14.1.tgz#4322001eea59a7bb427007902bfdec5b57cfc64d" - integrity sha512-nRzLVMBk1L8aft6tVhK/ieDWa/rsRUzZzuclv94Mn1g0AJcqEqM0weziNIAfemdMIWpoZyhseJELD6pkWqQQeg== +"@standardnotes/common@^1.15.1": + version "1.15.1" + resolved "https://registry.yarnpkg.com/@standardnotes/common/-/common-1.15.1.tgz#e028ca719e9c4c1acbf8867be5f97599275c7490" + integrity sha512-OQTDsB+DatNyRplzx6SUasOTWFdwJZXkJkyDUr1rb1HnPz/VQpHYaQh5pRNHt7OHe002373rQZPAweHBlmEoDg== "@standardnotes/components@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.6.tgz#6dcce572b32580a6df9091422d96c9c0b6917174" integrity sha512-5lSYNKpO1tQRD6PMOs0IVTmPhfUh33+h6HQZdbWyCmjUk99QE86cI6IC8LnPh5rjHKG+jkfwgVzBKrR3QS/eQw== -"@standardnotes/domain-events@^2.23.15": - version "2.23.15" - resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.15.tgz#ce568fb5d30b220d49a70878efbc9bbee769bdf5" - integrity sha512-wJAoad9oXmAz39KZwYowiYny1dnHX/AJXdCdLwKxpJErh0h+VQhEhT2bPnqdIxJ90MTvn9jALhKM9AGlMEl+Aw== +"@standardnotes/domain-events@^2.23.17": + version "2.23.17" + resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.17.tgz#b2256ad7711003fb1790ac53548e8db37df38b4c" + integrity sha512-9qhQFydyi0ZNw2u2tAAp53Gbz1VLRwDX4S7FK4vT3sSoHTmkvkI354ETcgDBlZuIMZSo7AwthKu3wZTCz3jvMA== dependencies: - "@standardnotes/auth" "^3.16.5" - "@standardnotes/features" "^1.32.12" + "@standardnotes/auth" "^3.17.1" + "@standardnotes/features" "^1.33.1" -"@standardnotes/features@1.32.12", "@standardnotes/features@^1.32.12": - version "1.32.12" - resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.32.12.tgz#20b52fa5b0c7c29feea9d9ebb12a10f87cb7ec75" - integrity sha512-Xs5Ss8DWNLFWIMibFMO5GKGv/je7SAYr3lR6NvyQgKl4+bBxAVKqLgccWLodAXrNuOFoGAXBbG9R8PsFfYKlYw== +"@standardnotes/features@1.33.1", "@standardnotes/features@^1.33.1": + version "1.33.1" + resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.33.1.tgz#0269acf6672396cd7015b8df7f559f600de4dd08" + integrity sha512-TeZJ8nfaVMi1RGCNhGoXtzbhLuODf8fmceuMdZGMJYJEE6eEIr/YvqpDp1tYO/xCsvboZgRdwVmC7D5jPPmIwg== dependencies: - "@standardnotes/auth" "^3.16.5" - "@standardnotes/common" "^1.14.1" + "@standardnotes/auth" "^3.17.1" + "@standardnotes/common" "^1.15.1" -"@standardnotes/services@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.1.1.tgz#96065a8144c6f0d7695d7aedb0e10b8a9341a1b0" - integrity sha512-wM15yy3fjzlyVQWi0t9l0CZCSTMzBYQMrZBaBItSnN7P76zDa1MvQ9g7yWyC91nYGCgihI+nmDdArle88/4gWw== +"@standardnotes/payloads@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.1.2.tgz#6cb7819ab5fedc17d2e90a703015d0a46e350643" + integrity sha512-uV7cKkgP7eqfqyzvsd8r3t+DOGFkWIYNT8bGqYvTSrj+gjIGVSPhqL//oN1iUTvFUtcFTJHVLO2eirE2xcn/0A== dependencies: - "@standardnotes/common" "^1.14.1" - "@standardnotes/utils" "^1.1.2" + "@standardnotes/applications" "^1.1.1" + "@standardnotes/common" "^1.15.1" + "@standardnotes/features" "^1.33.1" + "@standardnotes/utils" "^1.2.1" + +"@standardnotes/services@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.2.1.tgz#7f1ddd3a16cd1c8dc43d3466fbe936a28d6d5eeb" + integrity sha512-b8Nw20SSg3Xr34hHoDQPxWNJ6Xgnswrjfg2paYPHXclP1Qwvo7OpiqdcjMntZ88UftvY1bFZJvqF1xrak7TJFA== + dependencies: + "@standardnotes/applications" "^1.1.1" + "@standardnotes/common" "^1.15.1" + "@standardnotes/utils" "^1.2.1" "@standardnotes/settings@^1.11.3": version "1.11.3" @@ -2427,19 +2445,21 @@ buffer "^6.0.3" libsodium-wrappers "^0.7.9" -"@standardnotes/snjs@2.63.5": - version "2.63.5" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.63.5.tgz#eb5fab274bc576a610033d894a3853f116a5e584" - integrity sha512-vhmqsRJn6UXJW1DK6jF0awTXEI/EYt1jzk7t5xpwLSThVM12LgPi/5u2KGPg1Ke7HHq2pejU/3AWNx7cbzXujw== +"@standardnotes/snjs@2.65.3": + version "2.65.3" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.65.3.tgz#a5a769c3aabb80623cd62e3f861a865c1f376bf8" + integrity sha512-5kCJ53IKwhdZ9/hWpwmBnJlQ5kVSvAtrqfOf23Y/wHBhBmqSbaME3WtwUcvDS+MNZ1DH2ikv/iGkElAC+aClVw== dependencies: - "@standardnotes/auth" "^3.16.5" - "@standardnotes/common" "^1.14.1" - "@standardnotes/domain-events" "^2.23.15" - "@standardnotes/features" "^1.32.12" - "@standardnotes/services" "^1.1.1" + "@standardnotes/applications" "^1.1.1" + "@standardnotes/auth" "^3.17.1" + "@standardnotes/common" "^1.15.1" + "@standardnotes/domain-events" "^2.23.17" + "@standardnotes/features" "^1.33.1" + "@standardnotes/payloads" "^1.1.2" + "@standardnotes/services" "^1.2.1" "@standardnotes/settings" "^1.11.3" "@standardnotes/sncrypto-common" "^1.7.1" - "@standardnotes/utils" "^1.1.2" + "@standardnotes/utils" "^1.2.1" "@standardnotes/stylekit@5.9.0": version "5.9.0" @@ -2451,12 +2471,12 @@ "@svgr/webpack" "^6.2.1" prop-types "^15.7.2" -"@standardnotes/utils@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@standardnotes/utils/-/utils-1.1.2.tgz#5bc1919a3a90c61a34354275d9129f71a23ee34d" - integrity sha512-D39U3S1XJIeLCRYnI98sBVWx0VcVYTfBNZTLU2K0ICRg2fvszQvyLRlFA4U7wf9x0QXsqVjORxAVcIiC5UoQPA== +"@standardnotes/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@standardnotes/utils/-/utils-1.2.1.tgz#226c679f5f91713c58f8ec0e837ea4586b234b3c" + integrity sha512-6lCzDsps9jh+CcgAeyPjwVaZG7VYCqKl5+Qp6mLUyFbqBIylg4ZW3VXvjjfw8DYY1LgHZtCTIHTuDdXCDuGm+w== dependencies: - "@standardnotes/common" "^1.14.1" + "@standardnotes/common" "^1.15.1" dompurify "^2.3.4" lodash "^4.17.19" @@ -2738,10 +2758,10 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== -"@types/lodash@^4.14.178": - version "4.14.178" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" - integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw== +"@types/lodash@^4.14.179": + version "4.14.179" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.179.tgz#490ec3288088c91295780237d2497a3aa9dfb5c5" + integrity sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w== "@types/mime@^1": version "1.3.2" @@ -4765,22 +4785,22 @@ eslint-plugin-react-hooks@^4.3.0: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== -eslint-plugin-react@^7.28.0: - version "7.28.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.28.0.tgz#8f3ff450677571a659ce76efc6d80b6a525adbdf" - integrity sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw== +eslint-plugin-react@^7.29.2: + version "7.29.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.2.tgz#2d4da69d30d0a736efd30890dc6826f3e91f3f7c" + integrity sha512-ypEBTKOy5liFQXZWMchJ3LN0JX1uPI6n7MN7OPHKacqXAxq5gYC30TdO7wqGYQyxD1OrzpobdHC3hDmlRWDg9w== dependencies: array-includes "^3.1.4" array.prototype.flatmap "^1.2.5" doctrine "^2.1.0" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.0.4" + minimatch "^3.1.2" object.entries "^1.1.5" object.fromentries "^2.0.5" object.hasown "^1.1.0" object.values "^1.1.5" - prop-types "^15.7.2" + prop-types "^15.8.1" resolve "^2.0.0-next.3" semver "^6.3.0" string.prototype.matchall "^4.0.6" @@ -4828,12 +4848,12 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.9.0.tgz#a2a8227a99599adc4342fd9b854cb8d8d6412fdb" - integrity sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q== +eslint@^8.10.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d" + integrity sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw== dependencies: - "@eslint/eslintrc" "^1.1.0" + "@eslint/eslintrc" "^1.2.0" "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" chalk "^4.0.0" @@ -7195,6 +7215,13 @@ minimatch@^3.0.4, minimatch@~3.0.2: dependencies: brace-expansion "^1.1.7" +minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -7287,10 +7314,10 @@ mobx-react-lite@^3.3.0: resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.3.0.tgz#7174e807201943beff6f9d3701492314c9fc0db3" integrity sha512-U/kMSFtV/bNVgY01FuiGWpRkaQVHozBq5CEBZltFvPt4FcV111hEWkgwqVg9GPPZSEuEdV438PEz8mk8mKpYlA== -mobx@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.4.1.tgz#c1d0eeb37ceb31bb2020a85f6bf856782d47fe60" - integrity sha512-NFXx0uMbGBgsa0uxhH099L8cMuoRQWh01q6Sf0ZX/3hFU7svJ7yfTD+1LnLMa5wzY/b7gImAeMsR1p0wordDnA== +mobx@^6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.4.2.tgz#d25cd358a46b7a8fe2d8299259bc71008a2aa5b3" + integrity sha512-b4xQJYiH8sb0sEbfq/Ws3N77DEJtSihUFD1moeiz2jNoJ5B+mqJutt54ouO9iEfkp7Wk4jQDsVUOh7DPEW3wEw== mri@^1.1.5: version "1.2.0" @@ -7968,6 +7995,15 @@ prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" +prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -8090,7 +8126,7 @@ react-focus-lock@^2.5.2: use-callback-ref "^1.2.5" use-sidecar "^1.0.5" -react-is@^16.7.0, react-is@^16.8.1: +react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== From 60bddd0f4159a1aa30ce74db462c6c0315e55674 Mon Sep 17 00:00:00 2001 From: Mo Date: Sun, 27 Feb 2022 17:46:55 -0600 Subject: [PATCH 11/17] feat: untagged notes smart view --- app/assets/javascripts/components/Icon.tsx | 4 +++- .../components/Tags/SmartViewsListItem.tsx | 4 ++++ package.json | 4 ++-- yarn.lock | 16 ++++++++-------- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/components/Icon.tsx b/app/assets/javascripts/components/Icon.tsx index 440f1f450..831dd5dca 100644 --- a/app/assets/javascripts/components/Icon.tsx +++ b/app/assets/javascripts/components/Icon.tsx @@ -26,6 +26,7 @@ import { EyeIcon, EyeOffIcon, HashtagIcon, + HashtagOffIcon, HelpIcon, HistoryIcon, InfoIcon, @@ -85,6 +86,7 @@ const ICONS = { 'chevron-right': ChevronRightIcon, 'cloud-off': CloudOffIcon, 'eye-off': EyeOffIcon, + 'hashtag-off': HashtagOffIcon, 'link-off': LinkOffIcon, 'list-bulleted': ListBulleted, 'lock-filled': LockFilledIcon, @@ -92,8 +94,8 @@ const ICONS = { 'menu-arrow-down': MenuArrowDownIcon, 'menu-arrow-right': MenuArrowRight, 'menu-close': MenuCloseIcon, - 'pencil-off': PencilOffIcon, 'pencil-filled': PencilFilledIcon, + 'pencil-off': PencilOffIcon, 'pin-filled': PinFilledIcon, 'plain-text': PlainTextIcon, 'premium-feature': PremiumFeatureIcon, diff --git a/app/assets/javascripts/components/Tags/SmartViewsListItem.tsx b/app/assets/javascripts/components/Tags/SmartViewsListItem.tsx index cb52f78cc..841c7c540 100644 --- a/app/assets/javascripts/components/Tags/SmartViewsListItem.tsx +++ b/app/assets/javascripts/components/Tags/SmartViewsListItem.tsx @@ -31,6 +31,10 @@ const smartViewIconType = (view: SmartView): IconType => { if (view.uuid === SystemViewId.TrashedNotes) { return 'trash'; } + if (view.uuid === SystemViewId.UntaggedNotes) { + return 'hashtag-off'; + } + return 'hashtag'; }; diff --git a/package.json b/package.json index e5cf44306..7d68cd75d 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "pretty-quick": "^3.1.3", "sass-loader": "^12.6.0", "serve-static": "^1.14.2", - "@standardnotes/stylekit": "5.9.0", + "@standardnotes/stylekit": "5.10.0", "svg-jest": "^1.0.1", "ts-jest": "^27.1.3", "ts-loader": "^9.2.6", @@ -78,7 +78,7 @@ "@reach/tooltip": "^0.16.2", "@standardnotes/components": "1.7.6", "@standardnotes/features": "1.33.1", - "@standardnotes/snjs": "2.65.3", + "@standardnotes/snjs": "2.66.0", "@standardnotes/settings": "^1.11.3", "@standardnotes/sncrypto-web": "1.7.1", "mobx": "^6.4.2", diff --git a/yarn.lock b/yarn.lock index 462ccdce8..60861a5bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2445,10 +2445,10 @@ buffer "^6.0.3" libsodium-wrappers "^0.7.9" -"@standardnotes/snjs@2.65.3": - version "2.65.3" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.65.3.tgz#a5a769c3aabb80623cd62e3f861a865c1f376bf8" - integrity sha512-5kCJ53IKwhdZ9/hWpwmBnJlQ5kVSvAtrqfOf23Y/wHBhBmqSbaME3WtwUcvDS+MNZ1DH2ikv/iGkElAC+aClVw== +"@standardnotes/snjs@2.66.0": + version "2.66.0" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.66.0.tgz#ae4dd3def15e6e093bf9f39a677f67b98ca9685a" + integrity sha512-/sJ/9+a/ADhA77/k11liW1NlVkWhiT833euo/uhFDv/lfiZB512w/8Y3pfUrYGBQewBOPV1IqsXk4FH/eiz/GQ== dependencies: "@standardnotes/applications" "^1.1.1" "@standardnotes/auth" "^3.17.1" @@ -2461,10 +2461,10 @@ "@standardnotes/sncrypto-common" "^1.7.1" "@standardnotes/utils" "^1.2.1" -"@standardnotes/stylekit@5.9.0": - version "5.9.0" - resolved "https://registry.yarnpkg.com/@standardnotes/stylekit/-/stylekit-5.9.0.tgz#16d62623335091062238c850a930dedaa5ad6f1d" - integrity sha512-lIlEKwxKkQT+AttSmN40zvzWzfqpfI4VPTscZvRnWRqMQjYDEnSbcA1h0UDcT5tvnrna4RtsOiUL9o0KDx56sg== +"@standardnotes/stylekit@5.10.0": + version "5.10.0" + resolved "https://registry.yarnpkg.com/@standardnotes/stylekit/-/stylekit-5.10.0.tgz#94bc1c6686663b2b89b004eb777a6792a0305f47" + integrity sha512-W0vuqjfN1GD254ZTdlroMgKIQSebuhkJkc5Lh0tWQ5cpQyXrZ3HsHXd3H98PPbP+wtLS34XS5G/PHc7OjD146g== dependencies: "@reach/listbox" "^0.15.0" "@reach/menu-button" "^0.15.1" From c184ef2449044982ff27f162807f916fd16cce4a Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Wed, 2 Mar 2022 18:30:10 +0530 Subject: [PATCH 12/17] fix: first history entry being fetched twice (#903) --- .../RevisionHistoryModal/HistoryListContainer.tsx | 3 --- .../RevisionHistoryModal/LegacyHistoryList.tsx | 10 ---------- .../RevisionHistoryModal/RemoteHistoryList.tsx | 10 ---------- .../RevisionHistoryModal/SessionHistoryList.tsx | 10 ---------- 4 files changed, 33 deletions(-) diff --git a/app/assets/javascripts/components/RevisionHistoryModal/HistoryListContainer.tsx b/app/assets/javascripts/components/RevisionHistoryModal/HistoryListContainer.tsx index 8aafed274..71f07b5ec 100644 --- a/app/assets/javascripts/components/RevisionHistoryModal/HistoryListContainer.tsx +++ b/app/assets/javascripts/components/RevisionHistoryModal/HistoryListContainer.tsx @@ -202,7 +202,6 @@ export const HistoryListContainer: FunctionComponent = observer(
{selectedTab === RevisionListTabType.Session && ( = observer( remoteHistory={remoteHistory} isFetchingRemoteHistory={isFetchingRemoteHistory} fetchAndSetRemoteRevision={fetchAndSetRemoteRevision} - selectedTab={selectedTab} /> )} {selectedTab === RevisionListTabType.Legacy && ( = ({ legacyHistory, - selectedTab, setSelectedRevision, setSelectedRemoteEntry, fetchAndSetLegacyRevision, @@ -56,13 +53,6 @@ export const LegacyHistoryList: FunctionComponent = ({ } }, [firstEntry, selectFirstEntry, selectedItemUrl, setSelectedRevision]); - useEffect(() => { - if (selectedTab === RevisionListTabType.Legacy) { - selectFirstEntry(); - legacyHistoryListRef.current?.focus(); - } - }, [selectFirstEntry, selectedTab]); - return (
Promise; - selectedTab: RevisionListTabType; }; export const RemoteHistoryList: FunctionComponent = @@ -32,7 +30,6 @@ export const RemoteHistoryList: FunctionComponent = remoteHistory, isFetchingRemoteHistory, fetchAndSetRemoteRevision, - selectedTab, }) => { const remoteHistoryListRef = useRef(null); @@ -69,13 +66,6 @@ export const RemoteHistoryList: FunctionComponent = selectedEntryUuid.length, ]); - useEffect(() => { - if (selectedTab === RevisionListTabType.Remote) { - selectFirstEntry(); - remoteHistoryListRef.current?.focus(); - } - }, [selectFirstEntry, selectedTab]); - return (
[]; setSelectedRevision: StateUpdater< HistoryEntry | LegacyHistoryEntry | undefined @@ -28,7 +26,6 @@ type Props = { export const SessionHistoryList: FunctionComponent = ({ sessionHistory, - selectedTab, setSelectedRevision, setSelectedRemoteEntry, }) => { @@ -67,13 +64,6 @@ export const SessionHistoryList: FunctionComponent = ({ setSelectedRevision, ]); - useEffect(() => { - if (selectedTab === RevisionListTabType.Session) { - selectFirstEntry(); - sessionHistoryListRef.current?.focus(); - } - }, [selectFirstEntry, selectedTab]); - return (
Date: Wed, 2 Mar 2022 19:43:52 +0530 Subject: [PATCH 13/17] feat: show sign-in/sign-up errors under input instead of alert (#904) --- .../AccountMenu/ConfirmPassword.tsx | 28 +++++++++---------- .../components/AccountMenu/CreateAccount.tsx | 6 ++-- .../components/AccountMenu/SignIn.tsx | 26 ++++++----------- .../components/AccountMenu/index.tsx | 1 - 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/app/assets/javascripts/components/AccountMenu/ConfirmPassword.tsx b/app/assets/javascripts/components/AccountMenu/ConfirmPassword.tsx index b4d780545..25dd2c317 100644 --- a/app/assets/javascripts/components/AccountMenu/ConfirmPassword.tsx +++ b/app/assets/javascripts/components/AccountMenu/ConfirmPassword.tsx @@ -3,7 +3,7 @@ import { WebApplication } from '@/ui_models/application'; import { AppState } from '@/ui_models/app_state'; import { observer } from 'mobx-react-lite'; import { FunctionComponent } from 'preact'; -import { StateUpdater, useEffect, useRef, useState } from 'preact/hooks'; +import { useEffect, useRef, useState } from 'preact/hooks'; import { AccountMenuPane } from '.'; import { Button } from '../Button'; import { Checkbox } from '../Checkbox'; @@ -17,22 +17,22 @@ type Props = { setMenuPane: (pane: AccountMenuPane) => void; email: string; password: string; - setPassword: StateUpdater; }; export const ConfirmPassword: FunctionComponent = observer( - ({ application, appState, setMenuPane, email, password, setPassword }) => { + ({ application, appState, setMenuPane, email, password }) => { const { notesAndTagsCount } = appState.accountMenu; const [confirmPassword, setConfirmPassword] = useState(''); const [showPassword, setShowPassword] = useState(false); const [isRegistering, setIsRegistering] = useState(false); const [isEphemeral, setIsEphemeral] = useState(false); const [shouldMergeLocal, setShouldMergeLocal] = useState(true); + const [error, setError] = useState(''); const passwordInputRef = useRef(null); useEffect(() => { - passwordInputRef?.current?.focus(); + passwordInputRef.current?.focus(); }, []); const handlePasswordChange = (e: Event) => { @@ -50,6 +50,9 @@ export const ConfirmPassword: FunctionComponent = observer( }; const handleKeyDown = (e: KeyboardEvent) => { + if (error.length) { + setError(''); + } if (e.key === 'Enter') { handleConfirmFormSubmit(e); } @@ -59,7 +62,7 @@ export const ConfirmPassword: FunctionComponent = observer( e.preventDefault(); if (!password) { - passwordInputRef?.current!.focus(); + passwordInputRef.current?.focus(); return; } @@ -76,21 +79,15 @@ export const ConfirmPassword: FunctionComponent = observer( }) .catch((err) => { console.error(err); - application.alertService.alert(err).finally(() => { - setPassword(''); - handleGoBack(); - }); + setError(err.message); }) .finally(() => { setIsRegistering(false); }); } else { - application.alertService - .alert(STRING_NON_MATCHING_PASSWORDS) - .finally(() => { - setConfirmPassword(''); - passwordInputRef?.current!.focus(); - }); + setError(STRING_NON_MATCHING_PASSWORDS); + setConfirmPassword(''); + passwordInputRef.current?.focus(); } }; @@ -138,6 +135,7 @@ export const ConfirmPassword: FunctionComponent = observer( ref={passwordInputRef} disabled={isRegistering} /> + {error ?
{error}
: null}
= observer( ref={emailInputRef} /> = observer( }} ref={passwordInputRef} /> - {isInvalid ? ( -
- Invalid email or password. -
- ) : null} + {error ?
{error}
: null}
diff --git a/app/assets/javascripts/typings/stylekit.d.ts b/app/assets/javascripts/typings/stylekit.d.ts deleted file mode 100644 index 44b004f93..000000000 --- a/app/assets/javascripts/typings/stylekit.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module '@standardnotes/stylekit'; diff --git a/app/assets/stylesheets/_sn.scss b/app/assets/stylesheets/_sn.scss index 29094ef70..4c2fc3caa 100644 --- a/app/assets/stylesheets/_sn.scss +++ b/app/assets/stylesheets/_sn.scss @@ -32,22 +32,6 @@ text-decoration: underline; } -.sn-icon { - @extend .h-5; - @extend .w-5; - @extend .fill-current; - - &.sn-icon--small { - @extend .h-3\.5; - @extend .w-3\.5; - } - - &.sn-icon--mid { - @extend .w-4; - @extend .h-4; - } -} - .sn-dropdown { @extend .bg-default; @extend .rounded; @@ -257,9 +241,6 @@ .ml-3 { margin-left: 0.75rem; } -.ml-4 { - margin-left: 1rem; -} .mr-2\.5 { margin-right: 0.625rem; @@ -583,10 +564,6 @@ padding-bottom: 2.25rem; } -.select-none { - user-select: none; -} - .placeholder-dark-red::placeholder { @extend .color-dark-red; } @@ -719,11 +696,6 @@ background: var(--sn-stylekit-grey-4); } -.sn-component .spinner-info { - border-color: var(--sn-stylekit-info-color); - border-right-color: transparent; -} - @keyframes slide-up { 0% { opacity: 1; @@ -907,10 +879,6 @@ } } -.flex-shrink-0 { - flex-shrink: 0; -} - .leading-140\% { line-height: 140%; } @@ -921,10 +889,6 @@ pointer-events: none; } -.flex-shrink-0 { - flex-shrink: 0; -} - .last\:hidden:last-child { display: none; } diff --git a/app/assets/stylesheets/_ui.scss b/app/assets/stylesheets/_ui.scss index c2e8fab59..155cc39fb 100644 --- a/app/assets/stylesheets/_ui.scss +++ b/app/assets/stylesheets/_ui.scss @@ -210,10 +210,6 @@ $screen-md-max: ($screen-lg-min - 1) !default; pointer-events: none; } -.fill-current { - fill: currentColor; -} - .font-editor { font-family: var(--sn-stylekit-editor-font-family); } diff --git a/package.json b/package.json index 7d68cd75d..067e82e77 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "pretty-quick": "^3.1.3", "sass-loader": "^12.6.0", "serve-static": "^1.14.2", - "@standardnotes/stylekit": "5.10.0", + "@standardnotes/stylekit": "5.12.2", "svg-jest": "^1.0.1", "ts-jest": "^27.1.3", "ts-loader": "^9.2.6", diff --git a/yarn.lock b/yarn.lock index 60861a5bb..f0c49f25a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2052,6 +2052,11 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@nanostores/preact@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@nanostores/preact/-/preact-0.1.3.tgz#aeac0a1d8de1e067bc0b156c1fdd62a6b7bf6069" + integrity sha512-uiX1ned0LrzASot+sPUjyJzr8Js3pX075omazgsSdLf0zPp4ss8xwTiuNh5FSKigTSQEVqZFiS+W8CnHIrX62A== + "@nodelib/fs.scandir@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" @@ -2111,14 +2116,6 @@ prop-types "^15.7.2" tslib "^2.3.0" -"@reach/auto-id@0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.15.2.tgz#289640b47545a32f3621469ba497ba5c040b349c" - integrity sha512-K7d5qhYBlBHIjy+IpSEAyMeB5VTZ9m0tZdr7xyNd5Fr6oeefHEvJiJGuQpubP5bDoe7ShC3y0VQGFmT0g7KcZg== - dependencies: - "@reach/utils" "0.15.2" - tslib "^2.3.0" - "@reach/auto-id@0.16.0": version "0.16.0" resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.16.0.tgz#dfabc3227844e8c04f8e6e45203a8e14a8edbaed" @@ -2139,14 +2136,6 @@ tiny-warning "^1.0.3" tslib "^2.3.0" -"@reach/descendants@0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@reach/descendants/-/descendants-0.15.2.tgz#b0641f0bc864d91271364678dea51cf86b2e5c66" - integrity sha512-GdQXWVpscss89MOhWh+sL4TnIn0qX1y+Te3wE72aKQrz/QCR69JFEW4wftovmF7rFm4/kDZcp14lMy512U6VlA== - dependencies: - "@reach/utils" "0.15.2" - tslib "^2.3.0" - "@reach/descendants@0.16.1": version "0.16.1" resolved "https://registry.yarnpkg.com/@reach/descendants/-/descendants-0.16.1.tgz#fa3d89c0503565369707f32985d87eef61985d9f" @@ -2178,17 +2167,16 @@ tiny-warning "^1.0.3" tslib "^2.3.0" -"@reach/listbox@^0.15.0": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@reach/listbox/-/listbox-0.15.2.tgz#21aacc5340deb1b819d522f7f7fd4caac093c8a4" - integrity sha512-bXXelcm+PvAWAmhHQEaEVU6IQvTieIdoYcIrs5JsKzH98M+pp940Gdm0d2uDcmFatx/I9OMTAsOTJ129RPECrA== +"@reach/dropdown@0.16.2": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@reach/dropdown/-/dropdown-0.16.2.tgz#4aa7df0f716cb448d01bc020d54df595303d5fa6" + integrity sha512-l4nNiX6iUpMdHQNbZMhgW5APtw0AUwJuRnkqE93vkjvdtrYl/sNJy1Jr6cGG7TrZIABLSOsfwbXU3C+qwJ3ftQ== dependencies: - "@reach/auto-id" "0.15.2" - "@reach/descendants" "0.15.2" - "@reach/machine" "0.15.2" - "@reach/popover" "0.15.2" - "@reach/utils" "0.15.2" - prop-types "^15.7.2" + "@reach/auto-id" "0.16.0" + "@reach/descendants" "0.16.1" + "@reach/popover" "0.16.2" + "@reach/utils" "0.16.0" + tslib "^2.3.0" "@reach/listbox@^0.16.2": version "0.16.2" @@ -2202,15 +2190,6 @@ "@reach/utils" "0.16.0" prop-types "^15.7.2" -"@reach/machine@0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@reach/machine/-/machine-0.15.2.tgz#f1558e63a6b304e6cc12feefb0d0dd315b32c962" - integrity sha512-op8Duhp6rNCReZgdVScbIzoXMPFYP4nje6dvg4g2GKo8hUkyQpebsUFnUNNNv6NWdbmhIRiKHFlTgSl2gIlh5Q== - dependencies: - "@reach/utils" "0.15.2" - "@xstate/fsm" "1.4.0" - tslib "^2.3.0" - "@reach/machine@0.16.0": version "0.16.0" resolved "https://registry.yarnpkg.com/@reach/machine/-/machine-0.16.0.tgz#0504ba47ac09ed495bd341bf5fdd6625bcade0e3" @@ -2220,15 +2199,14 @@ "@xstate/fsm" "1.4.0" tslib "^2.3.0" -"@reach/menu-button@^0.15.1": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.15.2.tgz#00f91402be3ff23d3b4cfe377529f4f9e82a78fe" - integrity sha512-slEji1AnfnH134YDZSTwst4nZHYNrfyg9GF+A8p1+kGc8N3JsPysHc7uIUZ/IsK+PdaOCB+r9kuL1QWBgNO+jw== +"@reach/menu-button@^0.16.2": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.16.2.tgz#664e33e70de431f88abf1f8537c48b1b6ce87e88" + integrity sha512-p4n6tFVaJZHJZEznHWy0YH2Xr3I+W7tsQWAT72PqKGT+uryGRdtgEQqi76f/8cRaw/00ueazBk5lwLG7UKGFaA== dependencies: - "@reach/auto-id" "0.15.2" - "@reach/descendants" "0.15.2" - "@reach/popover" "0.15.2" - "@reach/utils" "0.15.2" + "@reach/dropdown" "0.16.2" + "@reach/popover" "0.16.2" + "@reach/utils" "0.16.0" prop-types "^15.7.2" tiny-warning "^1.0.3" tslib "^2.3.0" @@ -2238,17 +2216,6 @@ resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2" integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ== -"@reach/popover@0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@reach/popover/-/popover-0.15.2.tgz#e310e2afe82afa35929354f1fd1a747cdebb7654" - integrity sha512-92Ov7VPXjn4ciOVupeekki03lSMz9NAmw2BjWYE9mVvYWKyDx5jx2srtbkIqUaSCkAVV3KEsFUia8aMm60FDZg== - dependencies: - "@reach/portal" "0.15.2" - "@reach/rect" "0.15.2" - "@reach/utils" "0.15.2" - tabbable "^4.0.0" - tslib "^2.3.0" - "@reach/popover@0.16.2": version "0.16.2" resolved "https://registry.yarnpkg.com/@reach/popover/-/popover-0.16.2.tgz#71d7af3002ca49d791476b22dee1840dd1719c19" @@ -2260,14 +2227,6 @@ tabbable "^4.0.0" tslib "^2.3.0" -"@reach/portal@0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.15.2.tgz#fe7aa3d9a475ec07686c39bab3a0d85093fa91fb" - integrity sha512-5x+dchGr4btRnLazwmyCYbSPVJAIrw0eXwhz7Vj9uT/EIp43WzOtTcODdLOoH6Ol2QLjX1Yt/fBjdK9+UAKxSA== - dependencies: - "@reach/utils" "0.15.2" - tslib "^2.3.0" - "@reach/portal@0.16.2": version "0.16.2" resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.16.2.tgz#ca83696215ee03acc2bb25a5ae5d8793eaaf2f64" @@ -2277,17 +2236,6 @@ tiny-warning "^1.0.3" tslib "^2.3.0" -"@reach/rect@0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.15.2.tgz#734e3f17a499d6e22bd2ea95856c801c41ed66fd" - integrity sha512-S2lzvvfclUHdvgcfW/eoz0i729HJvG5f6ayVaXcKz+X6LKF9i9Jdhfwsz7b3UmnSCihKNs0cX5tyWfWr1E1JFw== - dependencies: - "@reach/observe-rect" "1.2.0" - "@reach/utils" "0.15.2" - prop-types "^15.7.2" - tiny-warning "^1.0.3" - tslib "^2.3.0" - "@reach/rect@0.16.0": version "0.16.0" resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.16.0.tgz#78cf6acefe2e83d3957fa84f938f6e1fc5700f16" @@ -2313,14 +2261,6 @@ tiny-warning "^1.0.3" tslib "^2.3.0" -"@reach/utils@0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.15.2.tgz#a63a761eb36266bf33d65cb91520dd85a04ae116" - integrity sha512-Lr1SJ5X4hEjD/M0TAonURM8wytM/JuPSuIP7t+e5cil34pThyLsBvTGeNfmpSgaLJ5vlsv0x9u6g4SRAEr84Og== - dependencies: - tiny-warning "^1.0.3" - tslib "^2.3.0" - "@reach/utils@0.16.0": version "0.16.0" resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.16.0.tgz#5b0777cf16a7cab1ddd4728d5d02762df0ba84ce" @@ -2461,15 +2401,18 @@ "@standardnotes/sncrypto-common" "^1.7.1" "@standardnotes/utils" "^1.2.1" -"@standardnotes/stylekit@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@standardnotes/stylekit/-/stylekit-5.10.0.tgz#94bc1c6686663b2b89b004eb777a6792a0305f47" - integrity sha512-W0vuqjfN1GD254ZTdlroMgKIQSebuhkJkc5Lh0tWQ5cpQyXrZ3HsHXd3H98PPbP+wtLS34XS5G/PHc7OjD146g== +"@standardnotes/stylekit@5.12.2": + version "5.12.2" + resolved "https://registry.yarnpkg.com/@standardnotes/stylekit/-/stylekit-5.12.2.tgz#8c2bea39aa696d27a3b88ef68c182638f9c72615" + integrity sha512-pa30xiil1ZQoXZetWdOhABIfOTkuhlSqdi2LAmJ7SkfiCclqsGGvOSf8z2R2V8DP5B7R2kYH6ko11CBGAhwjqA== dependencies: - "@reach/listbox" "^0.15.0" - "@reach/menu-button" "^0.15.1" + "@nanostores/preact" "^0.1.3" + "@reach/listbox" "^0.16.2" + "@reach/menu-button" "^0.16.2" "@svgr/webpack" "^6.2.1" - prop-types "^15.7.2" + nanoid "^3.3.1" + nanostores "^0.5.10" + prop-types "^15.8.1" "@standardnotes/utils@^1.2.1": version "1.2.1" @@ -7373,11 +7316,16 @@ nan@^2.13.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== -nanoid@^3.2.0: +nanoid@^3.2.0, nanoid@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== +nanostores@^0.5.10: + version "0.5.10" + resolved "https://registry.yarnpkg.com/nanostores/-/nanostores-0.5.10.tgz#16488776f01fa288b09c026400ff535da55c3583" + integrity sha512-8Y7C8sF8PsHGpLVJochWT+ytEY34XrNRDA30hDqgvLcl5Ih4d/IFb7gUSFIwmgFAaht1pLwKZHTeFoJrNz88RQ== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" From d8caa31dc9357587da00b1ad30b286107a9d7f20 Mon Sep 17 00:00:00 2001 From: Mo Date: Thu, 3 Mar 2022 13:31:51 -0600 Subject: [PATCH 15/17] chore: upgrade deps (#906) * chore: upgrade deps * fix: MenuArrowRight import * fix: type naming --- .../components/AccountMenu/User.tsx | 23 +- app/assets/javascripts/components/Icon.tsx | 4 +- .../changeEditor/createEditorMenuGroups.ts | 2 +- .../QuickSettingsMenu/FocusModeSwitch.tsx | 2 +- .../QuickSettingsMenu/ThemesMenuButton.tsx | 5 +- .../HistoryListContainer.tsx | 4 +- .../RemoteHistoryList.tsx | 6 +- .../preferences/panes/Appearance.tsx | 2 +- .../preferences/panes/Extensions.tsx | 2 +- .../panes/account/offlineSubscription.tsx | 14 +- .../panes/backups-segments/EmailBackups.tsx | 2 +- .../backups-segments/cloud-backups/index.tsx | 6 +- .../extensions-segments/ExtensionItem.tsx | 4 +- .../javascripts/services/alertService.ts | 1 + .../javascripts/services/desktopManager.ts | 3 +- .../javascripts/services/themeManager.ts | 9 +- .../ui_models/app_state/features_state.ts | 4 +- .../ui_models/application_group.ts | 6 +- package.json | 26 +- yarn.lock | 321 ++++++++++-------- 20 files changed, 239 insertions(+), 207 deletions(-) diff --git a/app/assets/javascripts/components/AccountMenu/User.tsx b/app/assets/javascripts/components/AccountMenu/User.tsx index 1dc2b2af4..68f49df1e 100644 --- a/app/assets/javascripts/components/AccountMenu/User.tsx +++ b/app/assets/javascripts/components/AccountMenu/User.tsx @@ -1,19 +1,16 @@ import { observer } from 'mobx-react-lite'; import { AppState } from '@/ui_models/app_state'; import { WebApplication } from '@/ui_models/application'; -import { User } from '@standardnotes/snjs/dist/@types/services/api/responses'; +import { User as UserType } from '@standardnotes/responses'; type Props = { appState: AppState; application: WebApplication; -} +}; -const User = observer(({ - appState, - application, -}: Props) => { +const User = observer(({ appState, application }: Props) => { const { server } = appState.accountMenu; - const user = application.getUser(); + const user = application.getUser() as UserType; return (
@@ -21,8 +18,8 @@ const User = observer(({
Sync Unreachable
- Hmm...we can't seem to sync your account. - The reason: {appState.sync.errorMessage} + Hmm...we can't seem to sync your account. The reason:{' '} + {appState.sync.errorMessage}
-
- {(user as User).email} -
-
- {server} -
+
{user.email}
+
{server}
diff --git a/app/assets/javascripts/components/Icon.tsx b/app/assets/javascripts/components/Icon.tsx index 831dd5dca..196a63e45 100644 --- a/app/assets/javascripts/components/Icon.tsx +++ b/app/assets/javascripts/components/Icon.tsx @@ -39,7 +39,7 @@ import { MarkdownIcon, MenuArrowDownAlt, MenuArrowDownIcon, - MenuArrowRight, + MenuArrowRightIcon, MenuCloseIcon, MoreIcon, NotesIcon, @@ -92,7 +92,7 @@ const ICONS = { 'lock-filled': LockFilledIcon, 'menu-arrow-down-alt': MenuArrowDownAlt, 'menu-arrow-down': MenuArrowDownIcon, - 'menu-arrow-right': MenuArrowRight, + 'menu-arrow-right': MenuArrowRightIcon, 'menu-close': MenuCloseIcon, 'pencil-filled': PencilFilledIcon, 'pencil-off': PencilOffIcon, diff --git a/app/assets/javascripts/components/NotesOptions/changeEditor/createEditorMenuGroups.ts b/app/assets/javascripts/components/NotesOptions/changeEditor/createEditorMenuGroups.ts index 2a9b16907..c2a56e096 100644 --- a/app/assets/javascripts/components/NotesOptions/changeEditor/createEditorMenuGroups.ts +++ b/app/assets/javascripts/components/NotesOptions/changeEditor/createEditorMenuGroups.ts @@ -76,7 +76,7 @@ export const createEditorMenuGroups = ( name: editor.name, component: editor, isEntitled: - application.getFeatureStatus(editor.identifier) === + application.features.getFeatureStatus(editor.identifier) === FeatureStatus.Entitled, }; diff --git a/app/assets/javascripts/components/QuickSettingsMenu/FocusModeSwitch.tsx b/app/assets/javascripts/components/QuickSettingsMenu/FocusModeSwitch.tsx index 102e07776..7d38f1c16 100644 --- a/app/assets/javascripts/components/QuickSettingsMenu/FocusModeSwitch.tsx +++ b/app/assets/javascripts/components/QuickSettingsMenu/FocusModeSwitch.tsx @@ -22,7 +22,7 @@ export const FocusModeSwitch: FunctionComponent = ({ }) => { const premiumModal = usePremiumModal(); const isEntitled = - application.getFeatureStatus(FeatureIdentifier.FocusMode) === + application.features.getFeatureStatus(FeatureIdentifier.FocusMode) === FeatureStatus.Entitled; const toggle = useCallback( diff --git a/app/assets/javascripts/components/QuickSettingsMenu/ThemesMenuButton.tsx b/app/assets/javascripts/components/QuickSettingsMenu/ThemesMenuButton.tsx index b874aa1b2..57859bb43 100644 --- a/app/assets/javascripts/components/QuickSettingsMenu/ThemesMenuButton.tsx +++ b/app/assets/javascripts/components/QuickSettingsMenu/ThemesMenuButton.tsx @@ -22,12 +22,13 @@ export const ThemesMenuButton: FunctionComponent = ({ const premiumModal = usePremiumModal(); const isThirdPartyTheme = useMemo( - () => application.isThirdPartyFeature(item.identifier), + () => application.features.isThirdPartyFeature(item.identifier), [application, item.identifier] ); const isEntitledToTheme = useMemo( () => - application.getFeatureStatus(item.identifier) === FeatureStatus.Entitled, + application.features.getFeatureStatus(item.identifier) === + FeatureStatus.Entitled, [application, item.identifier] ); const canActivateTheme = useMemo( diff --git a/app/assets/javascripts/components/RevisionHistoryModal/HistoryListContainer.tsx b/app/assets/javascripts/components/RevisionHistoryModal/HistoryListContainer.tsx index 71f07b5ec..55748187a 100644 --- a/app/assets/javascripts/components/RevisionHistoryModal/HistoryListContainer.tsx +++ b/app/assets/javascripts/components/RevisionHistoryModal/HistoryListContainer.tsx @@ -155,7 +155,9 @@ export const HistoryListContainer: FunctionComponent = observer( async (revisionListEntry: RevisionListEntry) => { setShowContentLockedScreen(false); - if (application.hasMinimumRole(revisionListEntry.required_role)) { + if ( + application.features.hasMinimumRole(revisionListEntry.required_role) + ) { setIsFetchingSelectedRevision(true); setSelectedRevision(undefined); setSelectedRemoteEntry(undefined); diff --git a/app/assets/javascripts/components/RevisionHistoryModal/RemoteHistoryList.tsx b/app/assets/javascripts/components/RevisionHistoryModal/RemoteHistoryList.tsx index c02bbaf4b..9399099ba 100644 --- a/app/assets/javascripts/components/RevisionHistoryModal/RemoteHistoryList.tsx +++ b/app/assets/javascripts/components/RevisionHistoryModal/RemoteHistoryList.tsx @@ -95,9 +95,9 @@ export const RemoteHistoryList: FunctionComponent = >
{previewHistoryEntryTitle(entry)}
- {!application.hasMinimumRole(entry.required_role) && ( - - )} + {!application.features.hasMinimumRole( + entry.required_role + ) && }
))} diff --git a/app/assets/javascripts/preferences/panes/Appearance.tsx b/app/assets/javascripts/preferences/panes/Appearance.tsx index 85c7f56ce..854c66fdc 100644 --- a/app/assets/javascripts/preferences/panes/Appearance.tsx +++ b/app/assets/javascripts/preferences/panes/Appearance.tsx @@ -32,7 +32,7 @@ export const Appearance: FunctionComponent = observer( ({ application }) => { const premiumModal = usePremiumModal(); const isEntitledToMidnightTheme = - application.getFeatureStatus(FeatureIdentifier.MidnightTheme) === + application.features.getFeatureStatus(FeatureIdentifier.MidnightTheme) === FeatureStatus.Entitled; const [themeItems, setThemeItems] = useState([]); diff --git a/app/assets/javascripts/preferences/panes/Extensions.tsx b/app/assets/javascripts/preferences/panes/Extensions.tsx index ae8f6756c..b70f06e73 100644 --- a/app/assets/javascripts/preferences/panes/Extensions.tsx +++ b/app/assets/javascripts/preferences/panes/Extensions.tsx @@ -58,7 +58,7 @@ export const Extensions: FunctionComponent<{ }; const submitExtensionUrl = async (url: string) => { - const component = await application.downloadExternalFeature(url); + const component = await application.features.downloadExternalFeature(url); if (component) { setConfirmableExtension(component); } diff --git a/app/assets/javascripts/preferences/panes/account/offlineSubscription.tsx b/app/assets/javascripts/preferences/panes/account/offlineSubscription.tsx index 5744600c3..7d9e83f9e 100644 --- a/app/assets/javascripts/preferences/panes/account/offlineSubscription.tsx +++ b/app/assets/javascripts/preferences/panes/account/offlineSubscription.tsx @@ -27,15 +27,17 @@ export const OfflineSubscription: FunctionalComponent = observer( useState(false); useEffect(() => { - if (application.hasOfflineRepo()) { + if (application.features.hasOfflineRepo()) { setHasUserPreviouslyStoredCode(true); } }, [application]); const shouldShowOfflineSubscription = () => { - return !application.hasAccount() || + return ( + !application.hasAccount() || application.isThirdPartyHostUsed() || - hasUserPreviouslyStoredCode; + hasUserPreviouslyStoredCode + ); }; const handleSubscriptionCodeSubmit = async ( @@ -43,7 +45,9 @@ export const OfflineSubscription: FunctionalComponent = observer( ) => { event.preventDefault(); - const result = await application.setOfflineFeaturesCode(activationCode); + const result = await application.features.setOfflineFeaturesCode( + activationCode + ); if (result?.error) { await application.alertService.alert(result.error); @@ -55,7 +59,7 @@ export const OfflineSubscription: FunctionalComponent = observer( }; const handleRemoveOfflineKey = async () => { - await application.deleteOfflineFeatureRepo(); + await application.features.deleteOfflineFeatureRepo(); setIsSuccessfullyActivated(false); setHasUserPreviouslyStoredCode(false); diff --git a/app/assets/javascripts/preferences/panes/backups-segments/EmailBackups.tsx b/app/assets/javascripts/preferences/panes/backups-segments/EmailBackups.tsx index 804e0d98b..edc124389 100644 --- a/app/assets/javascripts/preferences/panes/backups-segments/EmailBackups.tsx +++ b/app/assets/javascripts/preferences/panes/backups-segments/EmailBackups.tsx @@ -62,7 +62,7 @@ export const EmailBackups = observer(({ application }: Props) => { }, [application]); useEffect(() => { - const emailBackupsFeatureStatus = application.getFeatureStatus( + const emailBackupsFeatureStatus = application.features.getFeatureStatus( FeatureIdentifier.DailyEmailBackup ); setIsEntitledToEmailBackups( diff --git a/app/assets/javascripts/preferences/panes/backups-segments/cloud-backups/index.tsx b/app/assets/javascripts/preferences/panes/backups-segments/cloud-backups/index.tsx index 65f768e8f..7ac3e6fd7 100644 --- a/app/assets/javascripts/preferences/panes/backups-segments/cloud-backups/index.tsx +++ b/app/assets/javascripts/preferences/panes/backups-segments/cloud-backups/index.tsx @@ -65,13 +65,13 @@ export const CloudLink: FunctionComponent = ({ application }) => { }, [application]); useEffect(() => { - const dailyDropboxBackupStatus = application.getFeatureStatus( + const dailyDropboxBackupStatus = application.features.getFeatureStatus( FeatureIdentifier.DailyDropboxBackup ); - const dailyGdriveBackupStatus = application.getFeatureStatus( + const dailyGdriveBackupStatus = application.features.getFeatureStatus( FeatureIdentifier.DailyGDriveBackup ); - const dailyOneDriveBackupStatus = application.getFeatureStatus( + const dailyOneDriveBackupStatus = application.features.getFeatureStatus( FeatureIdentifier.DailyOneDriveBackup ); const isCloudBackupsAllowed = [ diff --git a/app/assets/javascripts/preferences/panes/extensions-segments/ExtensionItem.tsx b/app/assets/javascripts/preferences/panes/extensions-segments/ExtensionItem.tsx index c6f343bbf..7e231b761 100644 --- a/app/assets/javascripts/preferences/panes/extensions-segments/ExtensionItem.tsx +++ b/app/assets/javascripts/preferences/panes/extensions-segments/ExtensionItem.tsx @@ -74,7 +74,9 @@ export const ExtensionItem: FunctionComponent = ({ }; const localInstallable = extension.package_info.download_url; - const isThirParty = application.isThirdPartyFeature(extension.identifier); + const isThirParty = application.features.isThirdPartyFeature( + extension.identifier + ); return ( diff --git a/app/assets/javascripts/services/alertService.ts b/app/assets/javascripts/services/alertService.ts index 5eec432ac..b67bef491 100644 --- a/app/assets/javascripts/services/alertService.ts +++ b/app/assets/javascripts/services/alertService.ts @@ -99,6 +99,7 @@ export class AlertService implements SNAlertService { const alert = new SKAlert({ title: title && sanitizeHtmlString(title), text: sanitizeHtmlString(text), + buttons: [], }); alert.present(); return () => { diff --git a/app/assets/javascripts/services/desktopManager.ts b/app/assets/javascripts/services/desktopManager.ts index 342fe5046..f5f8c3e02 100644 --- a/app/assets/javascripts/services/desktopManager.ts +++ b/app/assets/javascripts/services/desktopManager.ts @@ -14,6 +14,7 @@ import { import { WebAppEvent, WebApplication } from '@/ui_models/application'; import { isDesktopApplication } from '@/utils'; import { Bridge, ElectronDesktopCallbacks } from './bridge'; +import { InternalEventBus } from '@standardnotes/services'; /** * An interface used by the Desktop application to interact with SN @@ -31,7 +32,7 @@ export class DesktopManager lastSearchedText?: string; constructor(application: WebApplication, private bridge: Bridge) { - super(application); + super(application, new InternalEventBus()); } get webApplication() { diff --git a/app/assets/javascripts/services/themeManager.ts b/app/assets/javascripts/services/themeManager.ts index 11d0262c8..81cb3218c 100644 --- a/app/assets/javascripts/services/themeManager.ts +++ b/app/assets/javascripts/services/themeManager.ts @@ -12,6 +12,7 @@ import { PayloadSource, PrefKey, } from '@standardnotes/snjs'; +import { InternalEventBus } from '@standardnotes/services'; const CACHED_THEMES_KEY = 'cachedThemes'; @@ -21,7 +22,7 @@ export class ThemeManager extends ApplicationService { private unregisterStream!: () => void; constructor(application: WebApplication) { - super(application); + super(application, new InternalEventBus()); this.colorSchemeEventHandler = this.colorSchemeEventHandler.bind(this); } @@ -127,7 +128,9 @@ export class ThemeManager extends ApplicationService { this.deactivateTheme(themeUuid); hasChange = true; } else { - const status = this.application.getFeatureStatus(theme.identifier); + const status = this.application.features.getFeatureStatus( + theme.identifier + ); if (status !== FeatureStatus.Entitled) { if (theme.active) { this.application.toggleTheme(theme); @@ -212,7 +215,7 @@ export class ThemeManager extends ApplicationService { if ( !skipEntitlementCheck && - this.application.getFeatureStatus(theme.identifier) !== + this.application.features.getFeatureStatus(theme.identifier) !== FeatureStatus.Entitled ) { return; diff --git a/app/assets/javascripts/ui_models/app_state/features_state.ts b/app/assets/javascripts/ui_models/app_state/features_state.ts index bebd3f14f..67b47a9b0 100644 --- a/app/assets/javascripts/ui_models/app_state/features_state.ts +++ b/app/assets/javascripts/ui_models/app_state/features_state.ts @@ -87,7 +87,7 @@ export class FeaturesState { } private hasNativeFolders(): boolean { - const status = this.application.getFeatureStatus( + const status = this.application.features.getFeatureStatus( FeatureIdentifier.TagNesting ); @@ -95,7 +95,7 @@ export class FeaturesState { } private hasNativeSmartViews(): boolean { - const status = this.application.getFeatureStatus( + const status = this.application.features.getFeatureStatus( FeatureIdentifier.SmartFilters ); diff --git a/app/assets/javascripts/ui_models/application_group.ts b/app/assets/javascripts/ui_models/application_group.ts index 5c74699bc..d062d0a24 100644 --- a/app/assets/javascripts/ui_models/application_group.ts +++ b/app/assets/javascripts/ui_models/application_group.ts @@ -16,6 +16,7 @@ import { IOService } from '@/services/ioService'; import { AutolockService } from '@/services/autolock_service'; import { StatusManager } from '@/services/statusManager'; import { ThemeManager } from '@/services/themeManager'; +import { InternalEventBus } from '@standardnotes/services'; export class ApplicationGroup extends SNApplicationGroup { constructor( @@ -62,7 +63,10 @@ export class ApplicationGroup extends SNApplicationGroup { const io = new IOService( platform === Platform.MacWeb || platform === Platform.MacDesktop ); - const autolockService = new AutolockService(application); + const autolockService = new AutolockService( + application, + new InternalEventBus() + ); const statusManager = new StatusManager(); const themeService = new ThemeManager(application); application.setWebServices({ diff --git a/package.json b/package.json index 067e82e77..3c360bb8d 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,15 @@ "@babel/preset-typescript": "^7.16.7", "@reach/disclosure": "^0.16.2", "@reach/visually-hidden": "^0.16.0", + "@standardnotes/responses": "^1.1.5", + "@standardnotes/services": "^1.4.0", + "@standardnotes/stylekit": "5.14.0", "@svgr/webpack": "^6.2.1", "@types/jest": "^27.4.1", "@types/lodash": "^4.14.179", "@types/react": "^17.0.39", - "@typescript-eslint/eslint-plugin": "^5.12.1", - "@typescript-eslint/parser": "^5.12.1", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", "apply-loader": "^2.0.0", "babel-eslint": "^10.1.0", "babel-loader": "^8.2.3", @@ -41,7 +44,7 @@ "css-loader": "^6.6.0", "dotenv": "^16.0.0", "eslint": "^8.10.0", - "eslint-config-prettier": "^8.4.0", + "eslint-config-prettier": "^8.5.0", "eslint-plugin-react": "^7.29.2", "eslint-plugin-react-hooks": "^4.3.0", "file-loader": "^6.2.0", @@ -57,13 +60,12 @@ "pretty-quick": "^3.1.3", "sass-loader": "^12.6.0", "serve-static": "^1.14.2", - "@standardnotes/stylekit": "5.12.2", "svg-jest": "^1.0.1", "ts-jest": "^27.1.3", - "ts-loader": "^9.2.6", - "typescript": "4.5.5", + "ts-loader": "^9.2.7", + "typescript": "4.6.2", "typescript-eslint": "0.0.1-alpha.0", - "webpack": "^5.69.1", + "webpack": "^5.70.0", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.7.4", "webpack-merge": "^5.8.0" @@ -76,11 +78,11 @@ "@reach/dialog": "^0.16.2", "@reach/listbox": "^0.16.2", "@reach/tooltip": "^0.16.2", - "@standardnotes/components": "1.7.6", - "@standardnotes/features": "1.33.1", - "@standardnotes/snjs": "2.66.0", - "@standardnotes/settings": "^1.11.3", - "@standardnotes/sncrypto-web": "1.7.1", + "@standardnotes/components": "1.7.8", + "@standardnotes/features": "1.34.0", + "@standardnotes/settings": "^1.11.5", + "@standardnotes/sncrypto-web": "1.7.3", + "@standardnotes/snjs": "2.72.0", "mobx": "^6.4.2", "mobx-react-lite": "^3.3.0", "preact": "^10.6.6", diff --git a/yarn.lock b/yarn.lock index f0c49f25a..11674449d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2306,105 +2306,116 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@standardnotes/applications@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@standardnotes/applications/-/applications-1.1.1.tgz#c57b9e192436d43963b36919ab44d1c626838151" - integrity sha512-C3K1dzjLG/kG4BCXMhCaL5xBnLXIaElkxZRxmg3Xrnh2XqtO7IbEsrjii8VxdYvjbhCEriFXLgghcSyHujaTTA== +"@standardnotes/applications@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@standardnotes/applications/-/applications-1.1.3.tgz#7f19ab3e1a5d7754e18be9b6b37ed66cbacdbd05" + integrity sha512-B5kJ9S9F7ikGl+KHWgokbBYGwB15XWQSlwpxCw0IAseZuf/b2J8PAS1oeNhRNK73nvXercrQE15X42ORbjSb1Q== dependencies: - "@standardnotes/common" "^1.15.1" + "@standardnotes/common" "^1.15.3" -"@standardnotes/auth@^3.17.1": - version "3.17.1" - resolved "https://registry.yarnpkg.com/@standardnotes/auth/-/auth-3.17.1.tgz#eda5f3e156c990c59407ce5a17f043a5caefe5f9" - integrity sha512-A3y20NeXa5MU5jxTlM1rxD6eMWe6K7WdWsANIiJceuFUx2jisX2esZyJluGZ2Pi3dwhMuOzmoX8iRgk3eUmkgg== +"@standardnotes/auth@^3.17.3": + version "3.17.3" + resolved "https://registry.yarnpkg.com/@standardnotes/auth/-/auth-3.17.3.tgz#a00f10faa0fb2a7dd76509d3b678f85818aad63c" + integrity sha512-tb5ylXuDBPhgeZZynNsMk83N74NMMV9z6M9hyrwuK5HbKWM5r5L9U8lwFawG8flqTKpYzPeWxmaRFZT/5qR22Q== dependencies: - "@standardnotes/common" "^1.15.1" + "@standardnotes/common" "^1.15.3" jsonwebtoken "^8.5.1" -"@standardnotes/common@^1.15.1": - version "1.15.1" - resolved "https://registry.yarnpkg.com/@standardnotes/common/-/common-1.15.1.tgz#e028ca719e9c4c1acbf8867be5f97599275c7490" - integrity sha512-OQTDsB+DatNyRplzx6SUasOTWFdwJZXkJkyDUr1rb1HnPz/VQpHYaQh5pRNHt7OHe002373rQZPAweHBlmEoDg== +"@standardnotes/common@^1.15.3": + version "1.15.3" + resolved "https://registry.yarnpkg.com/@standardnotes/common/-/common-1.15.3.tgz#0b8ce48b81b260abe2d405431fb04aacb44b5a01" + integrity sha512-9oh/W3sFQYyA5Vabcbu6BUkLVkFq/25Q5EK9KCd4aT9QnDJ9JQlTtzDmTk1jYuM6rnccsJ6SW2pcWjbi9FVniw== -"@standardnotes/components@1.7.6": - version "1.7.6" - resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.6.tgz#6dcce572b32580a6df9091422d96c9c0b6917174" - integrity sha512-5lSYNKpO1tQRD6PMOs0IVTmPhfUh33+h6HQZdbWyCmjUk99QE86cI6IC8LnPh5rjHKG+jkfwgVzBKrR3QS/eQw== +"@standardnotes/components@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.8.tgz#2717f54afe013b8b8ca66a8f5197a753d0570d6e" + integrity sha512-6xaUFMvzpisTASmEFKt88QtXIisWxNuZYpOZ2niE4KWTfiknjdMR3m5MSNG6FVI5jbKwaJENkeXVRuKCoIpeIA== -"@standardnotes/domain-events@^2.23.17": - version "2.23.17" - resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.17.tgz#b2256ad7711003fb1790ac53548e8db37df38b4c" - integrity sha512-9qhQFydyi0ZNw2u2tAAp53Gbz1VLRwDX4S7FK4vT3sSoHTmkvkI354ETcgDBlZuIMZSo7AwthKu3wZTCz3jvMA== +"@standardnotes/domain-events@^2.23.20": + version "2.23.20" + resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.20.tgz#8ba0fe7a4f13d91ecf37af6478b5c782e09d2b2c" + integrity sha512-ZIQ/+mZ+II/T8rjgliBhKAuZ4Z2IpAkNIj7GZtcs830tgc5wg9cC92P7aYnLEDzH2J1KCm+UTndEi8fE+fOWyg== dependencies: - "@standardnotes/auth" "^3.17.1" - "@standardnotes/features" "^1.33.1" + "@standardnotes/auth" "^3.17.3" + "@standardnotes/features" "^1.34.0" -"@standardnotes/features@1.33.1", "@standardnotes/features@^1.33.1": - version "1.33.1" - resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.33.1.tgz#0269acf6672396cd7015b8df7f559f600de4dd08" - integrity sha512-TeZJ8nfaVMi1RGCNhGoXtzbhLuODf8fmceuMdZGMJYJEE6eEIr/YvqpDp1tYO/xCsvboZgRdwVmC7D5jPPmIwg== +"@standardnotes/features@1.34.0", "@standardnotes/features@^1.34.0": + version "1.34.0" + resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.34.0.tgz#88a48a4b70d2894b459dadc3f01db912afc7ffdb" + integrity sha512-ipmrCNGsy3zyJRgfTfiN9U1RN1vnzsHXftbhhRECXvYuq+QXyeytJrxCw6SSpZpW/DNOjV6jeIaX8WmaIQfvdA== dependencies: - "@standardnotes/auth" "^3.17.1" - "@standardnotes/common" "^1.15.1" + "@standardnotes/auth" "^3.17.3" + "@standardnotes/common" "^1.15.3" -"@standardnotes/payloads@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.1.2.tgz#6cb7819ab5fedc17d2e90a703015d0a46e350643" - integrity sha512-uV7cKkgP7eqfqyzvsd8r3t+DOGFkWIYNT8bGqYvTSrj+gjIGVSPhqL//oN1iUTvFUtcFTJHVLO2eirE2xcn/0A== +"@standardnotes/payloads@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.3.0.tgz#0db372b21069ae5168cfcd1d6dc55bcb3247fb6b" + integrity sha512-2NUP22oevR2sBQ6blukLZCOkBt/3PoGh+x7nuCt6hdc2OfngcxtKmZ0XEscT1Pq5sAdXxLL4LrQzd0VLH1M0ZQ== dependencies: - "@standardnotes/applications" "^1.1.1" - "@standardnotes/common" "^1.15.1" - "@standardnotes/features" "^1.33.1" - "@standardnotes/utils" "^1.2.1" + "@standardnotes/applications" "^1.1.3" + "@standardnotes/common" "^1.15.3" + "@standardnotes/features" "^1.34.0" + "@standardnotes/utils" "^1.2.3" -"@standardnotes/services@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.2.1.tgz#7f1ddd3a16cd1c8dc43d3466fbe936a28d6d5eeb" - integrity sha512-b8Nw20SSg3Xr34hHoDQPxWNJ6Xgnswrjfg2paYPHXclP1Qwvo7OpiqdcjMntZ88UftvY1bFZJvqF1xrak7TJFA== +"@standardnotes/responses@^1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@standardnotes/responses/-/responses-1.1.5.tgz#565f8ae7cae95fab539904df8e56fd80dcf961d9" + integrity sha512-bk55ByUL07s92L38v4POfLKKBfCdxw/3dzHBRzF3FqDTH2bMOk4+qduqsTmdGDB4N9SuqZkv5/aMuZOw8PF6eA== dependencies: - "@standardnotes/applications" "^1.1.1" - "@standardnotes/common" "^1.15.1" - "@standardnotes/utils" "^1.2.1" + "@standardnotes/auth" "^3.17.3" + "@standardnotes/common" "^1.15.3" + "@standardnotes/features" "^1.34.0" + "@standardnotes/payloads" "^1.3.0" -"@standardnotes/settings@^1.11.3": - version "1.11.3" - resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.11.3.tgz#f7735da40807dab6eaf81cc82d8d30f5461d26d5" - integrity sha512-95nqPYIZt57HMrymf4FTMDHOibM13AmV/8JEj7mPbIqcNKvVD486BURsaqpoBgkqB4Q43LbT8dfTrBPDgmIdxg== - -"@standardnotes/sncrypto-common@^1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.7.1.tgz#2feead118e83b605696b2bc46a0986cbf577f855" - integrity sha512-KAT/bZdbgLzDG8gOeuV07ObnYVE3kBoIK3dtRwlRfal3+BuiXE6JxaSblsophjTLG4i38/sBZ0Ex+UTZoebkug== - -"@standardnotes/sncrypto-web@1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-web/-/sncrypto-web-1.7.1.tgz#8ccbd212a0afd4036d6048bd423b11f68fdafa38" - integrity sha512-oDAS8l6tWiCQNPxnI9i9P/5fud9jFIDz8/6MKeg+xsQ+HD+OUPES4c9a/5oz4ItY5gnYmYrEFLowv22gYFeKYg== +"@standardnotes/services@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.4.0.tgz#776ee5d022e4512844af1a284a2e90f599217218" + integrity sha512-wO0LQ+qMG0bfH0HNPulsO8nZ2Z1Y84NLP0fZdMdtqiuaCi1GrM/PUlcL/fpXCJKNeTKoYa8Dh4PfF8DOjalKXg== dependencies: - "@standardnotes/sncrypto-common" "^1.7.1" + "@standardnotes/applications" "^1.1.3" + "@standardnotes/common" "^1.15.3" + "@standardnotes/utils" "^1.2.3" + +"@standardnotes/settings@^1.11.5": + version "1.11.5" + resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.11.5.tgz#792bf3e0505065486f521b2f19c2bf1081b8fa5e" + integrity sha512-n6StAS3nBgs7Lia5mOt3+H4Xd6hatCcHFx83paFq9kdI1cKbqn7oFF4g/rUbWPy4nsx+96zBehB6EhsJ2MGzyQ== + +"@standardnotes/sncrypto-common@^1.7.3": + version "1.7.3" + resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.7.3.tgz#1e62a14800393be44cdb376d1d72fbc064334fc1" + integrity sha512-twwYeBL+COkNF9IUM5bWrLZ4gXjg41tRxBMR3r3JcbrkyYjcNqVHf9L+YdBcndjSV3/9xwWl2pYWK1RB3UR2Xg== + +"@standardnotes/sncrypto-web@1.7.3": + version "1.7.3" + resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-web/-/sncrypto-web-1.7.3.tgz#4fadaa8d41f301a5077db7a539c770db1cca9413" + integrity sha512-eudCOPQvuhEXUreBz8I+zN8NKNDkLZ1goxbi5nDC7THz+iGPxLFpYhhe9RzacA1oPjOQrBnkrWlByQD13XkvrA== + dependencies: + "@standardnotes/sncrypto-common" "^1.7.3" buffer "^6.0.3" libsodium-wrappers "^0.7.9" -"@standardnotes/snjs@2.66.0": - version "2.66.0" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.66.0.tgz#ae4dd3def15e6e093bf9f39a677f67b98ca9685a" - integrity sha512-/sJ/9+a/ADhA77/k11liW1NlVkWhiT833euo/uhFDv/lfiZB512w/8Y3pfUrYGBQewBOPV1IqsXk4FH/eiz/GQ== +"@standardnotes/snjs@2.72.0": + version "2.72.0" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.72.0.tgz#bf807b94a326e0d33acc15fe418f727f49737935" + integrity sha512-MIpfeZgJ/AHeHfNDGsG1te9SjmMAugOK1HFp8pY/LyEUw4uQJSKbPpwM6q81ExUPROFy3KbE4mn9IN2Kk/5c0A== dependencies: - "@standardnotes/applications" "^1.1.1" - "@standardnotes/auth" "^3.17.1" - "@standardnotes/common" "^1.15.1" - "@standardnotes/domain-events" "^2.23.17" - "@standardnotes/features" "^1.33.1" - "@standardnotes/payloads" "^1.1.2" - "@standardnotes/services" "^1.2.1" - "@standardnotes/settings" "^1.11.3" - "@standardnotes/sncrypto-common" "^1.7.1" - "@standardnotes/utils" "^1.2.1" + "@standardnotes/applications" "^1.1.3" + "@standardnotes/auth" "^3.17.3" + "@standardnotes/common" "^1.15.3" + "@standardnotes/domain-events" "^2.23.20" + "@standardnotes/features" "^1.34.0" + "@standardnotes/payloads" "^1.3.0" + "@standardnotes/responses" "^1.1.5" + "@standardnotes/services" "^1.4.0" + "@standardnotes/settings" "^1.11.5" + "@standardnotes/sncrypto-common" "^1.7.3" + "@standardnotes/utils" "^1.2.3" -"@standardnotes/stylekit@5.12.2": - version "5.12.2" - resolved "https://registry.yarnpkg.com/@standardnotes/stylekit/-/stylekit-5.12.2.tgz#8c2bea39aa696d27a3b88ef68c182638f9c72615" - integrity sha512-pa30xiil1ZQoXZetWdOhABIfOTkuhlSqdi2LAmJ7SkfiCclqsGGvOSf8z2R2V8DP5B7R2kYH6ko11CBGAhwjqA== +"@standardnotes/stylekit@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@standardnotes/stylekit/-/stylekit-5.14.0.tgz#806b7d896fb94de8be72e762dd205beefff05fd7" + integrity sha512-zCB8QFPUTe+063RsLNCudkP6FY6ujKC3iE2pD6ak4htpXtW6DndwYbhEffuiWIjbRzDGAy0YyQ7y8V19Jw7ElQ== dependencies: "@nanostores/preact" "^0.1.3" "@reach/listbox" "^0.16.2" @@ -2414,14 +2425,14 @@ nanostores "^0.5.10" prop-types "^15.8.1" -"@standardnotes/utils@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@standardnotes/utils/-/utils-1.2.1.tgz#226c679f5f91713c58f8ec0e837ea4586b234b3c" - integrity sha512-6lCzDsps9jh+CcgAeyPjwVaZG7VYCqKl5+Qp6mLUyFbqBIylg4ZW3VXvjjfw8DYY1LgHZtCTIHTuDdXCDuGm+w== +"@standardnotes/utils@^1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@standardnotes/utils/-/utils-1.2.3.tgz#2ff61f3214645c84dd6603858feb964db31cb19f" + integrity sha512-0/pSx+kJKRBdQ56oPPFRcMXBvTm/U4/zEE4Kqyx2vlm3EL0tXv4UKNuPSDbsbI5yUn8KpVSZ6LS4LZhhMU4IUA== dependencies: - "@standardnotes/common" "^1.15.1" - dompurify "^2.3.4" - lodash "^4.17.19" + "@standardnotes/common" "^1.15.3" + dompurify "^2.3.6" + lodash "^4.17.21" "@svgr/babel-plugin-add-jsx-attribute@^6.0.0": version "6.0.0" @@ -2821,14 +2832,14 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.12.1.tgz#b2cd3e288f250ce8332d5035a2ff65aba3374ac4" - integrity sha512-M499lqa8rnNK7mUv74lSFFttuUsubIRdAbHcVaP93oFcKkEmHmLqy2n7jM9C8DVmFMYK61ExrZU6dLYhQZmUpw== +"@typescript-eslint/eslint-plugin@^5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz#2809052b85911ced9c54a60dac10e515e9114497" + integrity sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ== dependencies: - "@typescript-eslint/scope-manager" "5.12.1" - "@typescript-eslint/type-utils" "5.12.1" - "@typescript-eslint/utils" "5.12.1" + "@typescript-eslint/scope-manager" "5.13.0" + "@typescript-eslint/type-utils" "5.13.0" + "@typescript-eslint/utils" "5.13.0" debug "^4.3.2" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -2836,69 +2847,69 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.12.1.tgz#b090289b553b8aa0899740d799d0f96e6f49771b" - integrity sha512-6LuVUbe7oSdHxUWoX/m40Ni8gsZMKCi31rlawBHt7VtW15iHzjbpj2WLiToG2758KjtCCiLRKZqfrOdl3cNKuw== +"@typescript-eslint/parser@^5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.13.0.tgz#0394ed8f2f849273c0bf4b811994d177112ced5c" + integrity sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg== dependencies: - "@typescript-eslint/scope-manager" "5.12.1" - "@typescript-eslint/types" "5.12.1" - "@typescript-eslint/typescript-estree" "5.12.1" + "@typescript-eslint/scope-manager" "5.13.0" + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/typescript-estree" "5.13.0" debug "^4.3.2" -"@typescript-eslint/scope-manager@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.12.1.tgz#58734fd45d2d1dec49641aacc075fba5f0968817" - integrity sha512-J0Wrh5xS6XNkd4TkOosxdpObzlYfXjAFIm9QxYLCPOcHVv1FyyFCPom66uIh8uBr0sZCrtS+n19tzufhwab8ZQ== +"@typescript-eslint/scope-manager@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz#cf6aff61ca497cb19f0397eea8444a58f46156b6" + integrity sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA== dependencies: - "@typescript-eslint/types" "5.12.1" - "@typescript-eslint/visitor-keys" "5.12.1" + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/visitor-keys" "5.13.0" -"@typescript-eslint/type-utils@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.12.1.tgz#8d58c6a0bb176b5e9a91581cda1a7f91a114d3f0" - integrity sha512-Gh8feEhsNLeCz6aYqynh61Vsdy+tiNNkQtc+bN3IvQvRqHkXGUhYkUi+ePKzP0Mb42se7FDb+y2SypTbpbR/Sg== +"@typescript-eslint/type-utils@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz#b0efd45c85b7bab1125c97b752cab3a86c7b615d" + integrity sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg== dependencies: - "@typescript-eslint/utils" "5.12.1" + "@typescript-eslint/utils" "5.13.0" debug "^4.3.2" tsutils "^3.21.0" -"@typescript-eslint/types@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.12.1.tgz#46a36a28ff4d946821b58fe5a73c81dc2e12aa89" - integrity sha512-hfcbq4qVOHV1YRdhkDldhV9NpmmAu2vp6wuFODL71Y0Ixak+FLeEU4rnPxgmZMnGreGEghlEucs9UZn5KOfHJA== +"@typescript-eslint/types@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.13.0.tgz#da1de4ae905b1b9ff682cab0bed6b2e3be9c04e5" + integrity sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg== -"@typescript-eslint/typescript-estree@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.12.1.tgz#6a9425b9c305bcbc38e2d1d9a24c08e15e02b722" - integrity sha512-ahOdkIY9Mgbza7L9sIi205Pe1inCkZWAHE1TV1bpxlU4RZNPtXaDZfiiFWcL9jdxvW1hDYZJXrFm+vlMkXRbBw== +"@typescript-eslint/typescript-estree@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz#b37c07b748ff030a3e93d87c842714e020b78141" + integrity sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA== dependencies: - "@typescript-eslint/types" "5.12.1" - "@typescript-eslint/visitor-keys" "5.12.1" + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/visitor-keys" "5.13.0" debug "^4.3.2" globby "^11.0.4" is-glob "^4.0.3" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.12.1.tgz#447c24a05d9c33f9c6c64cb48f251f2371eef920" - integrity sha512-Qq9FIuU0EVEsi8fS6pG+uurbhNTtoYr4fq8tKjBupsK5Bgbk2I32UGm0Sh+WOyjOPgo/5URbxxSNV6HYsxV4MQ== +"@typescript-eslint/utils@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.13.0.tgz#2328feca700eb02837298339a2e49c46b41bd0af" + integrity sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.12.1" - "@typescript-eslint/types" "5.12.1" - "@typescript-eslint/typescript-estree" "5.12.1" + "@typescript-eslint/scope-manager" "5.13.0" + "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/typescript-estree" "5.13.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.12.1.tgz#f722da106c8f9695ae5640574225e45af3e52ec3" - integrity sha512-l1KSLfupuwrXx6wc0AuOmC7Ko5g14ZOQ86wJJqRbdLbXLK02pK/DPiDDqCc7BqqiiA04/eAA6ayL0bgOrAkH7A== +"@typescript-eslint/visitor-keys@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz#f45ff55bcce16403b221ac9240fbeeae4764f0fd" + integrity sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g== dependencies: - "@typescript-eslint/types" "5.12.1" + "@typescript-eslint/types" "5.13.0" eslint-visitor-keys "^3.0.0" "@webassemblyjs/ast@1.11.1": @@ -4453,7 +4464,7 @@ domhandler@^4.0.0, domhandler@^4.2.0: dependencies: domelementtype "^2.2.0" -dompurify@^2.3.4: +dompurify@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875" integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg== @@ -4559,7 +4570,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.3: +enhanced-resolve@^5.0.0: version "5.8.3" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== @@ -4567,6 +4578,14 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.3: graceful-fs "^4.2.4" tapable "^2.2.0" +enhanced-resolve@^5.9.2: + version "5.9.2" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9" + integrity sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + entities@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" @@ -4718,10 +4737,10 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.4.0.tgz#8e6d17c7436649e98c4c2189868562921ef563de" - integrity sha512-CFotdUcMY18nGRo5KGsnNxpznzhkopOcOo0InID+sgQssPrzjvsyKZPvOgymTFeHrFuC3Tzdf2YndhXtULK9Iw== +eslint-config-prettier@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" + integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== eslint-plugin-react-hooks@^4.3.0: version "4.3.0" @@ -9237,10 +9256,10 @@ ts-jest@^27.1.3: semver "7.x" yargs-parser "20.x" -ts-loader@^9.2.6: - version "9.2.6" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" - integrity sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw== +ts-loader@^9.2.7: + version "9.2.7" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.7.tgz#948654099ca96992b62ec47bd9cee5632006e101" + integrity sha512-Fxh44mKli9QezgbdCXkEJWxnedQ0ead7DXTH+lfXEPedu+Y9EtMJ2aQ9G3Dj1j7Q612E8931rww8NDZha4Tibg== dependencies: chalk "^4.1.0" enhanced-resolve "^5.0.0" @@ -9350,10 +9369,10 @@ typescript-eslint@0.0.1-alpha.0: resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-0.0.1-alpha.0.tgz#285d68a4e96588295cd436278801bcb6a6b916c1" integrity sha512-1hNKM37dAWML/2ltRXupOq2uqcdRQyDFphl+341NTPXFLLLiDhErXx8VtaSLh3xP7SyHZdcCgpt9boYYVb3fQg== -typescript@4.5.5: - version "4.5.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" - integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== +typescript@4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" + integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== unbox-primitive@^1.0.1: version "1.0.1" @@ -9638,10 +9657,10 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.69.1: - version "5.69.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.69.1.tgz#8cfd92c192c6a52c99ab00529b5a0d33aa848dc5" - integrity sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A== +webpack@^5.70.0: + version "5.70.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.70.0.tgz#3461e6287a72b5e6e2f4872700bc8de0d7500e6d" + integrity sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" @@ -9652,7 +9671,7 @@ webpack@^5.69.1: acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" + enhanced-resolve "^5.9.2" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" From c150cd6867af87a6aa82cfaae809214cae57ad44 Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Fri, 4 Mar 2022 18:14:25 +0530 Subject: [PATCH 16/17] feat: close change editor menu once editor is selected (#907) --- app/assets/javascripts/components/ChangeEditorButton.tsx | 3 +++ .../components/NotesOptions/ChangeEditorOption.tsx | 3 +++ .../components/NotesOptions/changeEditor/ChangeEditorMenu.tsx | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/app/assets/javascripts/components/ChangeEditorButton.tsx b/app/assets/javascripts/components/ChangeEditorButton.tsx index 715dd94d7..c080c35ec 100644 --- a/app/assets/javascripts/components/ChangeEditorButton.tsx +++ b/app/assets/javascripts/components/ChangeEditorButton.tsx @@ -130,6 +130,9 @@ export const ChangeEditorButton: FunctionComponent = observer( setSelectedEditor={setCurrentEditor} note={note} groups={editorMenuGroups} + closeMenu={() => { + setOpen(false); + }} /> )} diff --git a/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx b/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx index 7f35a9f2d..fb90c0623 100644 --- a/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx +++ b/app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx @@ -148,6 +148,9 @@ export const ChangeEditorOption: FunctionComponent = ({ note={note} groups={editorMenuGroups} isOpen={changeEditorMenuVisible} + closeMenu={() => { + setChangeEditorMenuOpen(false); + }} /> )} diff --git a/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx b/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx index ac4a0631d..b6578bdba 100644 --- a/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx +++ b/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx @@ -26,6 +26,7 @@ import { PLAIN_EDITOR_NAME } from './createEditorMenuGroups'; type ChangeEditorMenuProps = { application: WebApplication; closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void; + closeMenu: () => void; groups: EditorMenuGroup[]; isOpen: boolean; currentEditor: SNComponent | undefined; @@ -39,6 +40,7 @@ const getGroupId = (group: EditorMenuGroup) => export const ChangeEditorMenu: FunctionComponent = ({ application, closeOnBlur, + closeMenu, groups, isOpen, currentEditor, @@ -169,6 +171,8 @@ export const ChangeEditorMenu: FunctionComponent = ({ if (shouldSelectEditor) { selectComponent(itemToBeSelected.component ?? null, note); } + + closeMenu(); }; return ( From 4a06cb3e0497d9aaa7b7e3c0fe4ceef8e121c03b Mon Sep 17 00:00:00 2001 From: Mo Date: Fri, 4 Mar 2022 08:43:03 -0600 Subject: [PATCH 17/17] chore: bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c360bb8d..74e55fbfe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "standard-notes-web", - "version": "3.11.2", + "version": "3.12.0", "license": "AGPL-3.0-or-later", "repository": { "type": "git",