diff --git a/app/assets/javascripts/components/AccountMenu/GeneralAccountMenu.tsx b/app/assets/javascripts/components/AccountMenu/GeneralAccountMenu.tsx index 706b85e3c..526ddf8d9 100644 --- a/app/assets/javascripts/components/AccountMenu/GeneralAccountMenu.tsx +++ b/app/assets/javascripts/components/AccountMenu/GeneralAccountMenu.tsx @@ -24,23 +24,23 @@ export const GeneralAccountMenu: FunctionComponent = observer( ({ application, appState, setMenuPane, closeMenu }) => { const [isSyncingInProgress, setIsSyncingInProgress] = useState(false); const [lastSyncDate, setLastSyncDate] = useState( - formatLastSyncDate(application.getLastSyncDate() as Date) + formatLastSyncDate(application.sync.getLastSyncDate() as Date) ); const doSynchronization = async () => { setIsSyncingInProgress(true); - application + application.sync .sync({ queueStrategy: SyncQueueStrategy.ForceSpawnNew, checkIntegrity: true, }) .then((res) => { - if (res && res.error) { + if (res && (res as any).error) { throw new Error(); } else { setLastSyncDate( - formatLastSyncDate(application.getLastSyncDate() as Date) + formatLastSyncDate(application.sync.getLastSyncDate() as Date) ); } }) diff --git a/app/assets/javascripts/components/ApplicationView.tsx b/app/assets/javascripts/components/ApplicationView.tsx index 71b467ed3..2cfc18f39 100644 --- a/app/assets/javascripts/components/ApplicationView.tsx +++ b/app/assets/javascripts/components/ApplicationView.tsx @@ -145,7 +145,7 @@ export class ApplicationView extends PureComponent { this.setState({ appClass }); } else if (eventName === AppStateEvent.WindowDidFocus) { if (!(await this.application.isLocked())) { - this.application.sync(); + this.application.sync.sync(); } } } diff --git a/app/assets/javascripts/components/Footer.tsx b/app/assets/javascripts/components/Footer.tsx index d04d7a194..b96437a79 100644 --- a/app/assets/javascripts/components/Footer.tsx +++ b/app/assets/javascripts/components/Footer.tsx @@ -256,7 +256,7 @@ export class Footer extends PureComponent { updateSyncStatus() { const statusManager = this.application.getStatusManager(); - const syncStatus = this.application.getSyncStatus(); + const syncStatus = this.application.sync.getSyncStatus(); const stats = syncStatus.getStats(); if (syncStatus.hasError()) { statusManager.setMessage('Unable to Sync'); @@ -290,7 +290,7 @@ export class Footer extends PureComponent { updateLocalDataStatus() { const statusManager = this.application.getStatusManager(); - const syncStatus = this.application.getSyncStatus(); + const syncStatus = this.application.sync.getSyncStatus(); const stats = syncStatus.getStats(); const encryption = this.application.isEncryptionAvailable(); if (stats.localDataDone) { @@ -312,7 +312,7 @@ export class Footer extends PureComponent { findErrors() { this.setState({ - hasError: this.application.getSyncStatus().hasError(), + hasError: this.application.sync.getSyncStatus().hasError(), }); } diff --git a/app/assets/javascripts/components/NoteView/NoteView.tsx b/app/assets/javascripts/components/NoteView/NoteView.tsx index 49e881e45..4de1ad6a9 100644 --- a/app/assets/javascripts/components/NoteView/NoteView.tsx +++ b/app/assets/javascripts/components/NoteView/NoteView.tsx @@ -681,7 +681,7 @@ export class NoteView extends PureComponent { if (left !== undefined && left !== null) { await this.application.setPreference(PrefKey.EditorLeft, left); } - this.application.sync(); + this.application.sync.sync(); }; async reloadSpellcheck() { @@ -797,7 +797,7 @@ export class NoteView extends PureComponent { } else { await this.disassociateComponentWithCurrentNote(component); } - this.application.sync(); + this.application.sync.sync(); }; async disassociateComponentWithCurrentNote(component: SNComponent) { diff --git a/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx b/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx index 7ca59b382..fad58fbae 100644 --- a/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx +++ b/app/assets/javascripts/components/NotesOptions/changeEditor/ChangeEditorMenu.tsx @@ -153,7 +153,7 @@ export const ChangeEditorMenu: FunctionComponent = ({ await application.runTransactionalMutations(transactions); /** Dirtying can happen above */ - application.sync(); + application.sync.sync(); setCurrentEditor(application.componentManager.editorForNote(note)); }; diff --git a/app/assets/javascripts/components/SyncResolutionMenu.tsx b/app/assets/javascripts/components/SyncResolutionMenu.tsx index 30a4eaaa4..d2a058e82 100644 --- a/app/assets/javascripts/components/SyncResolutionMenu.tsx +++ b/app/assets/javascripts/components/SyncResolutionMenu.tsx @@ -1,6 +1,5 @@ import { WebApplication } from '@/ui_models/application'; import { PureComponent } from './Abstract/PureComponent'; -import { Fragment } from 'preact'; type Props = { application: WebApplication; @@ -8,43 +7,13 @@ type Props = { }; export class SyncResolutionMenu extends PureComponent { - private status: Partial<{ - backupFinished: boolean; - resolving: boolean; - attemptedResolution: boolean; - success: boolean; - fail: boolean; - }> = {}; - constructor(props: Props) { super(props, props.application); } - downloadBackup(encrypted: boolean) { - this.props.application.getArchiveService().downloadBackup(encrypted); - this.status.backupFinished = true; - } - - skipBackup() { - this.status.backupFinished = true; - } - - async performSyncResolution() { - this.status.resolving = true; - await this.props.application.resolveOutOfSync(); - - this.status.resolving = false; - this.status.attemptedResolution = true; - if (this.props.application.isOutOfSync()) { - this.status.fail = true; - } else { - this.status.success = true; - } - } - - close() { + close = () => { this.props.close(); - } + }; render() { return ( @@ -59,13 +28,15 @@ export class SyncResolutionMenu extends PureComponent {
- We've detected that the data on the server may not match the - data in the current application session. + We've detected that the data in the current application session + may not match the data on the server. An attempt was made to + auto-resolve the issue, but it was unable to reconcile the + differences.
- Option 1 — Restart App: + Option 1 — Restart Application:
Quit the application and re-open it. Sometimes, this may @@ -76,108 +47,15 @@ export class SyncResolutionMenu extends PureComponent {
- Option 2 (recommended) — Sign Out: + Option 2 — Sign Out and Back In:
Sign out of your account, then sign back in. This will - ensure your data is consistent with the server. -
- Be sure to download a backup of your data before doing so. -
-
-
-
- - Option 3 — Sync Resolution: - -
- We can attempt to reconcile changes by downloading all data - from the server. No existing data will be overwritten. If - the local contents of an item differ from what the server - has, a conflicted copy will be created. + ensure your data is consistent with the server. Be sure to + download a backup of your data before doing so.
- {!this.status.backupFinished && ( - -
- Please download a backup before we attempt to perform a full - account sync resolution. -
-
-
- - - -
-
-
- )} - - {this.status.backupFinished && ( -
- {!this.status.resolving && !this.status.attemptedResolution && ( -
- -
- )} - {this.status.resolving && ( -
-
-
-
- Attempting sync resolution... -
-
-
- )} - {this.status.fail && ( -
-
- Sync Resolution Failed -
-
- We attempted to reconcile local content and server - content, but were unable to do so. At this point, we - recommend signing out of your account and signing back - in. You may wish to download a data backup before doing - so. -
-
- )} - {this.status.success && ( -
-
- Sync Resolution Success -
-
- Your local data is now in sync with the server. You may - close this window. -
-
- )} -
- )}
diff --git a/app/assets/javascripts/preferences/panes/Extensions.tsx b/app/assets/javascripts/preferences/panes/Extensions.tsx index b70f06e73..459bb7a22 100644 --- a/app/assets/javascripts/preferences/panes/Extensions.tsx +++ b/app/assets/javascripts/preferences/panes/Extensions.tsx @@ -74,7 +74,7 @@ export const Extensions: FunctionComponent<{ const confirmExtension = async () => { await application.insertItem(confirmableExtension as SNComponent); - application.sync(); + application.sync.sync(); setExtensions(loadExtensions(application)); }; diff --git a/app/assets/javascripts/preferences/panes/account/Sync.tsx b/app/assets/javascripts/preferences/panes/account/Sync.tsx index b7d6147bd..3e51f0383 100644 --- a/app/assets/javascripts/preferences/panes/account/Sync.tsx +++ b/app/assets/javascripts/preferences/panes/account/Sync.tsx @@ -24,22 +24,22 @@ export const Sync: FunctionComponent = observer( ({ application }: Props) => { const [isSyncingInProgress, setIsSyncingInProgress] = useState(false); const [lastSyncDate, setLastSyncDate] = useState( - formatLastSyncDate(application.getLastSyncDate() as Date) + formatLastSyncDate(application.sync.getLastSyncDate() as Date) ); const doSynchronization = async () => { setIsSyncingInProgress(true); - const response = await application.sync({ + const response = await application.sync.sync({ queueStrategy: SyncQueueStrategy.ForceSpawnNew, checkIntegrity: true, }); setIsSyncingInProgress(false); - if (response && response.error) { - application.alertService!.alert(STRING_GENERIC_SYNC_ERROR); + if (response && (response as any).error) { + application.alertService.alert(STRING_GENERIC_SYNC_ERROR); } else { setLastSyncDate( - formatLastSyncDate(application.getLastSyncDate() as Date) + formatLastSyncDate(application.sync.getLastSyncDate() as Date) ); } }; 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 2e86701e9..ecd81c7af 100644 --- a/app/assets/javascripts/ui_models/app_state/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state/app_state.ts @@ -381,7 +381,7 @@ export class AppState { } break; case ApplicationEvent.SyncStatusChanged: - this.sync.update(this.application.getSyncStatus()); + this.sync.update(this.application.sync.getSyncStatus()); break; } }); 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 4ae9200b4..25677e602 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 @@ -181,7 +181,7 @@ export class NoteTagsState { if (activeNote) { await this.application.addTagHierarchyToNote(activeNote, tag); - this.application.sync(); + this.application.sync.sync(); this.reloadTags(); } } @@ -192,7 +192,7 @@ export class NoteTagsState { await this.application.changeItem(tag.uuid, (mutator) => { mutator.removeItemAsRelationship(activeNote); }); - this.application.sync(); + this.application.sync.sync(); this.reloadTags(); } } 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 93f10ecea..47ded4d4a 100644 --- a/app/assets/javascripts/ui_models/app_state/notes_state.ts +++ b/app/assets/javascripts/ui_models/app_state/notes_state.ts @@ -265,7 +265,7 @@ export class NotesState { mutate, false ); - this.application.sync(); + this.application.sync.sync(); } setHideSelectedNotePreviews(hide: boolean): void { @@ -403,7 +403,7 @@ export class NotesState { }, false ); - this.application.sync(); + this.application.sync.sync(); } async addTagToSelectedNotes(tag: SNTag): Promise { @@ -419,7 +419,7 @@ export class NotesState { }); }) ); - this.application.sync(); + this.application.sync.sync(); } async removeTagFromSelectedNotes(tag: SNTag): Promise { @@ -429,7 +429,7 @@ export class NotesState { mutator.removeItemAsRelationship(note); } }); - this.application.sync(); + this.application.sync.sync(); } isTagInSelectedNotes(tag: SNTag): boolean { @@ -453,7 +453,7 @@ export class NotesState { }) ) { this.application.emptyTrash(); - this.application.sync(); + this.application.sync.sync(); } } 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 05dac66bb..c8d4be798 100644 --- a/app/assets/javascripts/ui_models/app_state/tags_state.ts +++ b/app/assets/javascripts/ui_models/app_state/tags_state.ts @@ -208,7 +208,7 @@ export class TagsState { this.assignParent(createdTag.uuid, parent.uuid); - this.application.sync(); + this.application.sync.sync(); runInAction(() => { this.selected = createdTag as SNTag; @@ -364,7 +364,7 @@ export class TagsState { await this.application.setTagParent(futureParent, tag); } - await this.application.sync(); + await this.application.sync.sync(); } get rootTags(): SNTag[] { @@ -507,7 +507,7 @@ export class TagsState { } const insertedTag = await this.application.createTagOrSmartView(newTitle); - this.application.sync(); + this.application.sync.sync(); runInAction(() => { this.selected = insertedTag as SNTag; }); diff --git a/package.json b/package.json index b591d8189..0fbf27403 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,8 @@ "@babel/preset-typescript": "^7.16.7", "@reach/disclosure": "^0.16.2", "@reach/visually-hidden": "^0.16.0", - "@standardnotes/responses": "^1.1.7", - "@standardnotes/services": "^1.4.0", + "@standardnotes/responses": "^1.2.0", + "@standardnotes/services": "^1.5.0", "@standardnotes/stylekit": "5.14.0", "@svgr/webpack": "^6.2.1", "@types/jest": "^27.4.1", @@ -80,13 +80,13 @@ "@reach/tooltip": "^0.16.2", "@standardnotes/components": "1.7.9", "@standardnotes/features": "1.34.1", - "@standardnotes/settings": "^1.11.5", + "@standardnotes/settings": "^1.12.0", "@standardnotes/sncrypto-web": "1.7.3", - "@standardnotes/snjs": "2.73.2", + "@standardnotes/snjs": "2.76.0", "mobx": "^6.4.2", "mobx-react-lite": "^3.3.0", "preact": "^10.6.6", - "qrcode.react": "^1.0.1", + "qrcode.react": "^2.0.0", "react-dnd": "^15.1.1", "react-dnd-html5-backend": "^15.1.2", "react-dnd-touch-backend": "^15.1.1" diff --git a/yarn.lock b/yarn.lock index 399002bf2..d3f7531ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2331,10 +2331,10 @@ resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.9.tgz#41e5fdbcee250b9b3c18045dad8998c6f668307b" integrity sha512-/+Paw6ry/IS9ldYUM/lgC4O6qwl1fukWvNw65IMKyB9LMY3+xTh/I2BfnWynP117pVPxtu3/2+FBEnx04KvQwg== -"@standardnotes/domain-events@^2.23.21": - version "2.23.21" - resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.21.tgz#bbf752ee7a0fd08b9fb675e81b46d3c10bbf89e9" - integrity sha512-YPpwy+QrDziBOpjt5cOIZwY47fOddN3038+NTRSqxi4h/D8hU+U5O8dGl2XktENEq9DqVJ78OVmWBjkA2FlsEQ== +"@standardnotes/domain-events@^2.23.22": + version "2.23.22" + resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.22.tgz#eb246cc3d8e69af7014678f5aac34fa1d7b494a0" + integrity sha512-mtw1nFZ/laiMisjTNBXgCsu6RLG/zkW4VtvnKjodG2TEJV3zPxFALGRUnsIlSlwt3YdClzg073sKHtUn4s+sAw== dependencies: "@standardnotes/auth" "^3.17.3" "@standardnotes/features" "^1.34.1" @@ -2347,39 +2347,40 @@ "@standardnotes/auth" "^3.17.3" "@standardnotes/common" "^1.15.3" -"@standardnotes/payloads@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.3.2.tgz#3255abf6e2a2385c73e7998705066b828e5a74e0" - integrity sha512-SnDqdQXyEWett/Y33crvNnDGwv4BfCkoHId99fLd+UL5uTgXpuFgkd/AVHg+mOT5xC3+KAR8zdUCmQSXTRuysg== +"@standardnotes/payloads@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.4.0.tgz#e1a5415708c9d462c4f5f4824f7effd7e9d7f791" + integrity sha512-gAOj3p9KPsQggZ2SjeMjh4XTkTy8ntUYD23kYKbLA/Z7ArCCp8LnZZHASII2kEznaK+vrUAqlSM2/oKwQlohDA== dependencies: "@standardnotes/applications" "^1.1.3" "@standardnotes/common" "^1.15.3" "@standardnotes/features" "^1.34.1" "@standardnotes/utils" "^1.2.3" -"@standardnotes/responses@^1.1.7": - version "1.1.7" - resolved "https://registry.yarnpkg.com/@standardnotes/responses/-/responses-1.1.7.tgz#ab982f94693f2e1f967809bdb5e3863182770b14" - integrity sha512-1q8+eGjvttleesciHAOTe6u478W3UpEy+0StT8ZL3miFWzIyCLXJmnxNbYfYCm6oZ+t2rwhW+AzmnMRhG2cOUA== +"@standardnotes/responses@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@standardnotes/responses/-/responses-1.2.0.tgz#fe295b31751dbc692bb65c8e162972127fb990b2" + integrity sha512-YuVJQlB4ipdqAlAtD0xPhbHSR38fPzcRbSkntaCadHeAZl7WAdDDf/7pxTCDwhXN8Hls9OXlrq+WNbhorpe0tw== dependencies: "@standardnotes/auth" "^3.17.3" "@standardnotes/common" "^1.15.3" "@standardnotes/features" "^1.34.1" - "@standardnotes/payloads" "^1.3.2" + "@standardnotes/payloads" "^1.4.0" -"@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== +"@standardnotes/services@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.5.0.tgz#ab71393d947bf52a7fb682d8bbcc190acef8fe97" + integrity sha512-vZ7NmV3SVdt5UQDCJ+OsoGtMFr0wsmHBdXpyb8s4rRnR4PgmJsrhuGXEu0t23EyLilL+Yb6WtkfJQhXeQsiT9w== dependencies: "@standardnotes/applications" "^1.1.3" "@standardnotes/common" "^1.15.3" + "@standardnotes/responses" "^1.2.0" "@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/settings@^1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.12.0.tgz#43f3dd7f015f726b1ed88a48fcc3737899116cd5" + integrity sha512-w6S5TT7KRpvUb+JsXZ7ucWPjlWRtpKQdsyT7cLs66ynKRXxUn40hf4kA8T9FhuLAKbG+wIYDrAZl3FRk+HvDWQ== "@standardnotes/sncrypto-common@^1.7.3": version "1.7.3" @@ -2395,20 +2396,20 @@ buffer "^6.0.3" libsodium-wrappers "^0.7.9" -"@standardnotes/snjs@2.73.2": - version "2.73.2" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.73.2.tgz#5361d73c861b990d06821d5a822dcb0893830a43" - integrity sha512-oGPZmzX+tNWQFxmvrQRtsqlofbW25YUOapyEPN8oVgfwV98r8EVzpUGXHWkog3ZW6oO3aO22Rhtk0D92d0CqtQ== +"@standardnotes/snjs@2.76.0": + version "2.76.0" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.76.0.tgz#61cfa03bea5e624529b7bbdd67646b4184ea30b3" + integrity sha512-SWSCMbDsJhdxNpHFHdK60iqaAsgvozvX8pgcAekko+yPlw3kz5Ucp+wwQbiznQRwrxOZPPrG/1NkJa1U/wWcdA== dependencies: "@standardnotes/applications" "^1.1.3" "@standardnotes/auth" "^3.17.3" "@standardnotes/common" "^1.15.3" - "@standardnotes/domain-events" "^2.23.21" + "@standardnotes/domain-events" "^2.23.22" "@standardnotes/features" "^1.34.1" - "@standardnotes/payloads" "^1.3.2" - "@standardnotes/responses" "^1.1.7" - "@standardnotes/services" "^1.4.0" - "@standardnotes/settings" "^1.11.5" + "@standardnotes/payloads" "^1.4.0" + "@standardnotes/responses" "^1.2.0" + "@standardnotes/services" "^1.5.0" + "@standardnotes/settings" "^1.12.0" "@standardnotes/sncrypto-common" "^1.7.3" "@standardnotes/utils" "^1.2.3" @@ -8002,10 +8003,10 @@ qr.js@0.0.0: resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8= -qrcode.react@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-1.0.1.tgz#2834bb50e5e275ffe5af6906eff15391fe9e38a5" - integrity sha512-8d3Tackk8IRLXTo67Y+c1rpaiXjoz/Dd2HpcMdW//62/x8J1Nbho14Kh8x974t9prsLHN6XqVgcnRiBGFptQmg== +qrcode.react@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-2.0.0.tgz#20b738eddcfc6958673bbbd1a0c5568ee5c399f5" + integrity sha512-1CCzwC4KHYCzOLb7M+lKYqHzDMVsppKJBhrU1ZDCuJRHKiD99LeDHOkuvUKCRvnJgDzp9SnB6/WNA7qp6I7ozA== dependencies: loose-envify "^1.4.0" prop-types "^15.6.0"