diff --git a/app/assets/javascripts/app/services/directives/functional/delay-hide.js b/app/assets/javascripts/app/services/directives/functional/delay-hide.js index 7467208f4..6e381ed3f 100644 --- a/app/assets/javascripts/app/services/directives/functional/delay-hide.js +++ b/app/assets/javascripts/app/services/directives/functional/delay-hide.js @@ -20,11 +20,15 @@ angular }); function showSpinner() { + if(scope.hidePromise) { + $timeout.cancel(scope.hidePromise); + scope.hidePromise = null; + } showElement(true); } function hideSpinner() { - $timeout(showElement.bind(this, false), getDelay()); + scope.hidePromise = $timeout(showElement.bind(this, false), getDelay()); } function showElement(show) { diff --git a/app/assets/javascripts/app/services/directives/views/accountMenu.js b/app/assets/javascripts/app/services/directives/views/accountMenu.js index 7364b51c4..aa171bfab 100644 --- a/app/assets/javascripts/app/services/directives/views/accountMenu.js +++ b/app/assets/javascripts/app/services/directives/views/accountMenu.js @@ -30,7 +30,7 @@ class AccountMenu { $scope.newPasswordData = {}; $scope.showPasswordChangeForm = function() { - $scope.newPasswordData.showNewPasswordForm = true; + $scope.newPasswordData.showForm = true; } $scope.submitPasswordChange = function() { @@ -49,29 +49,35 @@ class AccountMenu { } $scope.newPasswordData.status = "Generating New Keys..."; + $scope.newPasswordData.showForm = false; - authManager.changePassword(email, $scope.newPasswordData.newPassword, function(response){ - if(response.error) { - alert("There was an error changing your password. Please try again."); - $scope.newPasswordData.status = null; - return; - } - - // re-encrypt all items - $scope.newPasswordData.status = "Re-encrypting all items with your new key..."; - modelManager.setAllItemsDirty(); - syncManager.sync(function(response){ + // perform a sync beforehand to pull in any last minutes changes before we change the encryption key (and thus cant decrypt new changes) + syncManager.sync(function(response){ + authManager.changePassword(email, $scope.newPasswordData.newPassword, function(response){ if(response.error) { - alert("There was an error re-encrypting your items. Your password was changed, but not all your items were properly re-encrypted and synced. You should try syncing again. If all else fails, you should restore your notes from backup.") + alert("There was an error changing your password. Please try again."); + $scope.newPasswordData.status = null; return; } - $scope.newPasswordData.status = "Successfully changed password and re-encrypted all items."; - alert("Your password has been changed, and your items successfully re-encrypted and synced. Be sure to log out on all other signed in applications.") - $timeout(function(){ - $scope.newPasswordData = {}; - }, 1000) - }); + + // re-encrypt all items + $scope.newPasswordData.status = "Re-encrypting all items with your new key..."; + + modelManager.setAllItemsDirty(); + syncManager.sync(function(response){ + if(response.error) { + alert("There was an error re-encrypting your items. Your password was changed, but not all your items were properly re-encrypted and synced. You should try syncing again. If all else fails, you should restore your notes from backup.") + return; + } + $scope.newPasswordData.status = "Successfully changed password and re-encrypted all items."; + $timeout(function(){ + alert("Your password has been changed, and your items successfully re-encrypted and synced. You must sign out on all other signed in applications and sign in again, or else you may corrupt your data.") + $scope.newPasswordData = {}; + }, 1000) + }); + }) }) + } $scope.loginSubmitPressed = function() { diff --git a/app/assets/javascripts/app/services/syncManager.js b/app/assets/javascripts/app/services/syncManager.js index 851d1c0a5..618d77ef0 100644 --- a/app/assets/javascripts/app/services/syncManager.js +++ b/app/assets/javascripts/app/services/syncManager.js @@ -115,7 +115,6 @@ class SyncManager { allCallbacks.push(currentCallback); } if(allCallbacks.length) { - console.log(allCallbacks.length, "queued callbacks"); for(var eachCallback of allCallbacks) { eachCallback(response); } @@ -144,7 +143,7 @@ class SyncManager { return; } - var isContinuationSync = this.needsMoreSync; + var isContinuationSync = this.syncStatus.needsMoreSync; this.syncStatus.syncOpInProgress = true; @@ -152,9 +151,9 @@ class SyncManager { var subItems = allDirtyItems.slice(0, submitLimit); if(subItems.length < allDirtyItems.length) { // more items left to be synced, repeat - this.needsMoreSync = true; + this.syncStatus.needsMoreSync = true; } else { - this.needsMoreSync = false; + this.syncStatus.needsMoreSync = false; } if(!isContinuationSync) { @@ -199,14 +198,14 @@ class SyncManager { this.syncToken = response.sync_token; this.cursorToken = response.cursor_token; - if(this.cursorToken || this.needsMoreSync) { + if(this.cursorToken || this.syncStatus.needsMoreSync) { setTimeout(function () { this.sync(callback, options); }.bind(this), 10); // wait 10ms to allow UI to update } else if(this.repeatOnCompletion) { this.repeatOnCompletion = false; setTimeout(function () { - this.sync(null, options); + this.sync(callback, options); }.bind(this), 10); // wait 10ms to allow UI to update } else { this.callQueuedCallbacksAndCurrent(callback, response); @@ -242,7 +241,7 @@ class SyncManager { var item = this.modelManager.findItem(itemResponse.uuid); var error = mapping.error; if(error.tag == "uuid_conflict") { - // uuid conflicts can occur if a user attempts to import an old data archive with uuids form the old account into a new account + // uuid conflicts can occur if a user attempts to import an old data archive with uuids from the old account into a new account this.modelManager.alternateUUIDForItem(item, handleNext); } ++i; diff --git a/app/assets/templates/frontend/directives/account-menu.html.haml b/app/assets/templates/frontend/directives/account-menu.html.haml index 1db3d3669..628cd68f8 100644 --- a/app/assets/templates/frontend/directives/account-menu.html.haml +++ b/app/assets/templates/frontend/directives/account-menu.html.haml @@ -28,6 +28,7 @@ %div{"ng-if" => "user"} %h2 {{user.email}} %p {{server}} + %a.block.mt-10{"href" => "{{dashboardURL()}}", "target" => "_blank"} → Standard File Dashboard %a.block.mt-5{"ng-click" => "showCredentials = !showCredentials"} Show Credentials %section.gray-bg.mt-10.medium-padding{"ng-if" => "showCredentials"} %label.block @@ -44,22 +45,20 @@ %p.mt-5 If you have thousands of items, this can take several minutes — you must keep the application window open during this process. %p.mt-5 After changing your password, you must log out of all other applications currently signed in to your account. %p.bold.mt-5 It is highly recommended you download a backup of your data before proceeding. - %div.mt-10 - %a.red.mr-5{"ng-if" => "!newPasswordData.showNewPasswordForm", "ng-click" => "showPasswordChangeForm()"} Continue - %a{"ng-click" => "newPasswordData.changePassword = false; newPasswordData.showNewPasswordForm = false"} Cancel - %div.mt-10{"ng-if" => "newPasswordData.showNewPasswordForm"} + %div.mt-10{"ng-if" => "!newPasswordData.status"} + %a.red.mr-5{"ng-if" => "!newPasswordData.showForm", "ng-click" => "showPasswordChangeForm()"} Continue + %a{"ng-click" => "newPasswordData.changePassword = false; newPasswordData.showForm = false"} Cancel + %div.mt-10{"ng-if" => "newPasswordData.showForm"} %form %input.form-control{"type" => "text", "ng-model" => "newPasswordData.newPassword", "placeholder" => "Enter new password"} %input.form-control{"type" => "text", "ng-model" => "newPasswordData.newPasswordConfirmation", "placeholder" => "Confirm new password"} %button.btn.dark-button.btn-block{"ng-click" => "submitPasswordChange()"} Submit - %p.italic.mt-10{"ng-if" => "newPasswordData.status"} {{newPasswordData.status}} + %p.italic.mt-10{"ng-if" => "newPasswordData.status"} {{newPasswordData.status}} - %a.block.mt-5{"href" => "{{dashboardURL()}}", "target" => "_blank"} Standard File Dashboard - - %div.bold.mt-10.blue{"delay-hide" => "true", "show" => "syncStatus.syncOpInProgress", "delay" => "1000"} + %div.bold.mt-10.blue{"delay-hide" => "true", "show" => "syncStatus.syncOpInProgress || syncStatus.needsMoreSync", "delay" => "1000"} .spinner.inline.mr-5.blue - Syncing - %span{"ng-if" => "syncStatus.total > 0"}: {{syncStatus.current}}/{{syncStatus.total}} + {{"Syncing" + (syncStatus.total > 0 ? ":" : "")}} + %span{"ng-if" => "syncStatus.total > 0"} {{syncStatus.current}}/{{syncStatus.total}} %p.bold.mt-10.red.block{"ng-if" => "syncStatus.error"} Error syncing: {{syncStatus.error.message}} .medium-v-space