From 8434f598ca80259a32c28d10e399b271ff6bb7f5 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 23 Nov 2020 17:06:23 +0100 Subject: [PATCH] fix: show syncing message consistently --- .../directives/views/accountMenu.ts | 16 ++++-- app/assets/javascripts/ui_models/app_state.ts | 53 ++++++++++++++++--- app/assets/stylesheets/_stylekit-sub.scss | 6 +++ .../templates/directives/account-menu.pug | 25 +++++---- 4 files changed, 78 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index 85789c0e5..c5c550582 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -22,7 +22,6 @@ import { STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL, STRING_UNSUPPORTED_BACKUP_FILE_VERSION } from '@/strings'; -import { SyncOpStatus } from '@standardnotes/snjs'; import { PasswordWizardType } from '@/types'; import { BackupFile } from '@standardnotes/snjs'; import { confirmDialog, alertDialog } from '@/services/alertService'; @@ -67,15 +66,18 @@ type AccountMenuState = { selectedAutoLockInterval: any; showBetaWarning: boolean; errorReportingEnabled: boolean; + syncInProgress: boolean; + syncError: string; + syncPercentage: string; } class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> { public appVersion: string /** @template */ - syncStatus?: SyncOpStatus private closeFunction?: () => void private removeBetaWarningListener?: IReactionDisposer + private removeSyncObserver?: IReactionDisposer /* @ngInject */ constructor( @@ -130,7 +132,14 @@ class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> { $onInit() { super.$onInit(); - this.syncStatus = this.application!.getSyncStatus(); + const sync = this.appState.sync; + this.removeSyncObserver = autorun(() => { + this.setState({ + syncInProgress: sync.inProgress, + syncError: sync.errorMessage, + syncPercentage: sync.humanReadablePercentage, + }); + }) this.removeBetaWarningListener = autorun(() => { this.setState({ showBetaWarning: this.appState.showBetaWarning @@ -139,6 +148,7 @@ class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> { } deinit() { + this.removeSyncObserver?.(); this.removeBetaWarningListener?.(); super.deinit(); } diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index 732ef0fd5..9a08616e7 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -10,7 +10,8 @@ import { SNSmartTag, PayloadSource, DeinitSource, - UuidString + UuidString, + SyncOpStatus } from '@standardnotes/snjs'; import { WebApplication } from '@/ui_models/application'; import { Editor } from '@/ui_models/editor'; @@ -58,6 +59,39 @@ class ActionsMenuState { } } +export class SyncState { + inProgress = false; + errorMessage?: string; + humanReadablePercentage?: string; + + constructor() { + makeObservable(this, { + inProgress: observable, + errorMessage: observable, + humanReadablePercentage: observable, + update: action, + }); + } + + update(status: SyncOpStatus) { + this.errorMessage = status.error?.message; + this.inProgress = status.syncInProgress; + const stats = status.getStats(); + const completionPercentage = stats.uploadCompletionCount === 0 + ? 0 + : stats.uploadCompletionCount / stats.uploadTotalCount; + + if (completionPercentage === 0) { + this.humanReadablePercentage = undefined; + } else { + this.humanReadablePercentage = completionPercentage.toLocaleString( + undefined, + { style: 'percent' } + ); + } + } +} + export class AppState { $rootScope: ng.IRootScopeService; $timeout: ng.ITimeoutService; @@ -72,7 +106,8 @@ export class AppState { userPreferences?: SNUserPrefs; multiEditorEnabled = false; showBetaWarning = false; - actionsMenu = new ActionsMenuState(); + readonly actionsMenu = new ActionsMenuState(); + readonly sync = new SyncState(); /* @ngInject */ constructor( @@ -263,10 +298,16 @@ export class AppState { addAppEventObserver() { this.unsubApp = this.application.addEventObserver(async (eventName) => { - if (eventName === ApplicationEvent.Started) { - this.locked = true; - } else if (eventName === ApplicationEvent.Launched) { - this.locked = false; + switch (eventName) { + case ApplicationEvent.Started: + this.locked = true; + break; + case ApplicationEvent.Launched: + this.locked = false; + break; + case ApplicationEvent.SyncStatusChanged: + this.sync.update(this.application.getSyncStatus()); + break; } }); } diff --git a/app/assets/stylesheets/_stylekit-sub.scss b/app/assets/stylesheets/_stylekit-sub.scss index 33003133c..201a604d2 100644 --- a/app/assets/stylesheets/_stylekit-sub.scss +++ b/app/assets/stylesheets/_stylekit-sub.scss @@ -34,6 +34,12 @@ margin-left: 0.3rem; } +.sk-horizontal-group { + display: flex; + flex-direction: row; + align-items: center; +} + .sk-panel-section { &:last-child { padding-bottom: 1rem; diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index 799fa2c39..c521a899c 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -136,11 +136,11 @@ !self.state.formData.showRegister` ) .sk-panel-section(ng-if='self.state.user') - .sk-notification.danger(ng-if='self.syncStatus.error') + .sk-notification.danger(ng-if='self.state.syncError') .sk-notification-title Sync Unreachable .sk-notification-text | Hmm...we can't seem to sync your account. - | The reason: {{self.syncStatus.error.message}} + | The reason: {{self.state.syncError}} a.sk-a.info-contrast.sk-bold.sk-panel-row( href='https://standardnotes.org/help', rel='noopener', @@ -150,17 +150,16 @@ .sk-panel-column .sk-h1.sk-bold.wrap {{self.state.user.email}} .sk-subtitle.subtle.normal {{self.state.server}} - .sk-horizontal-group( - delay='1000', - delay-hide='true', - show='self.syncStatus.syncOpInProgress || self.syncStatus.needsMoreSync' - ) - .sk-spinner.small.info - .sk-sublabel - | {{"Syncing" + (self.syncStatus.total > 0 ? ":" : "")}} - span( - ng-if='self.syncStatus.total > 0' - ) {{self.syncStatus.current}}/{{self.syncStatus.total}} + .sk-horizontal-group( + delay='1000', + delay-hide='true', + show='self.state.syncInProgress' + ) + .sk-spinner.small.info + .sk-sublabel + | Syncing + span(ng-if='self.state.syncPercentage') + | ({{self.state.syncPercentage}}) .sk-panel-row a.sk-a.info.sk-panel-row.condensed( ng-click="self.openPasswordWizard()"