From e3ff04ba3f8c9a7d1a027ca3c2f5e9b04139f96d Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Sun, 3 Jun 2018 10:08:21 -0500 Subject: [PATCH] Incremental local loading, sync status on password wizard --- .../app/directives/views/accountMenu.js | 2 +- .../app/directives/views/passwordWizard.js | 3 +- .../app/services/componentManager.js | 4 +- .../javascripts/app/services/syncManager.js | 40 ++++++++++++++++--- app/assets/stylesheets/app/_modals.scss | 4 ++ .../directives/password-wizard.html.haml | 29 +++++++++----- 6 files changed, 62 insertions(+), 20 deletions(-) diff --git a/app/assets/javascripts/app/directives/views/accountMenu.js b/app/assets/javascripts/app/directives/views/accountMenu.js index 659f1c395..e5ba01cb6 100644 --- a/app/assets/javascripts/app/directives/views/accountMenu.js +++ b/app/assets/javascripts/app/directives/views/accountMenu.js @@ -208,7 +208,7 @@ class AccountMenu { var message = `Import complete. ${errorCount} items were not imported because there was an error decrypting them. Make sure the password is correct and try again.`; alert(message); } else { - alert("Your data was successfully imported.") + alert("Your data has been successfully imported.") } } }, 10); diff --git a/app/assets/javascripts/app/directives/views/passwordWizard.js b/app/assets/javascripts/app/directives/views/passwordWizard.js index e4acd3804..3b5024046 100644 --- a/app/assets/javascripts/app/directives/views/passwordWizard.js +++ b/app/assets/javascripts/app/directives/views/passwordWizard.js @@ -20,6 +20,7 @@ class PasswordWizard { $scope.$destroy(); } + $scope.syncStatus = syncManager.syncStatus; $scope.formData = {}; const IntroStep = 0; @@ -118,7 +119,7 @@ class PasswordWizard { $scope.formData.processing = passwordSuccess; if(passwordSuccess) { - $scope.formData.status = "Encrypting data with new keys..."; + $scope.formData.status = "Encrypting and syncing data with new keys..."; $scope.resyncData((syncSuccess) => { $scope.formData.statusError = !syncSuccess; diff --git a/app/assets/javascripts/app/services/componentManager.js b/app/assets/javascripts/app/services/componentManager.js index 8808126a5..275ef791e 100644 --- a/app/assets/javascripts/app/services/componentManager.js +++ b/app/assets/javascripts/app/services/componentManager.js @@ -399,7 +399,9 @@ class ComponentManager { for(let handler of this.handlersForArea(component.area)) { if(handler.contextRequestHandler) { var itemInContext = handler.contextRequestHandler(component); - this.sendContextItemInReply(component, itemInContext, message); + if(itemInContext) { + this.sendContextItemInReply(component, itemInContext, message); + } } } }.bind(this)) diff --git a/app/assets/javascripts/app/services/syncManager.js b/app/assets/javascripts/app/services/syncManager.js index fc5076e4f..4feedeb16 100644 --- a/app/assets/javascripts/app/services/syncManager.js +++ b/app/assets/javascripts/app/services/syncManager.js @@ -42,12 +42,34 @@ class SyncManager { }) } - loadLocalItems(callback) { - var params = this.storageManager.getAllModels((items) => { - this.handleItemsResponse(items, null, ModelManager.MappingSourceLocalRetrieved).then((items) => { - Item.sortItemsByDate(items); - callback(items); - }) + async loadLocalItems(callback) { + this.storageManager.getAllModels((items) => { + // break it up into chunks to make interface more responsive for large item counts + let total = items.length; + let iteration = 50; + var current = 0; + var processed = []; + + var completion = () => { + Item.sortItemsByDate(processed); + callback(processed); + } + + var decryptNext = async () => { + var subitems = items.slice(current, current + iteration); + var processedSubitems = await this.handleItemsResponse(subitems, null, ModelManager.MappingSourceLocalRetrieved); + processed.push(processedSubitems); + + current += subitems.length; + + if(current < total) { + this.$timeout(() => { decryptNext(); }); + } else { + completion(); + } + } + + decryptNext(); }) } @@ -266,6 +288,12 @@ class SyncManager { this.syncStatus.current = 0; } + // If items are marked as dirty during a long running sync request, total isn't updated + // This happens mostly in the case of large imports and sync conflicts where duplicated items are created + if(this.syncStatus.current > this.syncStatus.total) { + this.syncStatus.total = this.syncStatus.current; + } + // when doing a sync request that returns items greater than the limit, and thus subsequent syncs are required, // we want to keep track of all retreived items, then save to local storage only once all items have been retrieved, // so that relationships remain intact diff --git a/app/assets/stylesheets/app/_modals.scss b/app/assets/stylesheets/app/_modals.scss index 04c152488..a0925659e 100644 --- a/app/assets/stylesheets/app/_modals.scss +++ b/app/assets/stylesheets/app/_modals.scss @@ -81,6 +81,10 @@ padding: 0; padding-bottom: 0; min-width: 300px; + + -webkit-box-shadow: 0px 2px 35px 0px rgba(0,0,0,0.19); + -moz-box-shadow: 0px 2px 35px 0px rgba(0,0,0,0.19); + box-shadow: 0px 2px 35px 0px rgba(0,0,0,0.19); } } diff --git a/app/assets/templates/directives/password-wizard.html.haml b/app/assets/templates/directives/password-wizard.html.haml index 6ac3f3ee6..737e9d9d9 100644 --- a/app/assets/templates/directives/password-wizard.html.haml +++ b/app/assets/templates/directives/password-wizard.html.haml @@ -10,9 +10,11 @@ %div{"ng-if" => "step == 0"} %div{"ng-if" => "changePassword"} %h2.title.panel-row Change your password - %p Because your encryption key is based on your password, changing your password requires your data to be re-encrypted using your new key. - %p This process will guide you through changing your password. - %p If you have many items, re-uploading your data can take several minutes. You must keep the application window open during this process. + %p + Changing your password involves changing your encryption key, which requires your data to be re-encrypted and synced. + If you have many items, syncing your data can take several minutes. + %p.panel-row + %strong You must keep the application window open during this process. %div{"ng-if" => "securityUpdate"} %h2.title.panel-row Perform security update %p @@ -34,9 +36,9 @@ %div{"ng-if" => "step == 1"} %p.panel-row - As a result of this process, the entirety of your data will be re-encrypted and re-uploaded to your account. This is a generally safe process, + As a result of this process, the entirety of your data will be re-encrypted and synced to your account. This is a generally safe process, but unforeseen factors like poor network connectivity or a sudden shutdown of your computer may cause this process to fail. - It's best to be on the safe side before large operations like this. + It's best to be on the safe side before large operations such as this one. .panel-row .panel-row .button-group @@ -48,7 +50,7 @@ %div{"ng-if" => "step == 2"} %p.panel-row As a result of this process, your encryption keys will change. - Any devices on which you use Standard Notes will need to end their session. After this process completes, you will be asked to sign back in. + Any device on which you use Standard Notes will need to end its session. After this process completes, you will be asked to sign back in. %p.bold.panel-row.info-i Please sign out of all applications (excluding this one), including: %ul @@ -77,10 +79,14 @@ %p.panel-row.danger Do not close this window until this process completes. - %p.panel-row - .spinner.small.inline.info.mr-5{"ng-if" => "formData.processing"} - .inline.bold{"ng-class" => "{'info' : !formData.statusError, 'error' : formData.statusError}"} - {{formData.status}} + .panel-row + .panel-column + .spinner.small.inline.info.mr-5{"ng-if" => "formData.processing"} + .inline.bold{"ng-class" => "{'info' : !formData.statusError, 'error' : formData.statusError}"} + {{formData.status}} + .panel-column + %p.info{"ng-if" => "syncStatus.total > 0"} + Syncing {{syncStatus.current}}/{{syncStatus.total}} %div{"ng-if" => "step == 5"} %div{"ng-if" => "changePassword"} @@ -88,7 +94,8 @@ %div{"ng-if" => "securityUpdate"} %p.panel-row The security update has been successfully applied to your account. - Please ensure you are running the latest version of Standard Notes on all platforms to ensure maximum compatibility. + %p.panel-row + %strong Please ensure you are running the latest version of Standard Notes on all platforms to ensure maximum compatibility. %p.panel-row You may now sign back in on all your devices and close this window.