feat: snjs app groups (#468)
* feat: snjs app groups * fix: update snjs version to point to wip commit * wip: account switcher * feat: rename lock manager to auto lock service * fix: more relevant sign out copy * chore(deps): update snjs * fix: use setTimeout instead of setImmediate * feat: make account switcher expiremental feature * chore(deps): upgrade snjs
This commit is contained in:
@@ -63,9 +63,15 @@ export class PureViewCtrl<P = CtrlProps, S = CtrlState> {
|
||||
if (!this.$timeout) {
|
||||
return;
|
||||
}
|
||||
this.state = Object.freeze(Object.assign({}, this.state, state));
|
||||
return new Promise((resolve) => {
|
||||
this.stateTimeout = this.$timeout(resolve);
|
||||
this.stateTimeout = this.$timeout(() => {
|
||||
/**
|
||||
* State changes must be *inside* the timeout block for them to be affected in the UI
|
||||
* Otherwise UI controllers will need to use $timeout everywhere
|
||||
*/
|
||||
this.state = Object.freeze(Object.assign({}, this.state, state));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
.sk-modal-background(ng-click="ctrl.dismiss()")
|
||||
#account-switcher.sk-modal-content
|
||||
.sn-component
|
||||
.sk-menu-panel#menu-panel
|
||||
.sk-menu-panel-header
|
||||
.sk-menu-panel-column
|
||||
.sk-menu-panel-header-title Account Switcher
|
||||
.sk-menu-panel-column
|
||||
a.sk-label.info(ng-click='ctrl.addNewApplication()') Add Account
|
||||
.sk-menu-panel-row(
|
||||
ng-repeat='descriptor in ctrl.state.descriptors track by descriptor.identifier'
|
||||
ng-click='ctrl.selectDescriptor(descriptor)'
|
||||
)
|
||||
.sk-menu-panel-column.stretch
|
||||
.left
|
||||
.sk-menu-panel-column(ng-if='descriptor.identifier == ctrl.activeApplication.identifier')
|
||||
.sk-circle.small.success
|
||||
.sk-menu-panel-column.stretch
|
||||
input.sk-label.clickable(
|
||||
ng-model='descriptor.label'
|
||||
ng-disabled='descriptor != ctrl.state.editingDescriptor'
|
||||
ng-keyup='$event.keyCode == 13 && ctrl.submitRename($event)',
|
||||
ng-attr-id='input-{{descriptor.identifier}}'
|
||||
spellcheck="false"
|
||||
)
|
||||
.sk-sublabel(ng-if='descriptor.identifier == ctrl.activeApplication.identifier')
|
||||
| Current Application
|
||||
.sk-menu-panel-column(ng-if='descriptor.identifier == ctrl.activeApplication.identifier')
|
||||
.sk-button.success(
|
||||
ng-click='ctrl.renameDescriptor($event, descriptor)'
|
||||
)
|
||||
.sk-label Rename
|
||||
@@ -0,0 +1,105 @@
|
||||
import { ApplicationGroup } from '@/ui_models/application_group';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import template from './account-switcher.pug';
|
||||
import {
|
||||
ApplicationDescriptor,
|
||||
} from 'snjs';
|
||||
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||
import { WebDirective } from '@/types';
|
||||
|
||||
class AccountSwitcherCtrl extends PureViewCtrl<{}, {
|
||||
descriptors: ApplicationDescriptor[];
|
||||
editingDescriptor?: ApplicationDescriptor
|
||||
}> {
|
||||
private $element: JQLite
|
||||
application!: WebApplication
|
||||
private removeAppGroupObserver: any;
|
||||
/** @template */
|
||||
activeApplication!: WebApplication
|
||||
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
$element: JQLite,
|
||||
$timeout: ng.ITimeoutService,
|
||||
private mainApplicationGroup: ApplicationGroup
|
||||
) {
|
||||
super($timeout);
|
||||
this.$element = $element;
|
||||
this.removeAppGroupObserver = mainApplicationGroup.addApplicationChangeObserver(() => {
|
||||
this.activeApplication = mainApplicationGroup.primaryApplication as WebApplication;
|
||||
this.reloadApplications();
|
||||
});
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
super.$onInit();
|
||||
}
|
||||
|
||||
reloadApplications() {
|
||||
this.setState({
|
||||
descriptors: this.mainApplicationGroup.getDescriptors()
|
||||
})
|
||||
}
|
||||
|
||||
/** @template */
|
||||
addNewApplication() {
|
||||
this.dismiss();
|
||||
this.mainApplicationGroup.addNewApplication();
|
||||
}
|
||||
|
||||
/** @template */
|
||||
selectDescriptor(descriptor: ApplicationDescriptor) {
|
||||
this.dismiss();
|
||||
this.mainApplicationGroup.loadApplicationForDescriptor(descriptor);
|
||||
}
|
||||
|
||||
inputForDescriptor(descriptor: ApplicationDescriptor) {
|
||||
return document.getElementById(`input-${descriptor.identifier}`);
|
||||
}
|
||||
|
||||
/** @template */
|
||||
renameDescriptor($event: Event, descriptor: ApplicationDescriptor) {
|
||||
$event.stopPropagation();
|
||||
this.setState({ editingDescriptor: descriptor }).then(() => {
|
||||
const input = this.inputForDescriptor(descriptor);
|
||||
input?.focus();
|
||||
})
|
||||
}
|
||||
|
||||
/** @template */
|
||||
submitRename() {
|
||||
this.mainApplicationGroup.renameDescriptor(
|
||||
this.state.editingDescriptor!,
|
||||
this.state.editingDescriptor!.label
|
||||
)
|
||||
this.setState({ editingDescriptor: undefined });
|
||||
}
|
||||
|
||||
deinit() {
|
||||
(this.application as any) = undefined;
|
||||
super.deinit();
|
||||
this.removeAppGroupObserver();
|
||||
this.removeAppGroupObserver = undefined;
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
const elem = this.$element;
|
||||
const scope = elem.scope();
|
||||
scope.$destroy();
|
||||
elem.remove();
|
||||
}
|
||||
}
|
||||
|
||||
export class AccountSwitcher extends WebDirective {
|
||||
constructor() {
|
||||
super();
|
||||
this.restrict = 'E';
|
||||
this.template = template;
|
||||
this.controller = AccountSwitcherCtrl;
|
||||
this.controllerAs = 'ctrl';
|
||||
this.bindToController = true;
|
||||
this.scope = {
|
||||
application: '='
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
ng-class='self.platformString'
|
||||
)
|
||||
#app.app(
|
||||
ng-class='self.state.appClass',
|
||||
ng-class='self.state.appClass',
|
||||
ng-if='!self.state.needsUnlock && self.state.ready'
|
||||
)
|
||||
tags-view(application='self.application')
|
||||
@@ -14,4 +14,13 @@
|
||||
footer-view(
|
||||
ng-if='!self.state.needsUnlock && self.state.ready'
|
||||
application='self.application'
|
||||
)
|
||||
)
|
||||
|
||||
svg(data-ionicons="5.1.2", style="display: none")
|
||||
symbol#people-circle-outline.ionicon(viewbox="0 0 512 512")
|
||||
path(d="M256 464c-114.69 0-208-93.31-208-208S141.31 48 256 48s208 93.31 208 208-93.31 208-208 208zm0-384c-97 0-176 79-176 176s79 176 176 176 176-78.95 176-176S353.05 80 256 80z")
|
||||
path(d="M323.67 292c-17.4 0-34.21-7.72-47.34-21.73a83.76 83.76 0 01-22-51.32c-1.47-20.7 4.88-39.75 17.88-53.62S303.38 144 323.67 144c20.14 0 38.37 7.62 51.33 21.46s19.47 33 18 53.51a84 84 0 01-22 51.3C357.86 284.28 341.06 292 323.67 292zm55.81-74zM163.82 295.36c-29.76 0-55.93-27.51-58.33-61.33-1.23-17.32 4.15-33.33 15.17-45.08s26.22-18 43.15-18 32.12 6.44 43.07 18.14 16.5 27.82 15.25 45c-2.44 33.77-28.6 61.27-58.31 61.27zM420.37 355.28c-1.59-4.7-5.46-9.71-13.22-14.46-23.46-14.33-52.32-21.91-83.48-21.91-30.57 0-60.23 7.9-83.53 22.25-26.25 16.17-43.89 39.75-51 68.18-1.68 6.69-4.13 19.14-1.51 26.11a192.18 192.18 0 00232.75-80.17zM163.63 401.37c7.07-28.21 22.12-51.73 45.47-70.75a8 8 0 00-2.59-13.77c-12-3.83-25.7-5.88-42.69-5.88-23.82 0-49.11 6.45-68.14 18.17-5.4 3.33-10.7 4.61-14.78 5.75a192.84 192.84 0 0077.78 86.64l1.79-.14a102.82 102.82 0 013.16-20.02z")
|
||||
|
||||
symbol#layers-sharp.ionicon(viewbox="0 0 512 512")
|
||||
path(d="M480 150L256 48 32 150l224 104 224-104zM255.71 392.95l-144.81-66.2L32 362l224 102 224-102-78.69-35.3-145.6 66.25z")
|
||||
path(d="M480 256l-75.53-33.53L256.1 290.6l-148.77-68.17L32 256l224 102 224-102z")
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
STRING_DEFAULT_FILE_ERROR
|
||||
} from '@/strings';
|
||||
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||
import { PermissionDialog } from '@node_modules/snjs/dist/@types/services/component_manager';
|
||||
import { PermissionDialog } from 'snjs/dist/@types/services/component_manager';
|
||||
import { alertDialog } from '@/services/alertService';
|
||||
|
||||
class ApplicationViewCtrl extends PureViewCtrl {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
application-view(
|
||||
ng-repeat='application in self.applications',
|
||||
ng-if='application == self.activeApplication'
|
||||
application='application'
|
||||
)
|
||||
@@ -7,7 +7,8 @@ class ApplicationGroupViewCtrl {
|
||||
|
||||
private $timeout: ng.ITimeoutService
|
||||
private applicationGroup: ApplicationGroup
|
||||
public applications: WebApplication[] = []
|
||||
applications!: WebApplication[]
|
||||
activeApplication!: WebApplication
|
||||
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
@@ -19,11 +20,13 @@ class ApplicationGroupViewCtrl {
|
||||
this.applicationGroup.addApplicationChangeObserver(() => {
|
||||
this.reload();
|
||||
});
|
||||
this.applicationGroup.initialize();
|
||||
}
|
||||
|
||||
reload() {
|
||||
this.$timeout(() => {
|
||||
this.applications = this.applicationGroup.getApplications();
|
||||
this.activeApplication = this.applicationGroup.primaryApplication as WebApplication;
|
||||
this.applications = this.applicationGroup.getApplications() as WebApplication[];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -33,7 +36,7 @@ export class ApplicationGroupView extends WebDirective {
|
||||
super();
|
||||
this.template = template;
|
||||
this.controller = ApplicationGroupViewCtrl;
|
||||
this.replace = true;
|
||||
this.replace = false;
|
||||
this.controllerAs = 'self';
|
||||
this.bindToController = true;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.left
|
||||
.sk-app-bar-item(
|
||||
click-outside='ctrl.clickOutsideAccountMenu()',
|
||||
is-open='ctrl.showAccountMenu',
|
||||
is-open='ctrl.showAccountMenu',
|
||||
ng-click='ctrl.accountMenuPressed()'
|
||||
)
|
||||
.sk-app-bar-item-column
|
||||
@@ -13,15 +13,15 @@
|
||||
.sk-app-bar-item-column
|
||||
.sk-label.title(ng-class='{red: ctrl.hasError}') Account
|
||||
account-menu(
|
||||
close-function='ctrl.closeAccountMenu()',
|
||||
ng-click='$event.stopPropagation()',
|
||||
close-function='ctrl.closeAccountMenu()',
|
||||
ng-click='$event.stopPropagation()',
|
||||
ng-if='ctrl.showAccountMenu',
|
||||
application='ctrl.application'
|
||||
)
|
||||
.sk-app-bar-item
|
||||
a.no-decoration.sk-label.title(
|
||||
href='https://standardnotes.org/help',
|
||||
rel='noopener',
|
||||
href='https://standardnotes.org/help',
|
||||
rel='noopener',
|
||||
target='_blank'
|
||||
)
|
||||
| Help
|
||||
@@ -30,8 +30,8 @@
|
||||
.sk-app-bar-item-column(ng-click='ctrl.selectRoom(room)')
|
||||
.sk-label {{room.name}}
|
||||
component-modal(
|
||||
component-uuid='room.uuid',
|
||||
ng-if='ctrl.roomShowState[room.uuid]',
|
||||
component-uuid='room.uuid',
|
||||
ng-if='ctrl.roomShowState[room.uuid]',
|
||||
on-dismiss='ctrl.onRoomDismiss(room)',
|
||||
application='ctrl.application'
|
||||
)
|
||||
@@ -41,12 +41,12 @@
|
||||
span.neutral.sk-label {{ctrl.arbitraryStatusMessage}}
|
||||
.right
|
||||
.sk-app-bar-item(
|
||||
ng-click='ctrl.openSecurityUpdate()',
|
||||
ng-click='ctrl.openSecurityUpdate()',
|
||||
ng-if='ctrl.state.dataUpgradeAvailable'
|
||||
)
|
||||
span.success.sk-label Encryption upgrade available.
|
||||
.sk-app-bar-item(
|
||||
ng-click='ctrl.clickedNewUpdateAnnouncement()',
|
||||
ng-click='ctrl.clickedNewUpdateAnnouncement()',
|
||||
ng-if='ctrl.newUpdateAvailable == true'
|
||||
)
|
||||
span.info.sk-label New update available.
|
||||
@@ -56,13 +56,13 @@
|
||||
.sk-label.subtle(ng-if='!ctrl.offline')
|
||||
| Last refreshed {{ctrl.lastSyncDate}}
|
||||
.sk-app-bar-item(
|
||||
ng-click='ctrl.toggleSyncResolutionMenu()',
|
||||
ng-click='ctrl.toggleSyncResolutionMenu()',
|
||||
ng-if='(ctrl.state.outOfSync && !ctrl.isRefreshing) || ctrl.showSyncResolution'
|
||||
)
|
||||
.sk-label.warning(ng-if='ctrl.state.outOfSync') Potentially Out of Sync
|
||||
sync-resolution-menu(
|
||||
close-function='ctrl.toggleSyncResolutionMenu()',
|
||||
ng-click='$event.stopPropagation();',
|
||||
close-function='ctrl.toggleSyncResolutionMenu()',
|
||||
ng-click='$event.stopPropagation();',
|
||||
ng-if='ctrl.showSyncResolution',
|
||||
application='ctrl.application'
|
||||
)
|
||||
@@ -70,27 +70,35 @@
|
||||
.sk-spinner.small
|
||||
.sk-app-bar-item(ng-if='ctrl.offline')
|
||||
.sk-label Offline
|
||||
.sk-app-bar-item(ng-click='ctrl.refreshData()', ng-if='!ctrl.offline')
|
||||
.sk-app-bar-item(ng-click='ctrl.refreshData()' ng-if='!ctrl.offline')
|
||||
.sk-label Refresh
|
||||
.sk-app-bar-item.border(ng-if='ctrl.state.dockShortcuts.length > 0')
|
||||
.sk-app-bar-item.dock-shortcut(ng-repeat='shortcut in ctrl.state.dockShortcuts')
|
||||
.sk-app-bar-item-column(
|
||||
ng-class="{'underline': shortcut.component.active}",
|
||||
ng-class="{'underline': shortcut.component.active}",
|
||||
ng-click='ctrl.selectShortcut(shortcut)'
|
||||
)
|
||||
.div(ng-if="shortcut.icon.type == 'circle'", title='{{shortcut.name}}')
|
||||
.div(ng-if="shortcut.icon.type == 'circle'" title='{{shortcut.name}}')
|
||||
.sk-circle.small(
|
||||
ng-style="{'background-color': shortcut.icon.background_color, 'border-color': shortcut.icon.border_color}"
|
||||
)
|
||||
.div(ng-if="shortcut.icon.type == 'svg'", title='{{shortcut.name}}')
|
||||
.div(ng-if="shortcut.icon.type == 'svg'" title='{{shortcut.name}}')
|
||||
.svg-item(
|
||||
elem-ready='ctrl.initSvgForShortcut(shortcut)',
|
||||
elem-ready='ctrl.initSvgForShortcut(shortcut)',
|
||||
ng-attr-id='dock-svg-{{shortcut.component.uuid}}'
|
||||
)
|
||||
.sk-app-bar-item.border(ng-if='ctrl.state.hasAccountSwitcher')
|
||||
.sk-app-bar-item(
|
||||
ng-if='ctrl.state.hasAccountSwitcher'
|
||||
ng-click='ctrl.openAccountSwitcher()',
|
||||
)
|
||||
#account-switcher-icon(ng-class='{"alone": !ctrl.state.hasPasscode}')
|
||||
svg.info.ionicon
|
||||
use(href="#layers-sharp")
|
||||
.sk-app-bar-item.border(ng-if='ctrl.state.hasPasscode')
|
||||
#lock-item.sk-app-bar-item(
|
||||
ng-click='ctrl.lockApp()',
|
||||
ng-if='ctrl.state.hasPasscode',
|
||||
ng-click='ctrl.lockApp()',
|
||||
ng-if='ctrl.state.hasPasscode',
|
||||
title='Locks application and wipes unencrypted data from memory.'
|
||||
)
|
||||
.sk-label
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ApplicationGroup } from '@/ui_models/application_group';
|
||||
import { FooterStatus, WebDirective } from '@/types';
|
||||
import { dateToLocalizedString, preventRefreshing } from '@/utils';
|
||||
import {
|
||||
@@ -11,7 +12,7 @@ import {
|
||||
ComponentAction,
|
||||
topLevelCompare,
|
||||
CollectionSort,
|
||||
ComponentMutator,
|
||||
ComponentMutator
|
||||
} from 'snjs';
|
||||
import template from './footer-view.pug';
|
||||
import { AppStateEvent, EventSource } from '@/ui_models/app_state';
|
||||
@@ -22,6 +23,14 @@ import {
|
||||
} from '@/strings';
|
||||
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||
|
||||
/**
|
||||
* Disable before production release.
|
||||
* Anyone who used the beta will still have access to
|
||||
* the account switcher in production via local storage flag
|
||||
*/
|
||||
const ACCOUNT_SWITCHER_ENABLED = true;
|
||||
const ACCOUNT_SWITCHER_FEATURE_KEY = 'account_switcher';
|
||||
|
||||
type DockShortcut = {
|
||||
name: string,
|
||||
component: SNComponent,
|
||||
@@ -37,8 +46,8 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
hasPasscode: boolean;
|
||||
dataUpgradeAvailable: boolean;
|
||||
dockShortcuts: DockShortcut[];
|
||||
hasAccountSwitcher: boolean
|
||||
}> {
|
||||
|
||||
private $rootScope: ng.IRootScopeService
|
||||
private rooms: SNComponent[] = []
|
||||
private themesWithIcons: SNTheme[] = []
|
||||
@@ -66,6 +75,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
constructor(
|
||||
$rootScope: ng.IRootScopeService,
|
||||
$timeout: ng.ITimeoutService,
|
||||
private mainApplicationGroup: ApplicationGroup
|
||||
) {
|
||||
super($timeout);
|
||||
this.$rootScope = $rootScope;
|
||||
@@ -92,11 +102,22 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
|
||||
$onInit() {
|
||||
super.$onInit();
|
||||
this.application!.getStatusService().addStatusObserver((string: string) => {
|
||||
this.application.getStatusService().addStatusObserver((string: string) => {
|
||||
this.$timeout(() => {
|
||||
this.arbitraryStatusMessage = string;
|
||||
});
|
||||
});
|
||||
this.loadAccountSwitcherState();
|
||||
}
|
||||
|
||||
loadAccountSwitcherState() {
|
||||
const stringValue = localStorage.getItem(ACCOUNT_SWITCHER_FEATURE_KEY);
|
||||
if (!stringValue && ACCOUNT_SWITCHER_ENABLED) {
|
||||
/** Enable permanently for this user so they don't lose the feature after its disabled */
|
||||
localStorage.setItem(ACCOUNT_SWITCHER_FEATURE_KEY, JSON.stringify(true));
|
||||
}
|
||||
const hasAccountSwitcher = stringValue ? JSON.parse(stringValue) : ACCOUNT_SWITCHER_ENABLED;
|
||||
this.setState({ hasAccountSwitcher });
|
||||
}
|
||||
|
||||
getInitialState() {
|
||||
@@ -105,17 +126,24 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
dataUpgradeAvailable: false,
|
||||
hasPasscode: false,
|
||||
dockShortcuts: [],
|
||||
descriptors: this.mainApplicationGroup.getDescriptors(),
|
||||
hasAccountSwitcher: false
|
||||
};
|
||||
}
|
||||
|
||||
reloadUpgradeStatus() {
|
||||
this.application!.checkForSecurityUpdate().then((available) => {
|
||||
this.application.checkForSecurityUpdate().then((available) => {
|
||||
this.setState({
|
||||
dataUpgradeAvailable: available
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** @template */
|
||||
openAccountSwitcher() {
|
||||
this.application.openAccountSwitcher();
|
||||
}
|
||||
|
||||
async onAppLaunch() {
|
||||
super.onAppLaunch();
|
||||
this.reloadPasscodeStatus();
|
||||
@@ -128,11 +156,11 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
}
|
||||
|
||||
reloadUser() {
|
||||
this.user = this.application!.getUser();
|
||||
this.user = this.application.getUser();
|
||||
}
|
||||
|
||||
async reloadPasscodeStatus() {
|
||||
const hasPasscode = this.application!.hasPasscode();
|
||||
const hasPasscode = this.application.hasPasscode();
|
||||
this.setState({
|
||||
hasPasscode: hasPasscode
|
||||
});
|
||||
@@ -157,23 +185,23 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
this.closeAccountMenu();
|
||||
}
|
||||
} else if (eventName === AppStateEvent.BeganBackupDownload) {
|
||||
this.backupStatus = this.application!.getStatusService().addStatusFromString(
|
||||
this.backupStatus = this.application.getStatusService().addStatusFromString(
|
||||
"Saving local backup..."
|
||||
);
|
||||
} else if (eventName === AppStateEvent.EndedBackupDownload) {
|
||||
if (data.success) {
|
||||
this.backupStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||
this.backupStatus = this.application.getStatusService().replaceStatusWithString(
|
||||
this.backupStatus!,
|
||||
"Successfully saved backup."
|
||||
);
|
||||
} else {
|
||||
this.backupStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||
this.backupStatus = this.application.getStatusService().replaceStatusWithString(
|
||||
this.backupStatus!,
|
||||
"Unable to save local backup."
|
||||
);
|
||||
}
|
||||
this.$timeout(() => {
|
||||
this.backupStatus = this.application!.getStatusService().removeStatus(this.backupStatus!);
|
||||
this.backupStatus = this.application.getStatusService().removeStatus(this.backupStatus!);
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
@@ -199,7 +227,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
} else if (eventName === ApplicationEvent.CompletedFullSync) {
|
||||
if (!this.didCheckForOffline) {
|
||||
this.didCheckForOffline = true;
|
||||
if (this.offline && this.application!.getNoteCount() === 0) {
|
||||
if (this.offline && this.application.getNoteCount() === 0) {
|
||||
this.showAccountMenu = true;
|
||||
}
|
||||
}
|
||||
@@ -230,10 +258,10 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
}
|
||||
)
|
||||
|
||||
this.observerRemovers.push(this.application!.streamItems(
|
||||
this.observerRemovers.push(this.application.streamItems(
|
||||
ContentType.Component,
|
||||
async () => {
|
||||
const components = this.application!.getItems(ContentType.Component) as SNComponent[];
|
||||
const components = this.application.getItems(ContentType.Component) as SNComponent[];
|
||||
this.rooms = components.filter((candidate) => {
|
||||
return candidate.area === ComponentArea.Rooms && !candidate.deleted;
|
||||
});
|
||||
@@ -244,10 +272,10 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
}
|
||||
));
|
||||
|
||||
this.observerRemovers.push(this.application!.streamItems(
|
||||
this.observerRemovers.push(this.application.streamItems(
|
||||
ContentType.Theme,
|
||||
async () => {
|
||||
const themes = this.application!.getDisplayableItems(ContentType.Theme) as SNTheme[];
|
||||
const themes = this.application.getDisplayableItems(ContentType.Theme) as SNTheme[];
|
||||
this.themesWithIcons = themes;
|
||||
this.reloadDockShortcuts();
|
||||
}
|
||||
@@ -255,14 +283,14 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
}
|
||||
|
||||
registerComponentHandler() {
|
||||
this.unregisterComponent = this.application!.componentManager!.registerHandler({
|
||||
this.unregisterComponent = this.application.componentManager!.registerHandler({
|
||||
identifier: 'room-bar',
|
||||
areas: [ComponentArea.Rooms, ComponentArea.Modal],
|
||||
actionHandler: (component, action, data) => {
|
||||
if (action === ComponentAction.SetSize) {
|
||||
/** Do comparison to avoid repetitive calls by arbitrary component */
|
||||
if (!topLevelCompare(component.getLastSize(), data)) {
|
||||
this.application!.changeItem<ComponentMutator>(component.uuid, (mutator) => {
|
||||
this.application.changeItem<ComponentMutator>(component.uuid, (mutator) => {
|
||||
mutator.setLastSize(data);
|
||||
})
|
||||
}
|
||||
@@ -288,7 +316,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
* then closing it after a short delay.
|
||||
*/
|
||||
const extWindow = this.rooms.find((room) => {
|
||||
return room.package_info.identifier === this.application!
|
||||
return room.package_info.identifier === this.application
|
||||
.getNativeExtService().extManagerId;
|
||||
});
|
||||
if (!extWindow) {
|
||||
@@ -305,17 +333,17 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
}
|
||||
|
||||
updateOfflineStatus() {
|
||||
this.offline = this.application!.noAccount();
|
||||
this.offline = this.application.noAccount();
|
||||
}
|
||||
|
||||
async openSecurityUpdate() {
|
||||
preventRefreshing(STRING_CONFIRM_APP_QUIT_DURING_UPGRADE, async () => {
|
||||
await this.application!.performProtocolUpgrade();
|
||||
await this.application.performProtocolUpgrade();
|
||||
});
|
||||
}
|
||||
|
||||
findErrors() {
|
||||
this.hasError = this.application!.getSyncStatus().hasError();
|
||||
this.hasError = this.application.getSyncStatus().hasError();
|
||||
}
|
||||
|
||||
accountMenuPressed() {
|
||||
@@ -332,12 +360,12 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
}
|
||||
|
||||
lockApp() {
|
||||
this.application!.lock();
|
||||
this.application.lock();
|
||||
}
|
||||
|
||||
refreshData() {
|
||||
this.isRefreshing = true;
|
||||
this.application!.sync({
|
||||
this.application.sync({
|
||||
queueStrategy: SyncQueueStrategy.ForceSpawnNew,
|
||||
checkIntegrity: true
|
||||
}).then((response) => {
|
||||
@@ -345,7 +373,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
this.isRefreshing = false;
|
||||
}, 200);
|
||||
if (response && response.error) {
|
||||
this.application!.alertService!.alert(
|
||||
this.application.alertService!.alert(
|
||||
STRING_GENERIC_SYNC_ERROR
|
||||
);
|
||||
} else {
|
||||
@@ -355,7 +383,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
}
|
||||
|
||||
syncUpdated() {
|
||||
this.lastSyncDate = dateToLocalizedString(this.application!.getLastSyncDate()!);
|
||||
this.lastSyncDate = dateToLocalizedString(this.application.getLastSyncDate()!);
|
||||
}
|
||||
|
||||
onNewUpdateAvailable() {
|
||||
@@ -364,7 +392,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
|
||||
clickedNewUpdateAnnouncement() {
|
||||
this.newUpdateAvailable = false;
|
||||
this.application!.alertService!.alert(
|
||||
this.application.alertService!.alert(
|
||||
STRING_NEW_UPDATE_READY
|
||||
);
|
||||
}
|
||||
@@ -409,7 +437,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
}
|
||||
|
||||
selectShortcut(shortcut: DockShortcut) {
|
||||
this.application!.toggleComponent(shortcut.component);
|
||||
this.application.toggleComponent(shortcut.component);
|
||||
}
|
||||
|
||||
onRoomDismiss(room: SNComponent) {
|
||||
@@ -430,12 +458,12 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
};
|
||||
|
||||
if (!this.roomShowState[room.uuid]) {
|
||||
const requiresPrivilege = await this.application!.privilegesService!
|
||||
const requiresPrivilege = await this.application.privilegesService!
|
||||
.actionRequiresPrivilege(
|
||||
ProtectedAction.ManageExtensions
|
||||
);
|
||||
if (requiresPrivilege) {
|
||||
this.application!.presentPrivilegesModal(
|
||||
this.application.presentPrivilegesModal(
|
||||
ProtectedAction.ManageExtensions,
|
||||
run
|
||||
);
|
||||
@@ -448,7 +476,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
|
||||
}
|
||||
|
||||
clickOutsideAccountMenu() {
|
||||
if (this.application && this.application!.authenticationInProgress()) {
|
||||
if (this.application && this.application.authenticationInProgress()) {
|
||||
return;
|
||||
}
|
||||
this.showAccountMenu = false;
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
NoteSortKey,
|
||||
notePassesFilter
|
||||
} from './note_utils';
|
||||
import { UuidString } from '@node_modules/snjs/dist/@types/types';
|
||||
import { UuidString } from 'snjs/dist/@types/types';
|
||||
|
||||
type NotesState = {
|
||||
panelTitle: string
|
||||
|
||||
Reference in New Issue
Block a user