diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index 10a9fd367..2f53b42ac 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -342,13 +342,6 @@ class AccountMenuCtrl extends PureViewCtrl { } } - async submitImportPassword() { - await this.performImport( - this.getState().importData.data, - this.getState().importData.password - ); - } - showRegister() { this.setFormDataState({ showRegister: true @@ -384,73 +377,52 @@ class AccountMenuCtrl extends PureViewCtrl { if (data.version || data.auth_params || data.keyParams) { const version = data.version || data.keyParams?.version || data.auth_params?.version; if ( - !this.application!.protocolService!.supportedVersions().includes(version) + this.application.protocolService.supportedVersions().includes(version) ) { - await this.setState({ importData: null }); - alertDialog({ text: STRING_UNSUPPORTED_BACKUP_FILE_VERSION }); - return; - } - if (data.keyParams || data.auth_params) { - await this.setState({ - importData: { - ...this.getState().importData, - requestPassword: true, - data, - } - }); - const element = document.getElementById( - ELEMENT_ID_IMPORT_PASSWORD_INPUT - ); - if (element) { - element.scrollIntoView(false); - } + await this.performImport(data); } else { - await this.performImport(data, undefined); + await this.setState({ importData: null }); + void alertDialog({ text: STRING_UNSUPPORTED_BACKUP_FILE_VERSION }); } } else { - await this.performImport(data, undefined); + await this.performImport(data); } } - async performImport(data: BackupFile, password?: string) { - if (!(await this.application.authorizeFileImport())) { - return; - } + async performImport(data: BackupFile) { await this.setState({ importData: { ...this.getState().importData, loading: true } }); - const result = await this.application!.importData( - data, - password - ); + const result = await this.application.importData(data); this.setState({ importData: null }); - if ('error' in result) { - this.application!.alertService!.alert( - result.error - ); + if (!result) { + return; + } else if ('error' in result) { + void alertDialog({ + text: result.error + }); } else if (result.errorCount) { - const message = StringImportError(result.errorCount); - this.application!.alertService!.alert( - message - ); + void alertDialog({ + text: StringImportError(result.errorCount) + }); } else { - this.application!.alertService!.alert( - STRING_IMPORT_SUCCESS - ); + void alertDialog({ + text: STRING_IMPORT_SUCCESS + }); } } async downloadDataArchive() { - this.application!.getArchiveService().downloadBackup(this.getState().mutable.backupEncrypted); + this.application.getArchiveService().downloadBackup(this.getState().mutable.backupEncrypted); } notesAndTagsCount() { - return this.application!.getItems( + return this.application.getItems( [ ContentType.Note, ContentType.Tag diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index e41ffcb7c..dca220cc9 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -10,7 +10,6 @@ import { UuidString, SyncOpStatus, PrefKey, - Challenge, } from '@standardnotes/snjs'; import { WebApplication } from '@/ui_models/application'; import { Editor } from '@/ui_models/editor'; @@ -28,6 +27,11 @@ export enum AppStateEvent { WindowDidBlur, } +export type PanelResizedData = { + panel: string; + collapsed: boolean; +} + export enum EventSource { UserInteraction, Script, @@ -392,10 +396,11 @@ export class AppState { } panelDidResize(name: string, collapsed: boolean) { - this.notifyEvent(AppStateEvent.PanelResized, { + const data: PanelResizedData = { panel: name, collapsed: collapsed, - }); + }; + this.notifyEvent(AppStateEvent.PanelResized, data); } editorDidFocus(eventSource: EventSource) { diff --git a/app/assets/javascripts/views/application/application-view.pug b/app/assets/javascripts/views/application/application-view.pug index 59eea6acc..91f15b7fd 100644 --- a/app/assets/javascripts/views/application/application-view.pug +++ b/app/assets/javascripts/views/application/application-view.pug @@ -28,7 +28,7 @@ application='self.application' ) challenge-modal( - ng-repeat="challenge in self.state.challenges track by challenge.id" + ng-repeat="challenge in self.challenges track by challenge.id" class="sk-modal" application="self.application" challenge="challenge" diff --git a/app/assets/javascripts/views/application/application_view.ts b/app/assets/javascripts/views/application/application_view.ts index 9e3223253..3dbf4ab91 100644 --- a/app/assets/javascripts/views/application/application_view.ts +++ b/app/assets/javascripts/views/application/application_view.ts @@ -2,8 +2,8 @@ import { RootScopeMessages } from './../../messages'; import { WebDirective } from '@/types'; import { getPlatformString } from '@/utils'; import template from './application-view.pug'; -import { AppStateEvent } from '@/ui_models/app_state'; -import { ApplicationEvent, Challenge } from '@standardnotes/snjs'; +import { AppStateEvent, PanelResizedData } from '@/ui_models/app_state'; +import { ApplicationEvent, Challenge, removeFromArray } from '@standardnotes/snjs'; import { PANEL_NAME_NOTES, PANEL_NAME_TAGS @@ -18,18 +18,20 @@ class ApplicationViewCtrl extends PureViewCtrl { - private $location?: ng.ILocationService - private $rootScope?: ng.IRootScopeService public platformString: string private notesCollapsed = false private tagsCollapsed = false + /** + * To prevent stale state reads (setState is async), + * challenges is a mutable array + */ + private challenges: Challenge[] = []; /* @ngInject */ constructor( - $location: ng.ILocationService, - $rootScope: ng.IRootScopeService, + private $location: ng.ILocationService, + private $rootScope: ng.IRootScopeService, $timeout: ng.ITimeoutService ) { super($timeout); @@ -43,8 +45,8 @@ class ApplicationViewCtrl extends PureViewCtrl { - - this.setState({ - challenges: this.state.challenges.concat(challenge) + this.$timeout(() => { + this.challenges.push(challenge); }); } }); - await this.application!.launch(); + await this.application.launch(); } - public removeChallenge(challenge: Challenge) { - this.setState({ - challenges: this.state.challenges.filter(c => c.id !== challenge.id) + public async removeChallenge(challenge: Challenge) { + this.$timeout(() => { + removeFromArray(this.challenges, challenge); }); } @@ -90,7 +91,7 @@ class ApplicationViewCtrl extends PureViewCtrl 0) { + if (event.dataTransfer?.files.length) { event.preventDefault(); } } onDragDrop(event: DragEvent) { - if (event.dataTransfer!.files.length > 0) { + if (event.dataTransfer?.files.length) { event.preventDefault(); - this.application!.alertService!.alert( - STRING_DEFAULT_FILE_ERROR - ); + void alertDialog({ + text: STRING_DEFAULT_FILE_ERROR + }); } } async handleDemoSignInFromParams() { if ( - this.$location!.search().demo === 'true' && + this.$location.search().demo === 'true' && !this.application.hasAccount() ) { - await this.application!.setHost( + await this.application.setHost( 'https://syncing-server-demo.standardnotes.org' ); - this.application!.signIn( + this.application.signIn( 'demo@standardnotes.org', 'password', ); diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index 4dcddbdf2..b8aa78e1d 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -266,24 +266,6 @@ span(ng-if='self.isDesktopApplication()') | Backups are automatically created on desktop and can be managed | via the "Backups" top-level menu. - #import-password-request(ng-if='self.state.importData.requestPassword') - form.sk-panel-form.stretch(ng-submit='self.submitImportPassword()') - p Enter the account password associated with the import file. - input.sk-input.contrast.mt-5( - autofocus='true', - ng-model='self.state.importData.password', - placeholder='Enter File Account Password', - type='password' - ) - .sk-button-group.stretch.sk-panel-row.form-submit - button.sk-button.info(type='submit') - .sk-label Decrypt & Import - p - | Importing from backup will not overwrite existing data, - | but instead create a duplicate of any differing data. - p - | If you'd like to import only a selection of items instead of - | the whole file, please use the Batch Manager extension. .sk-panel-row .sk-spinner.small.info(ng-if='self.state.importData.loading') .sk-panel-section diff --git a/package.json b/package.json index 33aa5bcbb..fe53262fc 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "angular": "^1.8.2", "apply-loader": "^2.0.0", "babel-eslint": "^10.1.0", + "babel-loader": "^8.2.2", "babel-plugin-angularjs-annotate": "^0.10.0", "chai": "^4.2.0", "connect": "^3.7.0", @@ -69,8 +70,7 @@ "@reach/alert-dialog": "^0.12.1", "@reach/dialog": "^0.12.1", "@standardnotes/sncrypto-web": "^1.2.10", - "@standardnotes/snjs": "^2.0.47", - "babel-loader": "^8.2.2", + "@standardnotes/snjs": "^2.0.48", "mobx": "^6.0.4", "preact": "^10.5.11" } diff --git a/yarn.lock b/yarn.lock index 93efa3aea..4fe185ef8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1085,10 +1085,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.47": - version "2.0.47" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.47.tgz#b6235faed52369168d383d6bf1ba45302f9b9cea" - integrity sha512-2d4CKdcKXg0dKYMdPPqQrLQE1NS62IWusfD2OZ0zRNbzhOHUhap/eRIURCDa0UQphKTaDaGa70x2rJl3PW4J6Q== +"@standardnotes/snjs@^2.0.48": + version "2.0.48" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.48.tgz#0e61b21e9a3d70d02867b86d2ced5dd1e8c861a1" + integrity sha512-OnlG6D0QNTu+jePJqUpyqeC81VMxKwyu3yNfGQyC6/p5j/nFcBC6W0aU6xBTeVsE2zEOX+Dltj6olY6dN4vgdQ== dependencies: "@standardnotes/sncrypto-common" "^1.2.9"