From afc84b5702a9fcc24f9233fd9f19851da4d3ca35 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Wed, 30 Jun 2021 18:50:38 -0300 Subject: [PATCH 01/14] fix: reposition dropdowns when resizing window --- .../components/NotesContextMenu.tsx | 25 ++++++-- .../javascripts/components/SearchOptions.tsx | 24 ++++++-- .../ui_models/app_state/notes_state.ts | 60 +++++++++++++++++++ .../javascripts/views/notes/notes_view.ts | 57 ++---------------- 4 files changed, 104 insertions(+), 62 deletions(-) diff --git a/app/assets/javascripts/components/NotesContextMenu.tsx b/app/assets/javascripts/components/NotesContextMenu.tsx index abd4fa354..3afd7df89 100644 --- a/app/assets/javascripts/components/NotesContextMenu.tsx +++ b/app/assets/javascripts/components/NotesContextMenu.tsx @@ -2,13 +2,19 @@ import { AppState } from '@/ui_models/app_state'; import { toDirective, useCloseOnBlur, useCloseOnClickOutside } from './utils'; import { observer } from 'mobx-react-lite'; import { NotesOptions } from './NotesOptions'; -import { useRef } from 'preact/hooks'; +import { useCallback, useEffect, useRef } from 'preact/hooks'; type Props = { appState: AppState; }; const NotesContextMenu = observer(({ appState }: Props) => { + const { + contextMenuOpen, + contextMenuPosition, + contextMenuMaxHeight, + } = appState.notes; + const contextMenuRef = useRef(); const [closeOnBlur] = useCloseOnBlur( contextMenuRef, @@ -20,13 +26,24 @@ const NotesContextMenu = observer(({ appState }: Props) => { (open: boolean) => appState.notes.setContextMenuOpen(open) ); - return appState.notes.contextMenuOpen ? ( + const reloadContextMenuLayout = useCallback(() => { + appState.notes.reloadContextMenuLayout(); + }, [appState.notes]); + + useEffect(() => { + window.addEventListener('resize', reloadContextMenuLayout); + return () => { + window.removeEventListener('resize', reloadContextMenuLayout); + }; + }, [reloadContextMenuLayout]); + + return contextMenuOpen ? (
diff --git a/app/assets/javascripts/components/SearchOptions.tsx b/app/assets/javascripts/components/SearchOptions.tsx index 8315c3a91..ddd320d93 100644 --- a/app/assets/javascripts/components/SearchOptions.tsx +++ b/app/assets/javascripts/components/SearchOptions.tsx @@ -11,6 +11,7 @@ import { } from '@reach/disclosure'; import { Switch } from './Switch'; import { observer } from 'mobx-react-lite'; +import { useEffect } from 'react'; type Props = { appState: AppState; @@ -45,16 +46,27 @@ const SearchOptions = observer(({ appState }: Props) => { } } + const updateWidthAndPosition = () => { + const rect = buttonRef.current.getBoundingClientRect(); + setMaxWidth(rect.right - 16); + setPosition({ + top: rect.bottom, + right: document.body.clientWidth - rect.right, + }); + }; + + useEffect(() => { + window.addEventListener('resize', updateWidthAndPosition); + return () => { + window.removeEventListener('resize', updateWidthAndPosition); + }; + }, []); + return ( { - const rect = buttonRef.current.getBoundingClientRect(); - setMaxWidth(rect.right - 16); - setPosition({ - top: rect.bottom, - right: document.body.clientWidth - rect.right, - }); + updateWidthAndPosition(); setOpen(!open); }} > diff --git a/app/assets/javascripts/ui_models/app_state/notes_state.ts b/app/assets/javascripts/ui_models/app_state/notes_state.ts index 66d1ad024..9b59fc6c9 100644 --- a/app/assets/javascripts/ui_models/app_state/notes_state.ts +++ b/app/assets/javascripts/ui_models/app_state/notes_state.ts @@ -28,6 +28,7 @@ export class NotesState { top: 0, left: 0, }; + contextMenuClickLocation: { x: number, y: number } = { x: 0, y: 0 }; contextMenuMaxHeight: number | 'auto' = 'auto'; showProtectedWarning = false; @@ -47,6 +48,7 @@ export class NotesState { trashedNotesCount: computed, setContextMenuOpen: action, + setContextMenuClickLocation: action, setContextMenuPosition: action, setContextMenuMaxHeight: action, setShowProtectedWarning: action, @@ -183,6 +185,10 @@ export class NotesState { this.contextMenuOpen = open; } + setContextMenuClickLocation(location: { x: number, y: number }): void { + this.contextMenuClickLocation = location; + } + setContextMenuPosition(position: { top?: number; left: number; @@ -195,6 +201,60 @@ export class NotesState { this.contextMenuMaxHeight = maxHeight; } + reloadContextMenuLayout(): void { + const { clientHeight } = document.documentElement; + const defaultFontSize = window.getComputedStyle( + document.documentElement + ).fontSize; + const maxContextMenuHeight = parseFloat(defaultFontSize) * 30; + const footerHeight = 32; + + // Open up-bottom is default behavior + let openUpBottom = true; + + const bottomSpace = clientHeight - footerHeight - this.contextMenuClickLocation.y; + const upSpace = this.contextMenuClickLocation.y; + + // If not enough space to open up-bottom + if (maxContextMenuHeight > bottomSpace) { + // If there's enough space, open bottom-up + if (upSpace > maxContextMenuHeight) { + openUpBottom = false; + this.setContextMenuMaxHeight( + 'auto' + ); + // Else, reduce max height (menu will be scrollable) and open in whichever direction there's more space + } else { + if (upSpace > bottomSpace) { + this.setContextMenuMaxHeight( + upSpace - 2 + ); + openUpBottom = false; + } else { + this.setContextMenuMaxHeight( + bottomSpace - 2 + ); + } + } + } else { + this.setContextMenuMaxHeight( + 'auto' + ); + } + + if (openUpBottom) { + this.setContextMenuPosition({ + top: this.contextMenuClickLocation.y, + left: this.contextMenuClickLocation.x, + }); + } else { + this.setContextMenuPosition({ + bottom: clientHeight - this.contextMenuClickLocation.y, + left: this.contextMenuClickLocation.x, + }); + } + } + async changeSelectedNotes( mutate: (mutator: NoteMutator) => void ): Promise { diff --git a/app/assets/javascripts/views/notes/notes_view.ts b/app/assets/javascripts/views/notes/notes_view.ts index 6ed9e41c1..5ad8a32c8 100644 --- a/app/assets/javascripts/views/notes/notes_view.ts +++ b/app/assets/javascripts/views/notes/notes_view.ts @@ -310,58 +310,11 @@ class NotesViewCtrl extends PureViewCtrl { await this.selectNote(note, true); } if (this.state.selectedNotes[note.uuid]) { - const { clientHeight } = document.documentElement; - const defaultFontSize = window.getComputedStyle( - document.documentElement - ).fontSize; - const maxContextMenuHeight = parseFloat(defaultFontSize) * 30; - const footerHeight = 32; - - // Open up-bottom is default behavior - let openUpBottom = true; - - const bottomSpace = clientHeight - footerHeight - e.clientY; - const upSpace = e.clientY; - - // If not enough space to open up-bottom - if (maxContextMenuHeight > bottomSpace) { - // If there's enough space, open bottom-up - if (upSpace > maxContextMenuHeight) { - openUpBottom = false; - this.appState.notes.setContextMenuMaxHeight( - 'auto' - ); - // Else, reduce max height (menu will be scrollable) and open in whichever direction there's more space - } else { - if (upSpace > bottomSpace) { - this.appState.notes.setContextMenuMaxHeight( - upSpace - 2 - ); - openUpBottom = false; - } else { - this.appState.notes.setContextMenuMaxHeight( - bottomSpace - 2 - ); - } - } - } else { - this.appState.notes.setContextMenuMaxHeight( - 'auto' - ); - } - - if (openUpBottom) { - this.appState.notes.setContextMenuPosition({ - top: e.clientY, - left: e.clientX, - }); - } else { - this.appState.notes.setContextMenuPosition({ - bottom: clientHeight - e.clientY, - left: e.clientX, - }); - } - + this.appState.notes.setContextMenuClickLocation({ + x: e.clientX, + y: e.clientY, + }); + this.appState.notes.reloadContextMenuLayout(); this.appState.notes.setContextMenuOpen(true); } } From 8ea78351b56b4de9609debe0190520a860c3f54d Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Wed, 30 Jun 2021 18:58:22 -0300 Subject: [PATCH 02/14] chore: remove log --- app/assets/javascripts/components/SessionsModal.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/components/SessionsModal.tsx b/app/assets/javascripts/components/SessionsModal.tsx index 6677ff943..875f25f9c 100644 --- a/app/assets/javascripts/components/SessionsModal.tsx +++ b/app/assets/javascripts/components/SessionsModal.tsx @@ -76,7 +76,6 @@ function useSessions( setSessions(sessionsDuringRevoke); const response = await responsePromise; - console.log(response); if (isNullOrUndefined(response)) { setSessions(sessionsBeforeRevoke); } else if ('error' in response) { From 2295f5d59364d8aaea4f9e818762807b2046beac Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Wed, 30 Jun 2021 18:59:07 -0300 Subject: [PATCH 03/14] fix: fix tags tab navigation --- app/assets/javascripts/components/NoteTag.tsx | 1 - app/assets/javascripts/ui_models/app_state/note_tags_state.ts | 4 ---- 2 files changed, 5 deletions(-) diff --git a/app/assets/javascripts/components/NoteTag.tsx b/app/assets/javascripts/components/NoteTag.tsx index 3afcc3d35..f08c94ef8 100644 --- a/app/assets/javascripts/components/NoteTag.tsx +++ b/app/assets/javascripts/components/NoteTag.tsx @@ -97,7 +97,6 @@ export const NoteTag = observer(({ appState, tag }: Props) => { ref={deleteTagRef} type="button" className="ml-2 -mr-1 border-0 p-0 bg-transparent cursor-pointer flex" - onFocus={onFocus} onBlur={onBlur} onClick={onDeleteTagClick} > diff --git a/app/assets/javascripts/ui_models/app_state/note_tags_state.ts b/app/assets/javascripts/ui_models/app_state/note_tags_state.ts index 3f46a0781..3ad0900e8 100644 --- a/app/assets/javascripts/ui_models/app_state/note_tags_state.ts +++ b/app/assets/javascripts/ui_models/app_state/note_tags_state.ts @@ -30,9 +30,6 @@ export class NoteTagsState { autocompleteTagHintVisible: computed, - clearAutocompleteSearch: action, - focusNextTag: action, - focusPreviousTag: action, setAutocompleteInputFocused: action, setAutocompleteSearchQuery: action, setAutocompleteTagHintFocused: action, @@ -41,7 +38,6 @@ export class NoteTagsState { setFocusedTagUuid: action, setTags: action, setTagsContainerMaxWidth: action, - reloadTags: action, }); appEventListeners.push( From 3e76ef6b6f3fa0bc0174dc83d3a1e8baed69bbd8 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Thu, 1 Jul 2021 14:36:21 -0300 Subject: [PATCH 04/14] fix: fix tags keyboard navigation --- .../components/AutocompleteTagHint.tsx | 1 + .../components/AutocompleteTagInput.tsx | 2 +- .../components/AutocompleteTagResult.tsx | 1 + app/assets/javascripts/components/NoteTag.tsx | 15 +++++++++++++-- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/components/AutocompleteTagHint.tsx b/app/assets/javascripts/components/AutocompleteTagHint.tsx index 00cc04af7..bbb1ec928 100644 --- a/app/assets/javascripts/components/AutocompleteTagHint.tsx +++ b/app/assets/javascripts/components/AutocompleteTagHint.tsx @@ -62,6 +62,7 @@ export const AutocompleteTagHint = observer( onFocus={onFocus} onBlur={onBlur} onKeyDown={onKeyDown} + tabIndex={-1} > Create new tag: diff --git a/app/assets/javascripts/components/AutocompleteTagInput.tsx b/app/assets/javascripts/components/AutocompleteTagInput.tsx index 2dddf3077..e3771024d 100644 --- a/app/assets/javascripts/components/AutocompleteTagInput.tsx +++ b/app/assets/javascripts/components/AutocompleteTagInput.tsx @@ -92,7 +92,6 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { useEffect(() => { if (autocompleteInputFocused) { inputRef.current.focus(); - appState.noteTags.setAutocompleteInputFocused(false); } }, [appState.noteTags, autocompleteInputFocused]); @@ -113,6 +112,7 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { onBlur={onBlur} onFocus={onFocus} onKeyDown={onKeyDown} + tabIndex={tags.length === 0 ? 0 : -1} /> {dropdownVisible && (autocompleteTagResults.length > 0 || autocompleteTagHintVisible) && ( diff --git a/app/assets/javascripts/components/NoteTag.tsx b/app/assets/javascripts/components/NoteTag.tsx index f08c94ef8..ba80ebe48 100644 --- a/app/assets/javascripts/components/NoteTag.tsx +++ b/app/assets/javascripts/components/NoteTag.tsx @@ -10,7 +10,7 @@ type Props = { }; export const NoteTag = observer(({ appState, tag }: Props) => { - const { focusedTagUuid, tags } = appState.noteTags; + const { autocompleteInputFocused, focusedTagUuid, tags } = appState.noteTags; const [showDeleteButton, setShowDeleteButton] = useState(false); const [tagClicked, setTagClicked] = useState(false); @@ -51,6 +51,16 @@ export const NoteTag = observer(({ appState, tag }: Props) => { } }; + const getTabIndex = () => { + if (focusedTagUuid) { + return focusedTagUuid === tag.uuid ? 0 : -1; + } + if (autocompleteInputFocused) { + return -1; + } + return tags[0].uuid === tag.uuid ? 0 : -1; + }; + const onKeyDown = (event: KeyboardEvent) => { const tagIndex = appState.noteTags.getTagIndex(tag, tags); switch (event.key) { @@ -75,7 +85,6 @@ export const NoteTag = observer(({ appState, tag }: Props) => { useEffect(() => { if (focusedTagUuid === tag.uuid) { tagRef.current.focus(); - appState.noteTags.setFocusedTagUuid(undefined); } }, [appState.noteTags, focusedTagUuid, tag]); @@ -87,6 +96,7 @@ export const NoteTag = observer(({ appState, tag }: Props) => { onKeyDown={onKeyDown} onFocus={onFocus} onBlur={onBlur} + tabIndex={getTabIndex()} > @@ -99,6 +109,7 @@ export const NoteTag = observer(({ appState, tag }: Props) => { className="ml-2 -mr-1 border-0 p-0 bg-transparent cursor-pointer flex" onBlur={onBlur} onClick={onDeleteTagClick} + tabIndex={-1} > Date: Thu, 1 Jul 2021 14:36:56 -0300 Subject: [PATCH 05/14] fix: don't clear search query when navigating back to input --- .../components/AutocompleteTagInput.tsx | 104 ++++++++++-------- 1 file changed, 58 insertions(+), 46 deletions(-) diff --git a/app/assets/javascripts/components/AutocompleteTagInput.tsx b/app/assets/javascripts/components/AutocompleteTagInput.tsx index e3771024d..80c865f39 100644 --- a/app/assets/javascripts/components/AutocompleteTagInput.tsx +++ b/app/assets/javascripts/components/AutocompleteTagInput.tsx @@ -25,10 +25,10 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { const [dropdownMaxHeight, setDropdownMaxHeight] = useState('auto'); - const dropdownRef = useRef(); + const containerRef = useRef(); const inputRef = useRef(); - const [closeOnBlur] = useCloseOnBlur(dropdownRef, (visible: boolean) => { + const [closeOnBlur] = useCloseOnBlur(containerRef, (visible: boolean) => { setDropdownVisible(visible); appState.noteTags.clearAutocompleteSearch(); }); @@ -69,7 +69,9 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { case 'ArrowDown': event.preventDefault(); if (autocompleteTagResults.length > 0) { - appState.noteTags.setFocusedTagResultUuid(autocompleteTagResults[0].uuid); + appState.noteTags.setFocusedTagResultUuid( + autocompleteTagResults[0].uuid + ); } else if (autocompleteTagHintVisible) { appState.noteTags.setAutocompleteTagHintFocused(true); } @@ -96,50 +98,60 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { }, [appState.noteTags, autocompleteInputFocused]); return ( -
0 ? 'mt-2' : ''}`} - > - - 0 ? 'w-80' : 'w-70 mr-10'} bg-transparent text-xs +
+ 0 ? 'mt-2' : ''}`} + > + + 0 ? 'w-80' : 'w-70 mr-10' + } bg-transparent text-xs color-text no-border h-7 focus:outline-none focus:shadow-none focus:border-bottom`} - value={autocompleteSearchQuery} - onChange={onSearchQueryChange} - type="text" - placeholder="Add tag" - onBlur={onBlur} - onFocus={onFocus} - onKeyDown={onKeyDown} - tabIndex={tags.length === 0 ? 0 : -1} - /> - {dropdownVisible && (autocompleteTagResults.length > 0 || autocompleteTagHintVisible) && ( - 0 ? 'w-80' : 'w-70 mr-10'} sn-dropdown flex flex-col py-2 absolute`} - style={{ maxHeight: dropdownMaxHeight, maxWidth: tagsContainerMaxWidth }} - onBlur={closeOnBlur} - > -
- {autocompleteTagResults.map((tagResult: SNTag) => ( - - ))} -
- {autocompleteTagHintVisible && ( - + value={autocompleteSearchQuery} + onChange={onSearchQueryChange} + type="text" + placeholder="Add tag" + onBlur={onBlur} + onFocus={onFocus} + onKeyDown={onKeyDown} + tabIndex={tags.length === 0 ? 0 : -1} + /> + {dropdownVisible && + (autocompleteTagResults.length > 0 || + autocompleteTagHintVisible) && ( + 0 ? 'w-80' : 'w-70 mr-10' + } sn-dropdown flex flex-col py-2 absolute`} + style={{ + maxHeight: dropdownMaxHeight, + maxWidth: tagsContainerMaxWidth, + }} + onBlur={closeOnBlur} + > +
+ {autocompleteTagResults.map((tagResult: SNTag) => ( + + ))} +
+ {autocompleteTagHintVisible && ( + + )} +
)} -
- )} -
- + + +
); }); From 1d4eae5d0073cdda5f379011e6e76ffe25f155a5 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Thu, 1 Jul 2021 16:44:10 -0300 Subject: [PATCH 06/14] fix: set minimum passcode length --- .../javascripts/directives/views/accountMenu.ts | 14 ++++++++++++-- app/assets/javascripts/strings.ts | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index cf6851e4f..cd4ae8984 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -18,6 +18,7 @@ import { STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL, STRING_UNSUPPORTED_BACKUP_FILE_VERSION, StringUtils, + Strings, } from '@/strings'; import { PasswordWizardType } from '@/types'; import { @@ -509,8 +510,17 @@ class AccountMenuCtrl extends PureViewCtrl { } async submitPasscodeForm() { - const passcode = this.getState().formData.passcode!; - if (passcode !== this.getState().formData.confirmPasscode!) { + const passcode = this.getState().formData.passcode; + + if (!passcode || passcode.length === 0) { + await alertDialog({ + text: Strings.enterPasscode, + }); + this.passcodeInput[0].focus(); + return; + } + + if (passcode !== this.getState().formData.confirmPasscode) { await alertDialog({ text: STRING_NON_MATCHING_PASSCODES, }); diff --git a/app/assets/javascripts/strings.ts b/app/assets/javascripts/strings.ts index 1c112f341..217fb366d 100644 --- a/app/assets/javascripts/strings.ts +++ b/app/assets/javascripts/strings.ts @@ -113,6 +113,7 @@ export const Strings = { openAccountMenu: 'Open Account Menu', trashNotesTitle: 'Move to Trash', trashNotesText: 'Are you sure you want to move these notes to the trash?', + enterPasscode: 'Please enter a passcode.', }; export const StringUtils = { From 4a07d3e7db3e030053f2db6aa509a4e4ee886d09 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Thu, 1 Jul 2021 17:54:10 -0300 Subject: [PATCH 07/14] chore: update missing links to .com --- app/assets/javascripts/strings.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/strings.ts b/app/assets/javascripts/strings.ts index 217fb366d..3041fa42b 100644 --- a/app/assets/javascripts/strings.ts +++ b/app/assets/javascripts/strings.ts @@ -5,7 +5,7 @@ import { getPlatform, isDesktopApplication } from './utils'; export const STRING_SESSION_EXPIRED = 'Your session has expired. New changes will not be pulled in. Please sign in to refresh your session.'; export const STRING_DEFAULT_FILE_ERROR = - 'Please use FileSafe or the Bold Editor to attach images and files. Learn more at standardnotes.org/filesafe.'; + 'Please use FileSafe or the Bold Editor to attach images and files. Learn more at standardnotes.com/filesafe.'; export const STRING_GENERIC_SYNC_ERROR = 'There was an error syncing. Please try again. If all else fails, try signing out and signing back in.'; export function StringSyncException(data: any) { @@ -105,7 +105,7 @@ export const STRING_UPGRADE_ACCOUNT_CONFIRM_TEXT = 'Encryption version 004 is available. ' + 'This version strengthens the encryption algorithms your account and ' + 'local storage use. To learn more about this upgrade, visit our ' + - 'Security Upgrade page.'; + 'Security Upgrade page.'; export const STRING_UPGRADE_ACCOUNT_CONFIRM_BUTTON = 'Upgrade'; export const Strings = { From b3347b75bad6f61f916bbae4a5e3ed6069b6e293 Mon Sep 17 00:00:00 2001 From: Johnny A <5891646+johnny243@users.noreply.github.com> Date: Fri, 2 Jul 2021 11:18:06 -0400 Subject: [PATCH 08/14] feat: show deprecation notice (#587) * feat: show deprecation notice * feat: show deprecation message * chore(deps): update snjs Co-authored-by: Johnny Almonte --- .../javascripts/directives/views/componentView.ts | 11 +++++++++++ app/assets/templates/directives/component-view.pug | 8 ++++++++ package.json | 2 +- yarn.lock | 8 ++++---- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/directives/views/componentView.ts b/app/assets/javascripts/directives/views/componentView.ts index 85b18c29d..5df917399 100644 --- a/app/assets/javascripts/directives/views/componentView.ts +++ b/app/assets/javascripts/directives/views/componentView.ts @@ -33,6 +33,9 @@ class ComponentViewCtrl implements ComponentViewScope { private unregisterComponentHandler!: () => void private unregisterDesktopObserver!: () => void private issueLoading = false + private isDeprecated = false + private deprecationMessage = '' + private deprecationMessageDismissed = false public reloading = false private expired = false private loading = false @@ -175,6 +178,12 @@ class ComponentViewCtrl implements ComponentViewScope { }); } + private dismissDeprecationMessage() { + this.$timeout(() => { + this.deprecationMessageDismissed = true; + }); + } + private onVisibilityChange() { if (document.visibilityState === 'hidden') { return; @@ -215,6 +224,8 @@ class ComponentViewCtrl implements ComponentViewScope { if (this.expired && doManualReload) { this.$rootScope.$broadcast(RootScopeMessages.ReloadExtendedData); } + this.isDeprecated = component.isDeprecated; + this.deprecationMessage = component.package_info.deprecation_message; } private async handleIframeLoadTimeout() { diff --git a/app/assets/templates/directives/component-view.pug b/app/assets/templates/directives/component-view.pug index e8bd06759..917f44a66 100644 --- a/app/assets/templates/directives/component-view.pug +++ b/app/assets/templates/directives/component-view.pug @@ -33,6 +33,14 @@ rel='noopener', target='_blank' ) Help +.sn-component(ng-if='ctrl.isDeprecated && !ctrl.deprecationMessageDismissed') + .sk-app-bar.no-edges.no-top-edge.dynamic-height + .left + .sk-app-bar-item + .sk-label.warning {{ctrl.deprecationMessage || 'This extension is deprecated.'}} + .right + .sk-app-bar-item(ng-click='ctrl.dismissDeprecationMessage()') + button.sn-button.small.info Dismiss .sn-component(ng-if="ctrl.error == 'offline-restricted'") .sk-panel.static diff --git a/package.json b/package.json index b9fa15976..41b2b072b 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@reach/checkbox": "^0.13.2", "@reach/dialog": "^0.13.0", "@standardnotes/sncrypto-web": "1.2.10", - "@standardnotes/snjs": "2.7.9", + "@standardnotes/snjs": "2.7.10", "mobx": "^6.1.6", "mobx-react-lite": "^3.2.0", "preact": "^10.5.12" diff --git a/yarn.lock b/yarn.lock index 7699cacc1..8ac5a5994 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1936,10 +1936,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@2.7.9": - version "2.7.9" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.7.9.tgz#8b2a5d0f6248e1872b2fe68a73307f754528b4c3" - integrity sha512-FNiLXdaUb2+WpCteTbfg/iiv4k0UXFzz57RnY1O8X40vEVFVY8VjrJuJxxwDuZqidUZeLIdTMlmfdKWoD+NRDA== +"@standardnotes/snjs@2.7.10": + version "2.7.10" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.7.10.tgz#da92ed0ab8aca74ed885d2e1bec14c21ad03f4d2" + integrity sha512-aG0EOWOoybLXg3D9szoXsETNtYoaPSWzQBgrj14TwmENsJ70nLUW7TtzKwOny2hP6PegEFF3VdIE3tp7t5VGUg== dependencies: "@standardnotes/auth" "^2.0.0" "@standardnotes/sncrypto-common" "^1.2.9" From a9870214ea0b62381d759bff162e08804289b1c6 Mon Sep 17 00:00:00 2001 From: Gorjan Petrovski Date: Mon, 5 Jul 2021 16:57:37 +0200 Subject: [PATCH 09/14] feat: implement preferences pane --- app/assets/icons/ic-accessibility.svg | 3 + app/assets/icons/ic-help.svg | 3 + app/assets/icons/ic-keyboard.svg | 3 + app/assets/icons/ic-listed.svg | 3 + app/assets/icons/ic-security.svg | 3 + app/assets/icons/ic-settings-filled.svg | 3 + app/assets/icons/ic-star.svg | 3 + app/assets/icons/ic-themes.svg | 3 + app/assets/icons/ic-user.svg | 3 + app/assets/javascripts/app.ts | 16 +- app/assets/javascripts/components/Icon.tsx | 61 ++-- .../javascripts/components/IconButton.tsx | 53 ++++ .../components/PreferencesMenuItem.tsx | 23 ++ .../javascripts/components/TitleBar.tsx | 13 + .../components/preferences/index.tsx | 22 ++ .../components/preferences/mock-state.ts | 50 ++++ .../components/preferences/pane.tsx | 33 +++ .../components/preferences/view.tsx | 28 ++ .../ui_models/app_state/app_state.ts | 18 +- .../ui_models/app_state/preferences_state.ts | 26 ++ .../views/application/application-view.pug | 4 + .../javascripts/views/footer/footer_view.ts | 260 ++++++++++-------- app/assets/stylesheets/_main.scss | 6 + app/assets/stylesheets/_preferences.scss | 46 ++++ app/assets/stylesheets/_sn.scss | 59 ++-- app/assets/stylesheets/index.css.scss | 31 ++- package.json | 2 +- 27 files changed, 572 insertions(+), 206 deletions(-) create mode 100644 app/assets/icons/ic-accessibility.svg create mode 100644 app/assets/icons/ic-help.svg create mode 100644 app/assets/icons/ic-keyboard.svg create mode 100644 app/assets/icons/ic-listed.svg create mode 100644 app/assets/icons/ic-security.svg create mode 100644 app/assets/icons/ic-settings-filled.svg create mode 100644 app/assets/icons/ic-star.svg create mode 100644 app/assets/icons/ic-themes.svg create mode 100644 app/assets/icons/ic-user.svg create mode 100644 app/assets/javascripts/components/IconButton.tsx create mode 100644 app/assets/javascripts/components/PreferencesMenuItem.tsx create mode 100644 app/assets/javascripts/components/TitleBar.tsx create mode 100644 app/assets/javascripts/components/preferences/index.tsx create mode 100644 app/assets/javascripts/components/preferences/mock-state.ts create mode 100644 app/assets/javascripts/components/preferences/pane.tsx create mode 100644 app/assets/javascripts/components/preferences/view.tsx create mode 100644 app/assets/javascripts/ui_models/app_state/preferences_state.ts create mode 100644 app/assets/stylesheets/_preferences.scss diff --git a/app/assets/icons/ic-accessibility.svg b/app/assets/icons/ic-accessibility.svg new file mode 100644 index 000000000..de1e6249e --- /dev/null +++ b/app/assets/icons/ic-accessibility.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/icons/ic-help.svg b/app/assets/icons/ic-help.svg new file mode 100644 index 000000000..c312b7255 --- /dev/null +++ b/app/assets/icons/ic-help.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/icons/ic-keyboard.svg b/app/assets/icons/ic-keyboard.svg new file mode 100644 index 000000000..9a18af39c --- /dev/null +++ b/app/assets/icons/ic-keyboard.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/icons/ic-listed.svg b/app/assets/icons/ic-listed.svg new file mode 100644 index 000000000..03e347717 --- /dev/null +++ b/app/assets/icons/ic-listed.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/icons/ic-security.svg b/app/assets/icons/ic-security.svg new file mode 100644 index 000000000..badc9d1ad --- /dev/null +++ b/app/assets/icons/ic-security.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/icons/ic-settings-filled.svg b/app/assets/icons/ic-settings-filled.svg new file mode 100644 index 000000000..0a7c8b835 --- /dev/null +++ b/app/assets/icons/ic-settings-filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/icons/ic-star.svg b/app/assets/icons/ic-star.svg new file mode 100644 index 000000000..638dae331 --- /dev/null +++ b/app/assets/icons/ic-star.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/icons/ic-themes.svg b/app/assets/icons/ic-themes.svg new file mode 100644 index 000000000..88606ca76 --- /dev/null +++ b/app/assets/icons/ic-themes.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/icons/ic-user.svg b/app/assets/icons/ic-user.svg new file mode 100644 index 000000000..65ac58800 --- /dev/null +++ b/app/assets/icons/ic-user.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/javascripts/app.ts b/app/assets/javascripts/app.ts index 9cc5b8d46..01898de3c 100644 --- a/app/assets/javascripts/app.ts +++ b/app/assets/javascripts/app.ts @@ -65,6 +65,7 @@ import { NotesContextMenuDirective } from './components/NotesContextMenu'; import { NotesOptionsPanelDirective } from './components/NotesOptionsPanel'; import { IconDirective } from './components/Icon'; import { NoteTagsContainerDirective } from './components/NoteTagsContainer'; +import { PreferencesDirective } from './components/preferences'; function reloadHiddenFirefoxTab(): boolean { /** @@ -90,7 +91,7 @@ function reloadHiddenFirefoxTab(): boolean { const startApplication: StartApplication = async function startApplication( defaultSyncServerHost: string, bridge: Bridge, - nextVersionSyncServerHost: string, + nextVersionSyncServerHost: string ) { if (reloadHiddenFirefoxTab()) { return; @@ -161,7 +162,8 @@ const startApplication: StartApplication = async function startApplication( .directive('notesContextMenu', NotesContextMenuDirective) .directive('notesOptionsPanel', NotesOptionsPanelDirective) .directive('icon', IconDirective) - .directive('noteTagsContainer', NoteTagsContainerDirective); + .directive('noteTagsContainer', NoteTagsContainerDirective) + .directive('preferences', PreferencesDirective); // Filters angular.module('app').filter('trusted', ['$sce', trusted]); @@ -174,10 +176,12 @@ const startApplication: StartApplication = async function startApplication( Object.defineProperties(window, { application: { get: () => - (angular - .element(document) - .injector() - .get('mainApplicationGroup') as any).primaryApplication, + ( + angular + .element(document) + .injector() + .get('mainApplicationGroup') as any + ).primaryApplication, }, }); } diff --git a/app/assets/javascripts/components/Icon.tsx b/app/assets/javascripts/components/Icon.tsx index 78a874ab4..721c1cec5 100644 --- a/app/assets/javascripts/components/Icon.tsx +++ b/app/assets/javascripts/components/Icon.tsx @@ -13,40 +13,59 @@ import PasswordIcon from '../../icons/ic-textbox-password.svg'; import TrashSweepIcon from '../../icons/ic-trash-sweep.svg'; import MoreIcon from '../../icons/ic-more.svg'; import TuneIcon from '../../icons/ic-tune.svg'; + +import AccessibilityIcon from '../../icons/ic-accessibility.svg'; +import HelpIcon from '../../icons/ic-help.svg'; +import KeyboardIcon from '../../icons/ic-keyboard.svg'; +import ListedIcon from '../../icons/ic-listed.svg'; +import SecurityIcon from '../../icons/ic-security.svg'; +import SettingsFilledIcon from '../../icons/ic-settings-filled.svg'; +import StarIcon from '../../icons/ic-star.svg'; +import ThemesIcon from '../../icons/ic-themes.svg'; +import UserIcon from '../../icons/ic-user.svg'; + import { toDirective } from './utils'; const ICONS = { 'pencil-off': PencilOffIcon, 'rich-text': RichTextIcon, - 'trash': TrashIcon, - 'pin': PinIcon, - 'unpin': UnpinIcon, - 'archive': ArchiveIcon, - 'unarchive': UnarchiveIcon, - 'hashtag': HashtagIcon, + trash: TrashIcon, + pin: PinIcon, + unpin: UnpinIcon, + archive: ArchiveIcon, + unarchive: UnarchiveIcon, + hashtag: HashtagIcon, 'chevron-right': ChevronRightIcon, - 'restore': RestoreIcon, - 'close': CloseIcon, - 'password': PasswordIcon, + restore: RestoreIcon, + close: CloseIcon, + password: PasswordIcon, 'trash-sweep': TrashSweepIcon, - 'more': MoreIcon, - 'tune': TuneIcon, + more: MoreIcon, + tune: TuneIcon, + accessibility: AccessibilityIcon, + help: HelpIcon, + keyboard: KeyboardIcon, + listed: ListedIcon, + security: SecurityIcon, + 'settings-filled': SettingsFilledIcon, + star: StarIcon, + themes: ThemesIcon, + user: UserIcon, }; +export type IconType = keyof typeof ICONS; + type Props = { - type: keyof (typeof ICONS); - className: string; -} + type: IconType; + className?: string; +}; export const Icon: React.FC = ({ type, className }) => { const IconComponent = ICONS[type]; return ; }; -export const IconDirective = toDirective( - Icon, - { - type: '@', - className: '@', - } -); +export const IconDirective = toDirective(Icon, { + type: '@', + className: '@', +}); diff --git a/app/assets/javascripts/components/IconButton.tsx b/app/assets/javascripts/components/IconButton.tsx new file mode 100644 index 000000000..93d826c4e --- /dev/null +++ b/app/assets/javascripts/components/IconButton.tsx @@ -0,0 +1,53 @@ +import { FunctionComponent } from 'preact'; +import { Icon, IconType } from './Icon'; + +const ICON_BUTTON_TYPES: { + [type: string]: { className: string }; +} = { + normal: { + className: '', + }, + primary: { + className: 'info', + }, +}; + +export type IconButtonType = keyof typeof ICON_BUTTON_TYPES; + +interface IconButtonProps { + /** + * onClick - preventDefault is handled within the component + */ + onClick: () => void; + + type: IconButtonType; + + className?: string; + + iconType: IconType; +} + +/** + * CircleButton component with an icon for SPA + * preventDefault is already handled within the component + */ +export const IconButton: FunctionComponent = ({ + onClick, + type, + className, + iconType, +}) => { + const click = (e: MouseEvent) => { + e.preventDefault(); + onClick(); + }; + const typeProps = ICON_BUTTON_TYPES[type]; + return ( + + ); +}; diff --git a/app/assets/javascripts/components/PreferencesMenuItem.tsx b/app/assets/javascripts/components/PreferencesMenuItem.tsx new file mode 100644 index 000000000..eb872053a --- /dev/null +++ b/app/assets/javascripts/components/PreferencesMenuItem.tsx @@ -0,0 +1,23 @@ +import { Icon, IconType } from '@/components/Icon'; +import { FunctionComponent } from 'preact'; + +interface PreferencesMenuItemProps { + iconType: IconType; + label: string; + selected: boolean; + onClick: () => void; +} + +export const PreferencesMenuItem: FunctionComponent = + ({ iconType, label, selected, onClick }) => ( +
{ + e.preventDefault(); + onClick(); + }} + > + + {label} +
+ ); diff --git a/app/assets/javascripts/components/TitleBar.tsx b/app/assets/javascripts/components/TitleBar.tsx new file mode 100644 index 000000000..8cf9e9208 --- /dev/null +++ b/app/assets/javascripts/components/TitleBar.tsx @@ -0,0 +1,13 @@ +import { FunctionComponent } from 'preact'; + +export const TitleBar: FunctionComponent<{ className?: string }> = ({ + children, + className, +}) =>
{children}
; + +export const Title: FunctionComponent<{ className?: string }> = ({ + children, + className, +}) => { + return
{children}
; +}; diff --git a/app/assets/javascripts/components/preferences/index.tsx b/app/assets/javascripts/components/preferences/index.tsx new file mode 100644 index 000000000..7ad6bb318 --- /dev/null +++ b/app/assets/javascripts/components/preferences/index.tsx @@ -0,0 +1,22 @@ +import { observer } from 'mobx-react-lite'; +import { FunctionComponent } from 'preact'; + +import { toDirective } from '../utils'; +import { PreferencesView } from './view'; + +interface WrapperProps { + appState: { preferences: { isOpen: boolean; closePreferences: () => void } }; +} + +const PreferencesViewWrapper: FunctionComponent = observer( + ({ appState }) => { + if (!appState.preferences.isOpen) return null; + return ( + appState.preferences.closePreferences()} /> + ); + } +); + +export const PreferencesDirective = toDirective( + PreferencesViewWrapper +); diff --git a/app/assets/javascripts/components/preferences/mock-state.ts b/app/assets/javascripts/components/preferences/mock-state.ts new file mode 100644 index 000000000..dd018f243 --- /dev/null +++ b/app/assets/javascripts/components/preferences/mock-state.ts @@ -0,0 +1,50 @@ +import { IconType } from '@/components/Icon'; +import { action, computed, makeObservable, observable } from 'mobx'; + +interface PreferenceItem { + icon: IconType; + label: string; +} + +interface PreferenceListItem extends PreferenceItem { + id: number; +} + +const predefinedItems: PreferenceItem[] = [ + { label: 'General', icon: 'settings-filled' }, + { label: 'Account', icon: 'user' }, + { label: 'Appearance', icon: 'themes' }, + { label: 'Security', icon: 'security' }, + { label: 'Listed', icon: 'listed' }, + { label: 'Shortcuts', icon: 'keyboard' }, + { label: 'Accessibility', icon: 'accessibility' }, + { label: 'Get a free month', icon: 'star' }, + { label: 'Help & feedback', icon: 'help' }, +]; + +export class MockState { + private readonly _items: PreferenceListItem[]; + private _selectedId = 0; + + constructor(items: PreferenceItem[] = predefinedItems) { + makeObservable(this, { + _selectedId: observable, + items: computed, + select: action, + }); + + this._items = items.map((p, idx) => ({ ...p, id: idx })); + this._selectedId = this._items[0].id; + } + + select(id: number) { + this._selectedId = id; + } + + get items(): (PreferenceListItem & { selected: boolean })[] { + return this._items.map((p) => ({ + ...p, + selected: p.id === this._selectedId, + })); + } +} diff --git a/app/assets/javascripts/components/preferences/pane.tsx b/app/assets/javascripts/components/preferences/pane.tsx new file mode 100644 index 000000000..2738239ee --- /dev/null +++ b/app/assets/javascripts/components/preferences/pane.tsx @@ -0,0 +1,33 @@ +import { observer } from 'mobx-react-lite'; +import { FunctionComponent } from 'preact'; +import { PreferencesMenuItem } from '../PreferencesMenuItem'; +import { MockState } from './mock-state'; + +interface PreferencesMenuProps { + store: MockState; +} + +const PreferencesMenu: FunctionComponent = observer( + ({ store }) => ( +
+ {store.items.map((pref) => ( + store.select(pref.id)} + /> + ))} +
+ ) +); + +export const PreferencesPane: FunctionComponent = () => { + const store = new MockState(); + return ( +
+ +
+ ); +}; diff --git a/app/assets/javascripts/components/preferences/view.tsx b/app/assets/javascripts/components/preferences/view.tsx new file mode 100644 index 000000000..01ceb8773 --- /dev/null +++ b/app/assets/javascripts/components/preferences/view.tsx @@ -0,0 +1,28 @@ +import { IconButton } from '@/components/IconButton'; +import { TitleBar, Title } from '@/components/TitleBar'; +import { FunctionComponent } from 'preact'; +import { PreferencesPane } from './pane'; + +interface PreferencesViewProps { + close: () => void; +} + +export const PreferencesView: FunctionComponent = ({ + close, +}) => ( +
+ + {/* div is added so flex justify-between can center the title */} +
+ Your preferences for Standard Notes + { + close(); + }} + type="normal" + iconType="close" + /> + + +
+); 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 1c8191bd7..55851ede7 100644 --- a/app/assets/javascripts/ui_models/app_state/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state/app_state.ts @@ -22,6 +22,7 @@ import { SyncState } from './sync_state'; import { SearchOptionsState } from './search_options_state'; import { NotesState } from './notes_state'; import { TagsState } from './tags_state'; +import { PreferencesState } from './preferences_state'; export enum AppStateEvent { TagChanged, @@ -63,6 +64,7 @@ export class AppState { showBetaWarning: boolean; readonly accountMenu = new AccountMenuState(); readonly actionsMenu = new ActionsMenuState(); + readonly preferences = new PreferencesState(); readonly noAccountWarning: NoAccountWarningState; readonly noteTags: NoteTagsState; readonly sync = new SyncState(); @@ -89,21 +91,18 @@ export class AppState { async () => { await this.notifyEvent(AppStateEvent.ActiveEditorChanged); }, - this.appEventObserverRemovers, + this.appEventObserverRemovers ); this.noteTags = new NoteTagsState( application, this, this.appEventObserverRemovers ); - this.tags = new TagsState( - application, - this.appEventObserverRemovers, - ), - this.noAccountWarning = new NoAccountWarningState( - application, - this.appEventObserverRemovers - ); + (this.tags = new TagsState(application, this.appEventObserverRemovers)), + (this.noAccountWarning = new NoAccountWarningState( + application, + this.appEventObserverRemovers + )); this.searchOptions = new SearchOptionsState( application, this.appEventObserverRemovers @@ -128,6 +127,7 @@ export class AppState { makeObservable(this, { showBetaWarning: observable, isSessionsModalVisible: observable, + preferences: observable, enableBetaWarning: action, disableBetaWarning: action, diff --git a/app/assets/javascripts/ui_models/app_state/preferences_state.ts b/app/assets/javascripts/ui_models/app_state/preferences_state.ts new file mode 100644 index 000000000..607cd23e3 --- /dev/null +++ b/app/assets/javascripts/ui_models/app_state/preferences_state.ts @@ -0,0 +1,26 @@ +import { action, computed, makeObservable, observable } from 'mobx'; + +export class PreferencesState { + private _open = false; + + constructor() { + makeObservable(this, { + _open: observable, + openPreferences: action, + closePreferences: action, + isOpen: computed, + }); + } + + openPreferences = (): void => { + this._open = true; + }; + + closePreferences = (): void => { + this._open = false; + }; + + get isOpen() { + return this._open; + } +} diff --git a/app/assets/javascripts/views/application/application-view.pug b/app/assets/javascripts/views/application/application-view.pug index a1c08a28d..0f473bbea 100644 --- a/app/assets/javascripts/views/application/application-view.pug +++ b/app/assets/javascripts/views/application/application-view.pug @@ -26,6 +26,9 @@ application='self.application' app-state='self.appState' ) + preferences( + app-state='self.appState' + ) challenge-modal( ng-repeat="challenge in self.challenges track by challenge.id" class="sk-modal" @@ -36,3 +39,4 @@ notes-context-menu( app-state='self.appState' ) + diff --git a/app/assets/javascripts/views/footer/footer_view.ts b/app/assets/javascripts/views/footer/footer_view.ts index 64a1b2703..9764d3c2a 100644 --- a/app/assets/javascripts/views/footer/footer_view.ts +++ b/app/assets/javascripts/views/footer/footer_view.ts @@ -33,44 +33,47 @@ const ACCOUNT_SWITCHER_ENABLED = false; const ACCOUNT_SWITCHER_FEATURE_KEY = 'account_switcher'; type DockShortcut = { - name: string, - component: SNComponent, + name: string; + component: SNComponent; icon: { - type: string - background_color: string - border_color: string - } -} + type: string; + background_color: string; + border_color: string; + }; +}; -class FooterViewCtrl extends PureViewCtrl { - private $rootScope: ng.IRootScopeService - private rooms: SNComponent[] = [] - private themesWithIcons: SNTheme[] = [] - private showSyncResolution = false - private unregisterComponent: any - private rootScopeListener1: any - private rootScopeListener2: any - public arbitraryStatusMessage?: string - public user?: any - private offline = true - public showAccountMenu = false - private didCheckForOffline = false - private queueExtReload = false - private reloadInProgress = false - public hasError = false - public isRefreshing = false - public lastSyncDate?: string - public newUpdateAvailable = false - public dockShortcuts: DockShortcut[] = [] - public roomShowState: Partial> = {} +class FooterViewCtrl extends PureViewCtrl< + unknown, + { + outOfSync: boolean; + hasPasscode: boolean; + dataUpgradeAvailable: boolean; + dockShortcuts: DockShortcut[]; + hasAccountSwitcher: boolean; + showBetaWarning: boolean; + showDataUpgrade: boolean; + } +> { + private $rootScope: ng.IRootScopeService; + private rooms: SNComponent[] = []; + private themesWithIcons: SNTheme[] = []; + private showSyncResolution = false; + private unregisterComponent: any; + private rootScopeListener1: any; + private rootScopeListener2: any; + public arbitraryStatusMessage?: string; + public user?: any; + private offline = true; + public showAccountMenu = false; + private didCheckForOffline = false; + private queueExtReload = false; + private reloadInProgress = false; + public hasError = false; + public isRefreshing = false; + public lastSyncDate?: string; + public newUpdateAvailable = false; + public dockShortcuts: DockShortcut[] = []; + public roomShowState: Partial> = {}; private observerRemovers: Array<() => void> = []; private completedInitialSync = false; private showingDownloadStatus = false; @@ -117,7 +120,7 @@ class FooterViewCtrl extends PureViewCtrl { this.setState({ - dataUpgradeAvailable: available + dataUpgradeAvailable: available, }); }); } @@ -176,19 +181,25 @@ class FooterViewCtrl extends PureViewCtrl { - this.reloadExtendedData(); - }); - this.rootScopeListener2 = this.$rootScope.$on(RootScopeMessages.NewUpdateAvailable, () => { - this.$timeout(() => { - this.onNewUpdateAvailable(); - }); - }); + this.rootScopeListener1 = this.$rootScope.$on( + RootScopeMessages.ReloadExtendedData, + () => { + this.reloadExtendedData(); + } + ); + this.rootScopeListener2 = this.$rootScope.$on( + RootScopeMessages.NewUpdateAvailable, + () => { + this.$timeout(() => { + this.onNewUpdateAvailable(); + }); + } + ); } /** @override */ @@ -202,11 +213,11 @@ class FooterViewCtrl extends PureViewCtrl { - return ( - theme.package_info && - theme.package_info.dock_icon - ); + return theme.package_info && theme.package_info.dock_icon; } ); - this.observerRemovers.push(this.application.streamItems( - ContentType.Component, - async () => { - const components = this.application.getItems(ContentType.Component) as SNComponent[]; + this.observerRemovers.push( + this.application.streamItems(ContentType.Component, async () => { + const components = this.application.getItems( + ContentType.Component + ) as SNComponent[]; this.rooms = components.filter((candidate) => { return candidate.area === ComponentArea.Rooms && !candidate.deleted; }); @@ -308,33 +317,38 @@ class FooterViewCtrl extends PureViewCtrl { - const themes = this.application.getDisplayableItems(ContentType.Theme) as SNTheme[]; + this.observerRemovers.push( + this.application.streamItems(ContentType.Theme, async () => { + const themes = this.application.getDisplayableItems( + ContentType.Theme + ) as SNTheme[]; this.themesWithIcons = themes; this.reloadDockShortcuts(); - } - )); + }) + ); } registerComponentHandler() { - this.unregisterComponent = this.application.componentManager!.registerHandler({ - identifier: 'room-bar', - areas: [ComponentArea.Rooms, ComponentArea.Modal], - focusHandler: (component, focused) => { - if (component.isEditor() && focused) { - if (component.package_info?.identifier === 'org.standardnotes.standard-sheets') { - return; + this.unregisterComponent = + this.application.componentManager!.registerHandler({ + identifier: 'room-bar', + areas: [ComponentArea.Rooms, ComponentArea.Modal], + focusHandler: (component, focused) => { + if (component.isEditor() && focused) { + if ( + component.package_info?.identifier === + 'org.standardnotes.standard-sheets' + ) { + return; + } + this.closeAllRooms(); + this.closeAccountMenu(); } - this.closeAllRooms(); - this.closeAccountMenu(); - } - } - }); + }, + }); } updateSyncStatus() { @@ -354,17 +368,17 @@ class FooterViewCtrl extends PureViewCtrl 20) { - const completionPercentage = stats.uploadCompletionCount === 0 - ? 0 - : stats.uploadCompletionCount / stats.uploadTotalCount; + const completionPercentage = + stats.uploadCompletionCount === 0 + ? 0 + : stats.uploadCompletionCount / stats.uploadTotalCount; - const stringPercentage = completionPercentage.toLocaleString( - undefined, - { style: 'percent' } - ); + const stringPercentage = completionPercentage.toLocaleString(undefined, { + style: 'percent', + }); statusManager.setMessage( - `Syncing ${stats.uploadTotalCount} items (${stringPercentage} complete)`, + `Syncing ${stats.uploadTotalCount} items (${stringPercentage} complete)` ); } else { statusManager.setMessage(''); @@ -398,8 +412,10 @@ class FooterViewCtrl extends PureViewCtrl { - return room.package_info.identifier === this.application - .getNativeExtService().extManagerId; + return ( + room.package_info.identifier === + this.application.getNativeExtService().extManagerId + ); }); if (!extWindow) { this.queueExtReload = true; @@ -419,11 +435,13 @@ class FooterViewCtrl extends PureViewCtrl { await this.application.upgradeProtocolVersion(); }); @@ -453,25 +471,27 @@ class FooterViewCtrl extends PureViewCtrl { - this.$timeout(() => { - this.isRefreshing = false; - }, 200); - if (response && response.error) { - this.application.alertService!.alert( - STRING_GENERIC_SYNC_ERROR - ); - } else { - this.syncUpdated(); - } - }); + this.application + .sync({ + queueStrategy: SyncQueueStrategy.ForceSpawnNew, + checkIntegrity: true, + }) + .then((response) => { + this.$timeout(() => { + this.isRefreshing = false; + }, 200); + if (response && response.error) { + this.application.alertService!.alert(STRING_GENERIC_SYNC_ERROR); + } else { + this.syncUpdated(); + } + }); } syncUpdated() { - this.lastSyncDate = dateToLocalizedString(this.application.getLastSyncDate()!); + this.lastSyncDate = dateToLocalizedString( + this.application.getLastSyncDate()! + ); } onNewUpdateAvailable() { @@ -480,9 +500,7 @@ class FooterViewCtrl extends PureViewCtrlYou can silence this warning from the ' + - 'Account menu.' + 'Account menu.', }); } @@ -563,6 +581,10 @@ class FooterViewCtrl extends PureViewCtrl Date: Mon, 5 Jul 2021 17:03:34 +0200 Subject: [PATCH 10/14] feat: implement enableUnfinishedFeatures flag and hidden preferences button --- .env.sample | 1 + .../javascripts/ui_models/app_state/app_state.ts | 16 ++++++++-------- .../javascripts/views/footer/footer-view.pug | 5 +++++ app/views/application/app.html.erb | 1 + index.html | 2 ++ 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.env.sample b/.env.sample index 03888379e..66af6248e 100644 --- a/.env.sample +++ b/.env.sample @@ -16,6 +16,7 @@ SF_NEXT_VERSION_SERVER=http://localhost:3000 DEV_DEFAULT_SYNC_SERVER=https://sync.standardnotes.org DEV_NEXT_VERSION_SYNC_SERVER=https://api.standardnotes.com DEV_EXTENSIONS_MANAGER_LOCATION=public/extensions/extensions-manager/dist/index.html +ENABLE_UNFINISHED_FEATURES=false # NewRelic (Optional) NEW_RELIC_ENABLED=false 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 55851ede7..396968cf4 100644 --- a/app/assets/javascripts/ui_models/app_state/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state/app_state.ts @@ -1,4 +1,4 @@ -import { isDesktopApplication, isDev } from '@/utils'; +import { isDesktopApplication } from '@/utils'; import pull from 'lodash/pull'; import { ApplicationEvent, @@ -48,8 +48,8 @@ export enum EventSource { type ObserverCallback = (event: AppStateEvent, data?: any) => Promise; export class AppState { - readonly enableUnfinishedFeatures = - isDev || location.host.includes('app-dev.standardnotes.org'); + readonly enableUnfinishedFeatures: boolean = (window as any) + ?._enable_unfinished_features; $rootScope: ng.IRootScopeService; $timeout: ng.ITimeoutService; @@ -98,11 +98,11 @@ export class AppState { this, this.appEventObserverRemovers ); - (this.tags = new TagsState(application, this.appEventObserverRemovers)), - (this.noAccountWarning = new NoAccountWarningState( - application, - this.appEventObserverRemovers - )); + this.tags = new TagsState(application, this.appEventObserverRemovers); + this.noAccountWarning = new NoAccountWarningState( + application, + this.appEventObserverRemovers + ); this.searchOptions = new SearchOptionsState( application, this.appEventObserverRemovers diff --git a/app/assets/javascripts/views/footer/footer-view.pug b/app/assets/javascripts/views/footer/footer-view.pug index a4aa5c293..8abd9c47a 100644 --- a/app/assets/javascripts/views/footer/footer-view.pug +++ b/app/assets/javascripts/views/footer/footer-view.pug @@ -18,6 +18,11 @@ ng-if='ctrl.showAccountMenu', application='ctrl.application' ) + .sk-app-bar-item( + ng-click='ctrl.clickPreferences()' + ng-if='ctrl.appState.enableUnfinishedFeatures' + ) + .sk-label.title Preferences .sk-app-bar-item a.no-decoration.sk-label.title( href='https://standardnotes.com/help', diff --git a/app/views/application/app.html.erb b/app/views/application/app.html.erb index db302df40..d0018ed90 100644 --- a/app/views/application/app.html.erb +++ b/app/views/application/app.html.erb @@ -34,6 +34,7 @@ window._extensions_manager_location = "<%= ENV['EXTENSIONS_MANAGER_LOCATION'] %>"; window._batch_manager_location = "<%= ENV['BATCH_MANAGER_LOCATION'] %>"; window._bugsnag_api_key = "<%= ENV['BUGSNAG_API_KEY'] %>"; + window._enable_unfinished_features = "<%= ENV['ENABLE_UNFINISHED_FEATURES'] %>" <% if Rails.env.development? %> diff --git a/index.html b/index.html index a7cfd5561..c5ff27c9d 100644 --- a/index.html +++ b/index.html @@ -33,12 +33,14 @@ data-next-version-sync-server="<%= env.DEV_NEXT_VERSION_SYNC_SERVER || env.DEV_DEFAULT_SYNC_SERVER %>" data-extensions-manager-location="<%= env.DEV_EXTENSIONS_MANAGER_LOCATION %>" data-bugsnag-api-key="<%= env.DEV_BUGSNAG_API_KEY %>" + data-enable-unfinished-features="<%= env.ENABLE_UNFINISHED_FEATURES %>" > From 1be87cbef8819f2a946a7599a2c39ee478982f9b Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Mon, 5 Jul 2021 14:43:09 -0300 Subject: [PATCH 11/14] fix: disable delete note shortcut for inputs --- app/assets/javascripts/services/ioService.ts | 5 +++++ app/assets/javascripts/views/editor/editor_view.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/services/ioService.ts b/app/assets/javascripts/services/ioService.ts index bfc503dee..e1c775047 100644 --- a/app/assets/javascripts/services/ioService.ts +++ b/app/assets/javascripts/services/ioService.ts @@ -28,6 +28,7 @@ type KeyboardObserver = { elements?: HTMLElement[]; notElement?: HTMLElement; notElementIds?: string[]; + notTags?: string[]; }; export class IOService { @@ -175,6 +176,10 @@ export class IOService { continue; } + if (observer.notTags && observer.notTags.includes(target.tagName)) { + continue; + } + if ( this.eventMatchesKeyAndModifiers( event, diff --git a/app/assets/javascripts/views/editor/editor_view.ts b/app/assets/javascripts/views/editor/editor_view.ts index 822c4d50e..2e2936fac 100644 --- a/app/assets/javascripts/views/editor/editor_view.ts +++ b/app/assets/javascripts/views/editor/editor_view.ts @@ -863,7 +863,7 @@ class EditorViewCtrl extends PureViewCtrl { .io .addKeyObserver({ key: KeyboardKey.Backspace, - notElementIds: [ElementIds.NoteTextEditor, ElementIds.NoteTitleEditor], + notTags: ['INPUT', 'TEXTAREA'], modifiers: [KeyboardModifier.Meta], onKeyDown: () => { this.deleteNote(false); From ac90fa7169182520bdd9a52f9b7815dbaa121100 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Mon, 5 Jul 2021 15:22:42 -0300 Subject: [PATCH 12/14] chore(version-snjs): 2.7.13 --- package.json | 2 +- yarn.lock | 128 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 121 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 68d4b9f97..ad6d8a4d6 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@reach/checkbox": "^0.13.2", "@reach/dialog": "^0.13.0", "@standardnotes/sncrypto-web": "1.2.10", - "@standardnotes/snjs": "2.7.10", + "@standardnotes/snjs": "2.7.13", "mobx": "^6.1.6", "mobx-react-lite": "^3.2.0", "preact": "^10.5.12" diff --git a/yarn.lock b/yarn.lock index 8ac5a5994..24206977f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1826,6 +1826,14 @@ "@reach/utils" "0.14.0" tslib "^2.1.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/checkbox@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@reach/checkbox/-/checkbox-0.13.2.tgz#b972b922cf6cea0c2bbabca0129c58307b566a4e" @@ -1837,6 +1845,14 @@ prop-types "^15.7.2" tslib "^2.1.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/dialog@0.13.0", "@reach/dialog@^0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@reach/dialog/-/dialog-0.13.0.tgz#2110725c3b8a3c64685834cdc9f3ce5c15617809" @@ -1859,6 +1875,18 @@ prop-types "^15.7.2" tslib "^2.1.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== + 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/machine@0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@reach/machine/-/machine-0.13.2.tgz#744302f5ce2d4e5fd0527ae0baa60d325b2325d8" @@ -1868,6 +1896,44 @@ "@xstate/fsm" "1.4.0" tslib "^2.1.0" +"@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/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== + dependencies: + "@reach/auto-id" "0.15.2" + "@reach/descendants" "0.15.2" + "@reach/popover" "0.15.2" + "@reach/utils" "0.15.2" + prop-types "^15.7.2" + tiny-warning "^1.0.3" + tslib "^2.3.0" + +"@reach/observe-rect@1.2.0": + version "1.2.0" + 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/portal@0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.13.0.tgz#bed220d41097deb1454a7928b22529ba10d3ea2b" @@ -1876,6 +1942,25 @@ "@reach/utils" "0.13.0" tslib "^2.0.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/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/utils@0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.13.0.tgz#2da775a910d8894bb34e1e94fe95842674f71844" @@ -1903,6 +1988,14 @@ tslib "^2.1.0" warning "^4.0.3" +"@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/visually-hidden@0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.13.0.tgz#cace36d9bb80ffb797374fcaea989391b881038f" @@ -1936,10 +2029,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@2.7.10": - version "2.7.10" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.7.10.tgz#da92ed0ab8aca74ed885d2e1bec14c21ad03f4d2" - integrity sha512-aG0EOWOoybLXg3D9szoXsETNtYoaPSWzQBgrj14TwmENsJ70nLUW7TtzKwOny2hP6PegEFF3VdIE3tp7t5VGUg== +"@standardnotes/snjs@2.7.13": + version "2.7.13" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.7.13.tgz#8a48e631cabd8d3a18db4070b72db1992a26272d" + integrity sha512-7Nz05gV5tc4F/bHxDoaIN0bVwjrcI/WxRZ/BZ4Em8CTbHxMnsPvO+DTr9I0mUgquKIHbzCIGvfKk4oSOHleU2Q== dependencies: "@standardnotes/auth" "^2.0.0" "@standardnotes/sncrypto-common" "^1.2.9" @@ -7815,10 +7908,14 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -sn-stylekit@5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/sn-stylekit/-/sn-stylekit-5.2.1.tgz#d56a38017d6b45f5c2ebcf7b2c2db94c50a26e27" - integrity sha512-kupuH9XlPy5TuO2a2E+sLQnF41VQ0a4cwHRltNhQSI6O135n4HkkDYgyEAvy5DKcc0aun4KHy5mz9kYefQvciw== +sn-stylekit@5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/sn-stylekit/-/sn-stylekit-5.2.3.tgz#24246471c03cde5129bda51a08fabef4d3c4880c" + integrity sha512-hzziH89IY2UjmGh8OYgapb+/QVD6P6NNjnoyzSyveOh671MM9Z4IaPLZTJckgxJVjV0q7G495Pxfta5r4CSRDQ== + dependencies: + "@reach/listbox" "^0.15.0" + "@reach/menu-button" "^0.15.1" + prop-types "^15.7.2" snapdragon-node@^2.0.1: version "2.1.1" @@ -8266,6 +8363,11 @@ svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" +tabbable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261" + integrity sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ== + table@^6.0.4: version "6.0.7" resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" @@ -8339,6 +8441,11 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -8437,6 +8544,11 @@ tslib@^2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== +tslib@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" From f9b25624a83f525af71fd2292ef85e27efab096a Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Mon, 5 Jul 2021 16:38:46 -0300 Subject: [PATCH 13/14] chore(version-snjs): 2.7.14 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ad6d8a4d6..98fcdfbf6 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@reach/checkbox": "^0.13.2", "@reach/dialog": "^0.13.0", "@standardnotes/sncrypto-web": "1.2.10", - "@standardnotes/snjs": "2.7.13", + "@standardnotes/snjs": "2.7.14", "mobx": "^6.1.6", "mobx-react-lite": "^3.2.0", "preact": "^10.5.12" diff --git a/yarn.lock b/yarn.lock index 24206977f..213d81525 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2029,10 +2029,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@2.7.13": - version "2.7.13" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.7.13.tgz#8a48e631cabd8d3a18db4070b72db1992a26272d" - integrity sha512-7Nz05gV5tc4F/bHxDoaIN0bVwjrcI/WxRZ/BZ4Em8CTbHxMnsPvO+DTr9I0mUgquKIHbzCIGvfKk4oSOHleU2Q== +"@standardnotes/snjs@2.7.14": + version "2.7.14" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.7.14.tgz#3c1e57a53cfe61957bbcb253281c5c43611c9acf" + integrity sha512-xh71KLOCjodmVdrnNT0zfChB4fy3FaWMvWoh/5iso+myI6tQ8X59+gUM+VuNk9N9rwyItiBvq88BD82RUia8uQ== dependencies: "@standardnotes/auth" "^2.0.0" "@standardnotes/sncrypto-common" "^1.2.9" From a71e60c6d1da923f9c459c7366c2ca8c344b5dd2 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Mon, 5 Jul 2021 15:51:22 -0300 Subject: [PATCH 14/14] chore(version): 3.8.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 98fcdfbf6..fa91f7f11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "standard-notes-web", - "version": "3.8.13", + "version": "3.8.14", "license": "AGPL-3.0-or-later", "repository": { "type": "git",