Footer TS
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
|
import { PanelPuppet, WebDirective, PermissionsModalScope, ModalComponentScope } from './../types';
|
||||||
import { getPlatformString } from '@/utils';
|
import { getPlatformString } from '@/utils';
|
||||||
import template from '%/application-view.pug';
|
import template from '%/application-view.pug';
|
||||||
import { AppStateEvent } from '@/services/state';
|
import { AppStateEvent } from '@/services/state';
|
||||||
import { ApplicationEvent } from 'snjs';
|
import { ApplicationEvent, SNComponent } from 'snjs';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import {
|
import {
|
||||||
PANEL_NAME_NOTES,
|
PANEL_NAME_NOTES,
|
||||||
@@ -12,14 +13,27 @@ import {
|
|||||||
STRING_DEFAULT_FILE_ERROR
|
STRING_DEFAULT_FILE_ERROR
|
||||||
} from '@/strings';
|
} from '@/strings';
|
||||||
import { PureCtrl } from './abstract/pure_ctrl';
|
import { PureCtrl } from './abstract/pure_ctrl';
|
||||||
|
import { PermissionDialog } from '@/../../../../snjs/dist/@types/services/component_manager';
|
||||||
|
|
||||||
class ApplicationViewCtrl extends PureCtrl {
|
class ApplicationViewCtrl extends PureCtrl {
|
||||||
|
private $compile?: ng.ICompileService
|
||||||
|
private $location?: ng.ILocationService
|
||||||
|
private $rootScope?: ng.IRootScopeService
|
||||||
|
public platformString: string
|
||||||
|
private completedInitialSync = false
|
||||||
|
private syncStatus: any
|
||||||
|
private notesCollapsed = false
|
||||||
|
private tagsCollapsed = false
|
||||||
|
private showingDownloadStatus = false
|
||||||
|
private uploadSyncStatus: any
|
||||||
|
private lastAlertShownDate?: Date
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$compile,
|
$compile: ng.ICompileService,
|
||||||
$location,
|
$location: ng.ILocationService,
|
||||||
$rootScope,
|
$rootScope: ng.IRootScopeService,
|
||||||
$timeout
|
$timeout: ng.ITimeoutService
|
||||||
) {
|
) {
|
||||||
super($timeout);
|
super($timeout);
|
||||||
this.$location = $location;
|
this.$location = $location;
|
||||||
@@ -35,17 +49,16 @@ class ApplicationViewCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deinit() {
|
deinit() {
|
||||||
this.$location = null;
|
this.$location = undefined;
|
||||||
this.$rootScope = null;
|
this.$rootScope = undefined;
|
||||||
this.$compile = null;
|
this.$compile = undefined;
|
||||||
this.application = null;
|
this.application = undefined;
|
||||||
this.lockScreenPuppet = null;
|
|
||||||
window.removeEventListener('dragover', this.onDragOver, true);
|
window.removeEventListener('dragover', this.onDragOver, true);
|
||||||
window.removeEventListener('drop', this.onDragDrop, true);
|
window.removeEventListener('drop', this.onDragDrop, true);
|
||||||
this.onDragDrop = null;
|
(this.onDragDrop as any) = undefined;
|
||||||
this.onDragOver = null;
|
(this.onDragOver as any) = undefined;
|
||||||
this.openModalComponent = null;
|
(this.openModalComponent as any) = undefined;
|
||||||
this.presentPermissionsDialog = null;
|
(this.presentPermissionsDialog as any) = undefined;
|
||||||
super.deinit();
|
super.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,41 +68,39 @@ class ApplicationViewCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadApplication() {
|
async loadApplication() {
|
||||||
await this.application.prepareForLaunch({
|
await this.application!.prepareForLaunch({
|
||||||
callbacks: {
|
receiveChallenge: async (challenge, orchestrator) => {
|
||||||
receiveChallenge: async (challenge, orchestrator) => {
|
this.application!.promptForChallenge(challenge, orchestrator);
|
||||||
this.application.promptForChallenge(challenge, orchestrator);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await this.application.launch();
|
await this.application!.launch();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onAppStart() {
|
async onAppStart() {
|
||||||
super.onAppStart();
|
super.onAppStart();
|
||||||
this.overrideComponentManagerFunctions();
|
this.overrideComponentManagerFunctions();
|
||||||
this.application.componentManager.setDesktopManager(
|
this.application!.componentManager!.setDesktopManager(
|
||||||
this.application.getDesktopService()
|
this.application!.getDesktopService()
|
||||||
);
|
);
|
||||||
this.setState({
|
this.setState({
|
||||||
ready: true,
|
ready: true,
|
||||||
needsUnlock: this.application.hasPasscode()
|
needsUnlock: this.application!.hasPasscode()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onAppLaunch() {
|
async onAppLaunch() {
|
||||||
super.onAppLaunch();
|
super.onAppLaunch();
|
||||||
this.setState({ needsUnlock: false });
|
this.setState({ needsUnlock: false });
|
||||||
this.handleAutoSignInFromParams();
|
this.handleAutoSignInFromParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdateAvailable() {
|
onUpdateAvailable() {
|
||||||
this.$rootScope.$broadcast('new-update-available');
|
this.$rootScope!.$broadcast('new-update-available');
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async onAppEvent(eventName) {
|
async onAppEvent(eventName: ApplicationEvent) {
|
||||||
super.onAppEvent(eventName);
|
super.onAppEvent(eventName);
|
||||||
if (eventName === ApplicationEvent.LocalDataIncrementalLoad) {
|
if (eventName === ApplicationEvent.LocalDataIncrementalLoad) {
|
||||||
this.updateLocalDataStatus();
|
this.updateLocalDataStatus();
|
||||||
@@ -102,31 +113,31 @@ class ApplicationViewCtrl extends PureCtrl {
|
|||||||
this.updateLocalDataStatus();
|
this.updateLocalDataStatus();
|
||||||
} else if (eventName === ApplicationEvent.WillSync) {
|
} else if (eventName === ApplicationEvent.WillSync) {
|
||||||
if (!this.completedInitialSync) {
|
if (!this.completedInitialSync) {
|
||||||
this.syncStatus = this.application.getStatusService().replaceStatusWithString(
|
this.syncStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||||
this.syncStatus,
|
this.syncStatus,
|
||||||
"Syncing..."
|
"Syncing..."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (eventName === ApplicationEvent.CompletedSync) {
|
} else if (eventName === ApplicationEvent.CompletedSync) {
|
||||||
if (!this.completedInitialSync) {
|
if (!this.completedInitialSync) {
|
||||||
this.syncStatus = this.application.getStatusService().removeStatus(this.syncStatus);
|
this.syncStatus = this.application!.getStatusService().removeStatus(this.syncStatus);
|
||||||
this.completedInitialSync = true;
|
this.completedInitialSync = true;
|
||||||
}
|
}
|
||||||
} else if (eventName === ApplicationEvent.InvalidSyncSession) {
|
} else if (eventName === ApplicationEvent.InvalidSyncSession) {
|
||||||
this.showInvalidSessionAlert();
|
this.showInvalidSessionAlert();
|
||||||
} else if (eventName === ApplicationEvent.LocalDatabaseReadError) {
|
} else if (eventName === ApplicationEvent.LocalDatabaseReadError) {
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: 'Unable to load local database. Please restart the app and try again.'
|
'Unable to load local database. Please restart the app and try again.'
|
||||||
});
|
);
|
||||||
} else if (eventName === ApplicationEvent.LocalDatabaseWriteError) {
|
} else if (eventName === ApplicationEvent.LocalDatabaseWriteError) {
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: 'Unable to write to local database. Please restart the app and try again.'
|
'Unable to write to local database. Please restart the app and try again.'
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async onAppStateEvent(eventName, data) {
|
async onAppStateEvent(eventName: AppStateEvent, data?: any) {
|
||||||
if (eventName === AppStateEvent.PanelResized) {
|
if (eventName === AppStateEvent.PanelResized) {
|
||||||
if (data.panel === PANEL_NAME_NOTES) {
|
if (data.panel === PANEL_NAME_NOTES) {
|
||||||
this.notesCollapsed = data.collapsed;
|
this.notesCollapsed = data.collapsed;
|
||||||
@@ -139,41 +150,41 @@ class ApplicationViewCtrl extends PureCtrl {
|
|||||||
if (this.tagsCollapsed) { appClass += " collapsed-tags"; }
|
if (this.tagsCollapsed) { appClass += " collapsed-tags"; }
|
||||||
this.setState({ appClass });
|
this.setState({ appClass });
|
||||||
} else if (eventName === AppStateEvent.WindowDidFocus) {
|
} else if (eventName === AppStateEvent.WindowDidFocus) {
|
||||||
if (!(await this.application.isLocked())) {
|
if (!(await this.application!.isLocked())) {
|
||||||
this.application.sync();
|
this.application!.sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLocalDataStatus() {
|
updateLocalDataStatus() {
|
||||||
const syncStatus = this.application.getSyncStatus();
|
const syncStatus = this.application!.getSyncStatus();
|
||||||
const stats = syncStatus.getStats();
|
const stats = syncStatus.getStats();
|
||||||
const encryption = this.application.isEncryptionAvailable();
|
const encryption = this.application!.isEncryptionAvailable();
|
||||||
if (stats.localDataDone) {
|
if (stats.localDataDone) {
|
||||||
this.syncStatus = this.application.getStatusService().removeStatus(this.syncStatus);
|
this.syncStatus = this.application!.getStatusService().removeStatus(this.syncStatus);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const notesString = `${stats.localDataCurrent}/${stats.localDataTotal} items...`;
|
const notesString = `${stats.localDataCurrent}/${stats.localDataTotal} items...`;
|
||||||
const loadingStatus = encryption
|
const loadingStatus = encryption
|
||||||
? `Decrypting ${notesString}`
|
? `Decrypting ${notesString}`
|
||||||
: `Loading ${notesString}`;
|
: `Loading ${notesString}`;
|
||||||
this.syncStatus = this.application.getStatusService().replaceStatusWithString(
|
this.syncStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||||
this.syncStatus,
|
this.syncStatus,
|
||||||
loadingStatus
|
loadingStatus
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSyncStatus() {
|
updateSyncStatus() {
|
||||||
const syncStatus = this.application.getSyncStatus();
|
const syncStatus = this.application!.getSyncStatus();
|
||||||
const stats = syncStatus.getStats();
|
const stats = syncStatus.getStats();
|
||||||
if (syncStatus.hasError()) {
|
if (syncStatus.hasError()) {
|
||||||
this.syncStatus = this.application.getStatusService().replaceStatusWithString(
|
this.syncStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||||
this.syncStatus,
|
this.syncStatus,
|
||||||
'Unable to Sync'
|
'Unable to Sync'
|
||||||
);
|
);
|
||||||
} else if (stats.downloadCount > 20) {
|
} else if (stats.downloadCount > 20) {
|
||||||
const text = `Downloading ${stats.downloadCount} items. Keep app open.`;
|
const text = `Downloading ${stats.downloadCount} items. Keep app open.`;
|
||||||
this.syncStatus = this.application.getStatusService().replaceStatusWithString(
|
this.syncStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||||
this.syncStatus,
|
this.syncStatus,
|
||||||
text
|
text
|
||||||
);
|
);
|
||||||
@@ -181,56 +192,63 @@ class ApplicationViewCtrl extends PureCtrl {
|
|||||||
} else if (this.showingDownloadStatus) {
|
} else if (this.showingDownloadStatus) {
|
||||||
this.showingDownloadStatus = false;
|
this.showingDownloadStatus = false;
|
||||||
const text = "Download Complete.";
|
const text = "Download Complete.";
|
||||||
this.syncStatus = this.application.getStatusService().replaceStatusWithString(
|
this.syncStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||||
this.syncStatus,
|
this.syncStatus,
|
||||||
text
|
text
|
||||||
);
|
);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.syncStatus = this.application.getStatusService().removeStatus(this.syncStatus);
|
this.syncStatus = this.application!.getStatusService().removeStatus(this.syncStatus);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
} else if (stats.uploadTotalCount > 20) {
|
} else if (stats.uploadTotalCount > 20) {
|
||||||
this.uploadSyncStatus = this.application.getStatusService().replaceStatusWithString(
|
this.uploadSyncStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||||
this.uploadSyncStatus,
|
this.uploadSyncStatus,
|
||||||
`Syncing ${stats.uploadCompletionCount}/${stats.uploadTotalCount} items...`
|
`Syncing ${stats.uploadCompletionCount}/${stats.uploadTotalCount} items...`
|
||||||
);
|
);
|
||||||
} else if (this.uploadSyncStatus) {
|
} else if (this.uploadSyncStatus) {
|
||||||
this.uploadSyncStatus = this.application.getStatusService().removeStatus(
|
this.uploadSyncStatus = this.application!.getStatusService().removeStatus(
|
||||||
this.uploadSyncStatus
|
this.uploadSyncStatus
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openModalComponent(component) {
|
openModalComponent(component: SNComponent) {
|
||||||
const scope = this.$rootScope.$new(true);
|
const scope = this.$rootScope!.$new(true) as ModalComponentScope;
|
||||||
scope.component = component;
|
scope.component = component;
|
||||||
const el = this.$compile("<component-modal component='component' class='sk-modal'></component-modal>")(scope);
|
const el = this.$compile!(
|
||||||
|
"<component-modal component='component' class='sk-modal'></component-modal>"
|
||||||
|
)(scope as any);
|
||||||
angular.element(document.body).append(el);
|
angular.element(document.body).append(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
presentPermissionsDialog(dialog) {
|
presentPermissionsDialog(dialog: PermissionDialog) {
|
||||||
const scope = this.$rootScope.$new(true);
|
const scope = this.$rootScope!.$new(true) as PermissionsModalScope;
|
||||||
scope.permissionsString = dialog.permissionsString;
|
scope.permissionsString = dialog.permissionsString;
|
||||||
scope.component = dialog.component;
|
scope.component = dialog.component;
|
||||||
scope.callback = dialog.callback;
|
scope.callback = dialog.callback;
|
||||||
const el = this.$compile("<permissions-modal component='component' permissions-string='permissionsString' callback='callback' class='sk-modal'></permissions-modal>")(scope);
|
const el = this.$compile!(
|
||||||
|
"<permissions-modal component='component' permissions-string='permissionsString'"
|
||||||
|
+ " callback='callback' class='sk-modal'></permissions-modal>"
|
||||||
|
)(scope as any);
|
||||||
angular.element(document.body).append(el);
|
angular.element(document.body).append(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
overrideComponentManagerFunctions() {
|
overrideComponentManagerFunctions() {
|
||||||
this.application.componentManager.openModalComponent = this.openModalComponent;
|
this.application!.componentManager!.openModalComponent = this.openModalComponent;
|
||||||
this.application.componentManager.presentPermissionsDialog = this.presentPermissionsDialog;
|
this.application!.componentManager!.presentPermissionsDialog = this.presentPermissionsDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
showInvalidSessionAlert() {
|
showInvalidSessionAlert() {
|
||||||
/** Don't show repeatedly; at most 30 seconds in between */
|
/** Don't show repeatedly; at most 30 seconds in between */
|
||||||
const SHOW_INTERVAL = 30;
|
const SHOW_INTERVAL = 30;
|
||||||
const lastShownSeconds = (new Date() - this.lastShownDate) / 1000;
|
if (
|
||||||
if (!this.lastShownDate || lastShownSeconds > SHOW_INTERVAL) {
|
!this.lastAlertShownDate ||
|
||||||
this.lastShownDate = new Date();
|
(new Date().getTime() - this.lastAlertShownDate!.getTime()) / 1000 > SHOW_INTERVAL
|
||||||
|
) {
|
||||||
|
this.lastAlertShownDate = new Date();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: STRING_SESSION_EXPIRED
|
STRING_SESSION_EXPIRED
|
||||||
});
|
);
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,49 +263,49 @@ class ApplicationViewCtrl extends PureCtrl {
|
|||||||
window.addEventListener('drop', this.onDragDrop, true);
|
window.addEventListener('drop', this.onDragDrop, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDragOver(event) {
|
onDragOver(event: DragEvent) {
|
||||||
if (event.dataTransfer.files.length > 0) {
|
if (event.dataTransfer!.files.length > 0) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDragDrop(event) {
|
onDragDrop(event: DragEvent) {
|
||||||
if (event.dataTransfer.files.length > 0) {
|
if (event.dataTransfer!.files.length > 0) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: STRING_DEFAULT_FILE_ERROR
|
STRING_DEFAULT_FILE_ERROR
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleAutoSignInFromParams() {
|
async handleAutoSignInFromParams() {
|
||||||
const params = this.$location.search();
|
const params = this.$location!.search();
|
||||||
const server = params.server;
|
const server = params.server;
|
||||||
const email = params.email;
|
const email = params.email;
|
||||||
const password = params.pw;
|
const password = params.pw;
|
||||||
if (!server || !email || !password) return;
|
if (!server || !email || !password) return;
|
||||||
|
|
||||||
const user = this.application.getUser();
|
const user = this.application!.getUser();
|
||||||
if (user) {
|
if (user) {
|
||||||
if (user.email === email && await this.application.getHost() === server) {
|
if (user.email === email && await this.application!.getHost() === server) {
|
||||||
/** Already signed in, return */
|
/** Already signed in, return */
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
/** Sign out */
|
/** Sign out */
|
||||||
await this.application.signOut();
|
await this.application!.signOut();
|
||||||
await this.application.restart();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.application.setHost(server);
|
await this.application!.setHost(server);
|
||||||
this.application.signIn({
|
this.application!.signIn(
|
||||||
email: email,
|
email,
|
||||||
password: password,
|
password,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ApplicationView {
|
export class ApplicationView extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
super();
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.controller = ApplicationViewCtrl;
|
this.controller = ApplicationViewCtrl;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
|
import { FooterStatus, WebDirective } from './../types';
|
||||||
import { dateToLocalizedString } from '@/utils';
|
import { dateToLocalizedString } from '@/utils';
|
||||||
import {
|
import {
|
||||||
ApplicationEvent,
|
ApplicationEvent,
|
||||||
TIMING_STRATEGY_FORCE_SPAWN_NEW,
|
SyncQueueStrategy,
|
||||||
ProtectedAction,
|
ProtectedAction,
|
||||||
ContentTypes
|
ContentType,
|
||||||
|
SNComponent,
|
||||||
|
SNTheme,
|
||||||
|
ComponentArea,
|
||||||
|
ComponentAction
|
||||||
} from 'snjs';
|
} from 'snjs';
|
||||||
import template from '%/footer.pug';
|
import template from '%/footer.pug';
|
||||||
import { AppStateEvent, EventSource } from '@/services/state';
|
import { AppStateEvent, EventSource } from '@/services/state';
|
||||||
@@ -11,40 +16,71 @@ import {
|
|||||||
STRING_GENERIC_SYNC_ERROR,
|
STRING_GENERIC_SYNC_ERROR,
|
||||||
STRING_NEW_UPDATE_READY
|
STRING_NEW_UPDATE_READY
|
||||||
} from '@/strings';
|
} from '@/strings';
|
||||||
import { PureCtrl } from '@Controllers';
|
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
||||||
|
import { ComponentMutator } from '@/../../../../snjs/dist/@types/models';
|
||||||
|
|
||||||
|
type DockShortcut = {
|
||||||
|
name: string,
|
||||||
|
component: SNComponent,
|
||||||
|
icon: {
|
||||||
|
type: string
|
||||||
|
background_color: string
|
||||||
|
border_color: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FooterCtrl extends PureCtrl {
|
class FooterCtrl extends PureCtrl {
|
||||||
|
|
||||||
|
private $rootScope: ng.IRootScopeService
|
||||||
|
private rooms: SNComponent[] = []
|
||||||
|
private themesWithIcons: SNTheme[] = []
|
||||||
|
private showSyncResolution = false
|
||||||
|
private unregisterComponent: any
|
||||||
|
private rootScopeListener1: any
|
||||||
|
private rootScopeListener2: any
|
||||||
|
public arbitraryStatusMessage?: string
|
||||||
|
public user?: any
|
||||||
|
private backupStatus?: FooterStatus
|
||||||
|
private offline = true
|
||||||
|
private showAccountMenu = false
|
||||||
|
private queueExtReload = false
|
||||||
|
private reloadInProgress = false
|
||||||
|
public hasError = false
|
||||||
|
public isRefreshing = false
|
||||||
|
public lastSyncDate?: string
|
||||||
|
public newUpdateAvailable = false
|
||||||
|
public dockShortcuts: DockShortcut[] = []
|
||||||
|
public roomShowState: Partial<Record<string, boolean>> = {}
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$rootScope,
|
$rootScope: ng.IRootScopeService,
|
||||||
$timeout,
|
$timeout: ng.ITimeoutService,
|
||||||
) {
|
) {
|
||||||
super($timeout);
|
super($timeout);
|
||||||
this.$rootScope = $rootScope;
|
this.$rootScope = $rootScope;
|
||||||
this.rooms = [];
|
|
||||||
this.themesWithIcons = [];
|
|
||||||
this.showSyncResolution = false;
|
|
||||||
this.addRootScopeListeners();
|
this.addRootScopeListeners();
|
||||||
|
this.toggleSyncResolutionMenu = this.toggleSyncResolutionMenu.bind(this);
|
||||||
|
this.closeAccountMenu = this.closeAccountMenu.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit() {
|
deinit() {
|
||||||
this.rooms.length = 0;
|
this.rooms.length = 0;
|
||||||
this.themesWithIcons.length = 0;
|
this.themesWithIcons.length = 0;
|
||||||
this.unregisterComponent();
|
this.unregisterComponent();
|
||||||
this.unregisterComponent = null;
|
this.unregisterComponent = undefined;
|
||||||
this.rootScopeListener1();
|
this.rootScopeListener1();
|
||||||
this.rootScopeListener2();
|
this.rootScopeListener2();
|
||||||
this.rootScopeListener1 = null;
|
this.rootScopeListener1 = undefined;
|
||||||
this.rootScopeListener2 = null;
|
this.rootScopeListener2 = undefined;
|
||||||
this.closeAccountMenu = null;
|
(this.closeAccountMenu as any) = undefined;
|
||||||
this.toggleSyncResolutionMenu = null;
|
(this.toggleSyncResolutionMenu as any) = undefined;
|
||||||
super.deinit();
|
super.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
super.$onInit();
|
super.$onInit();
|
||||||
this.application.getStatusService().addStatusObserver((string) => {
|
this.application!.getStatusService().addStatusObserver((string: string) => {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.arbitraryStatusMessage = string;
|
this.arbitraryStatusMessage = string;
|
||||||
});
|
});
|
||||||
@@ -58,18 +94,18 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reloadUpgradeStatus() {
|
reloadUpgradeStatus() {
|
||||||
this.application.checkForSecurityUpdate().then((available) => {
|
this.application!.checkForSecurityUpdate().then((available) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
dataUpgradeAvailable: available
|
dataUpgradeAvailable: available
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onAppLaunch() {
|
async onAppLaunch() {
|
||||||
super.onAppLaunch();
|
super.onAppLaunch();
|
||||||
this.reloadPasscodeStatus();
|
this.reloadPasscodeStatus();
|
||||||
this.reloadUpgradeStatus();
|
this.reloadUpgradeStatus();
|
||||||
this.user = this.application.getUser();
|
this.user = this.application!.getUser();
|
||||||
this.updateOfflineStatus();
|
this.updateOfflineStatus();
|
||||||
this.findErrors();
|
this.findErrors();
|
||||||
this.streamItems();
|
this.streamItems();
|
||||||
@@ -77,7 +113,7 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async reloadPasscodeStatus() {
|
async reloadPasscodeStatus() {
|
||||||
const hasPasscode = this.application.hasPasscode();
|
const hasPasscode = this.application!.hasPasscode();
|
||||||
this.setState({
|
this.setState({
|
||||||
hasPasscode: hasPasscode
|
hasPasscode: hasPasscode
|
||||||
});
|
});
|
||||||
@@ -95,30 +131,30 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
onAppStateEvent(eventName, data) {
|
onAppStateEvent(eventName: AppStateEvent, data: any) {
|
||||||
if (eventName === AppStateEvent.EditorFocused) {
|
if (eventName === AppStateEvent.EditorFocused) {
|
||||||
if (data.eventSource === EventSource.UserInteraction) {
|
if (data.eventSource === EventSource.UserInteraction) {
|
||||||
this.closeAllRooms();
|
this.closeAllRooms();
|
||||||
this.closeAccountMenu();
|
this.closeAccountMenu();
|
||||||
}
|
}
|
||||||
} else if (eventName === AppStateEvent.BeganBackupDownload) {
|
} else if (eventName === AppStateEvent.BeganBackupDownload) {
|
||||||
this.backupStatus = this.application.getStatusService().addStatusFromString(
|
this.backupStatus = this.application!.getStatusService().addStatusFromString(
|
||||||
"Saving local backup..."
|
"Saving local backup..."
|
||||||
);
|
);
|
||||||
} else if (eventName === AppStateEvent.EndedBackupDownload) {
|
} else if (eventName === AppStateEvent.EndedBackupDownload) {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
this.backupStatus = this.application.getStatusService().replaceStatusWithString(
|
this.backupStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||||
this.backupStatus,
|
this.backupStatus!,
|
||||||
"Successfully saved backup."
|
"Successfully saved backup."
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.backupStatus = this.application.getStatusService().replaceStatusWithString(
|
this.backupStatus = this.application!.getStatusService().replaceStatusWithString(
|
||||||
this.backupStatus,
|
this.backupStatus!,
|
||||||
"Unable to save local backup."
|
"Unable to save local backup."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.backupStatus = this.application.getStatusService().removeStatus(this.backupStatus);
|
this.backupStatus = this.application!.getStatusService().removeStatus(this.backupStatus!);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,7 +167,7 @@ class FooterCtrl extends PureCtrl {
|
|||||||
|
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
onAppEvent(eventName) {
|
onAppEvent(eventName: ApplicationEvent) {
|
||||||
if (eventName === ApplicationEvent.KeyStatusChanged) {
|
if (eventName === ApplicationEvent.KeyStatusChanged) {
|
||||||
this.reloadUpgradeStatus();
|
this.reloadUpgradeStatus();
|
||||||
} else if (eventName === ApplicationEvent.EnteredOutOfSync) {
|
} else if (eventName === ApplicationEvent.EnteredOutOfSync) {
|
||||||
@@ -143,7 +179,7 @@ class FooterCtrl extends PureCtrl {
|
|||||||
outOfSync: false
|
outOfSync: false
|
||||||
});
|
});
|
||||||
} else if (eventName === ApplicationEvent.CompletedSync) {
|
} else if (eventName === ApplicationEvent.CompletedSync) {
|
||||||
if (this.offline && this.application.getNoteCount() === 0) {
|
if (this.offline && this.application!.getNoteCount() === 0) {
|
||||||
this.showAccountMenu = true;
|
this.showAccountMenu = true;
|
||||||
}
|
}
|
||||||
this.syncUpdated();
|
this.syncUpdated();
|
||||||
@@ -156,52 +192,53 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
streamItems() {
|
streamItems() {
|
||||||
this.application.streamItems({
|
this.application!.streamItems(
|
||||||
contentType: ContentType.Component,
|
ContentType.Component,
|
||||||
stream: async () => {
|
async () => {
|
||||||
this.rooms = this.application.getItems({
|
const components = this.application!.getItems(ContentType.Component) as SNComponent[];
|
||||||
contentType: ContentType.Component
|
this.rooms = components.filter((candidate) => {
|
||||||
}).filter((candidate) => {
|
return candidate.area === ComponentArea.Rooms && !candidate.deleted;
|
||||||
return candidate.area === 'rooms' && !candidate.deleted;
|
|
||||||
});
|
});
|
||||||
if (this.queueExtReload) {
|
if (this.queueExtReload) {
|
||||||
this.queueExtReload = false;
|
this.queueExtReload = false;
|
||||||
this.reloadExtendedData();
|
this.reloadExtendedData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
this.application.streamItems({
|
this.application!.streamItems(
|
||||||
contentType: 'SN|Theme',
|
ContentType.Theme,
|
||||||
stream: async () => {
|
async () => {
|
||||||
const themes = this.application.getDisplayableItems({
|
const themes = this.application!.getDisplayableItems(ContentType.Theme) as SNTheme[];
|
||||||
contentType: ContentType.Theme
|
const filteredThemes = themes.filter((candidate) => {
|
||||||
}).filter((candidate) => {
|
|
||||||
return (
|
return (
|
||||||
!candidate.deleted &&
|
!candidate.deleted &&
|
||||||
candidate.content.package_info &&
|
candidate.package_info &&
|
||||||
candidate.content.package_info.dock_icon
|
candidate.package_info.dock_icon
|
||||||
);
|
);
|
||||||
}).sort((a, b) => {
|
}).sort((a, b) => {
|
||||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||||
});
|
});
|
||||||
const differ = themes.length !== this.themesWithIcons.length;
|
const differ = filteredThemes.length !== this.themesWithIcons.length;
|
||||||
this.themesWithIcons = themes;
|
this.themesWithIcons = filteredThemes;
|
||||||
if (differ) {
|
if (differ) {
|
||||||
this.reloadDockShortcuts();
|
this.reloadDockShortcuts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerComponentHandler() {
|
registerComponentHandler() {
|
||||||
this.unregisterComponent = this.application.componentManager.registerHandler({
|
this.unregisterComponent = this.application!.componentManager!.registerHandler({
|
||||||
identifier: "roomBar",
|
identifier: 'room-bar',
|
||||||
areas: ["rooms", "modal"],
|
areas: [ComponentArea.Rooms, ComponentArea.Modal],
|
||||||
activationHandler: (component) => { },
|
activationHandler: () => { },
|
||||||
actionHandler: (component, action, data) => {
|
actionHandler: (component, action, data) => {
|
||||||
if (action === "set-size") {
|
if (action === ComponentAction.SetSize) {
|
||||||
component.setLastSize(data);
|
this.application!.changeItem(component.uuid, (m) => {
|
||||||
|
const mutator = m as ComponentMutator;
|
||||||
|
mutator.setLastSize(data);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
focusHandler: (component, focused) => {
|
focusHandler: (component, focused) => {
|
||||||
@@ -224,7 +261,8 @@ class FooterCtrl extends PureCtrl {
|
|||||||
* then closing it after a short delay.
|
* then closing it after a short delay.
|
||||||
*/
|
*/
|
||||||
const extWindow = this.rooms.find((room) => {
|
const extWindow = this.rooms.find((room) => {
|
||||||
return room.package_info.identifier === this.application.getNativeExtService().extManagerId;
|
return room.package_info.identifier === this.application!
|
||||||
|
.getNativeExtService().extManagerId;
|
||||||
});
|
});
|
||||||
if (!extWindow) {
|
if (!extWindow) {
|
||||||
this.queueExtReload = true;
|
this.queueExtReload = true;
|
||||||
@@ -240,15 +278,15 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateOfflineStatus() {
|
updateOfflineStatus() {
|
||||||
this.offline = this.application.noAccount();
|
this.offline = this.application!.noAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
openSecurityUpdate() {
|
openSecurityUpdate() {
|
||||||
this.application.performProtocolUpgrade();
|
this.application!.performProtocolUpgrade();
|
||||||
}
|
}
|
||||||
|
|
||||||
findErrors() {
|
findErrors() {
|
||||||
this.error = this.application.getSyncStatus().error;
|
this.hasError = this.application!.getSyncStatus().hasError();
|
||||||
}
|
}
|
||||||
|
|
||||||
accountMenuPressed() {
|
accountMenuPressed() {
|
||||||
@@ -256,31 +294,31 @@ class FooterCtrl extends PureCtrl {
|
|||||||
this.closeAllRooms();
|
this.closeAllRooms();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSyncResolutionMenu = () => {
|
toggleSyncResolutionMenu() {
|
||||||
this.showSyncResolution = !this.showSyncResolution;
|
this.showSyncResolution = !this.showSyncResolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
closeAccountMenu = () => {
|
closeAccountMenu() {
|
||||||
this.showAccountMenu = false;
|
this.showAccountMenu = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
lockApp() {
|
lockApp() {
|
||||||
this.application.lock();
|
this.application!.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshData() {
|
refreshData() {
|
||||||
this.isRefreshing = true;
|
this.isRefreshing = true;
|
||||||
this.application.sync({
|
this.application!.sync({
|
||||||
timingStrategy: TIMING_STRATEGY_FORCE_SPAWN_NEW,
|
queueStrategy: SyncQueueStrategy.ForceSpawnNew,
|
||||||
checkIntegrity: true
|
checkIntegrity: true
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.isRefreshing = false;
|
this.isRefreshing = false;
|
||||||
}, 200);
|
}, 200);
|
||||||
if (response && response.error) {
|
if (response && response.error) {
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: STRING_GENERIC_SYNC_ERROR
|
STRING_GENERIC_SYNC_ERROR
|
||||||
});
|
);
|
||||||
} else {
|
} else {
|
||||||
this.syncUpdated();
|
this.syncUpdated();
|
||||||
}
|
}
|
||||||
@@ -288,7 +326,7 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
syncUpdated() {
|
syncUpdated() {
|
||||||
this.lastSyncDate = dateToLocalizedString(this.application.getLastSyncDate());
|
this.lastSyncDate = dateToLocalizedString(this.application!.getLastSyncDate()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
onNewUpdateAvailable() {
|
onNewUpdateAvailable() {
|
||||||
@@ -297,16 +335,16 @@ class FooterCtrl extends PureCtrl {
|
|||||||
|
|
||||||
clickedNewUpdateAnnouncement() {
|
clickedNewUpdateAnnouncement() {
|
||||||
this.newUpdateAvailable = false;
|
this.newUpdateAvailable = false;
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: STRING_NEW_UPDATE_READY
|
STRING_NEW_UPDATE_READY
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadDockShortcuts() {
|
reloadDockShortcuts() {
|
||||||
const shortcuts = [];
|
const shortcuts = [];
|
||||||
for (const theme of this.themesWithIcons) {
|
for (const theme of this.themesWithIcons) {
|
||||||
const name = theme.content.package_info.name;
|
const name = theme.package_info.name;
|
||||||
const icon = theme.content.package_info.dock_icon;
|
const icon = theme.package_info.dock_icon;
|
||||||
if (!icon) {
|
if (!icon) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -314,7 +352,7 @@ class FooterCtrl extends PureCtrl {
|
|||||||
name: name,
|
name: name,
|
||||||
component: theme,
|
component: theme,
|
||||||
icon: icon
|
icon: icon
|
||||||
});
|
} as DockShortcut);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dockShortcuts = shortcuts.sort((a, b) => {
|
this.dockShortcuts = shortcuts.sort((a, b) => {
|
||||||
@@ -327,46 +365,49 @@ class FooterCtrl extends PureCtrl {
|
|||||||
return -1;
|
return -1;
|
||||||
} else if (bType === 'circle' && aType === 'svg') {
|
} else if (bType === 'circle' && aType === 'svg') {
|
||||||
return 1;
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
initSvgForShortcut(shortcut) {
|
initSvgForShortcut(shortcut: DockShortcut) {
|
||||||
const id = 'dock-svg-' + shortcut.component.uuid;
|
const id = 'dock-svg-' + shortcut.component.uuid;
|
||||||
const element = document.getElementById(id);
|
const element = document.getElementById(id)!;
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const svg = shortcut.component.content.package_info.dock_icon.source;
|
const svg = shortcut.component.package_info.dock_icon.source;
|
||||||
const doc = parser.parseFromString(svg, 'image/svg+xml');
|
const doc = parser.parseFromString(svg, 'image/svg+xml');
|
||||||
element.appendChild(doc.documentElement);
|
element.appendChild(doc.documentElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectShortcut(shortcut) {
|
selectShortcut(shortcut: DockShortcut) {
|
||||||
this.application.componentManager.toggleComponent(shortcut.component);
|
this.application!.componentManager!.toggleComponent(shortcut.component);
|
||||||
}
|
}
|
||||||
|
|
||||||
onRoomDismiss(room) {
|
onRoomDismiss(room: SNComponent) {
|
||||||
room.showRoom = false;
|
this.roomShowState[room.uuid] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
closeAllRooms() {
|
closeAllRooms() {
|
||||||
for (const room of this.rooms) {
|
for (const room of this.rooms) {
|
||||||
room.showRoom = false;
|
this.roomShowState[room.uuid] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectRoom(room) {
|
async selectRoom(room: SNComponent) {
|
||||||
const run = () => {
|
const run = () => {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
room.showRoom = !room.showRoom;
|
this.roomShowState[room.uuid] = !this.roomShowState[room.uuid];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!room.showRoom) {
|
if (!this.roomShowState[room.uuid]) {
|
||||||
const requiresPrivilege = await this.application.privilegesService.actionRequiresPrivilege(
|
const requiresPrivilege = await this.application!.privilegesService!
|
||||||
ProtectedAction.ManageExtensions
|
.actionRequiresPrivilege(
|
||||||
);
|
ProtectedAction.ManageExtensions
|
||||||
|
);
|
||||||
if (requiresPrivilege) {
|
if (requiresPrivilege) {
|
||||||
this.application.presentPrivilegesModal(
|
this.application!.presentPrivilegesModal(
|
||||||
ProtectedAction.ManageExtensions,
|
ProtectedAction.ManageExtensions,
|
||||||
run
|
run
|
||||||
);
|
);
|
||||||
@@ -379,15 +420,16 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clickOutsideAccountMenu() {
|
clickOutsideAccountMenu() {
|
||||||
if (this.application && this.application.authenticationInProgress()) {
|
if (this.application && this.application!.authenticationInProgress()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.showAccountMenu = false;
|
this.showAccountMenu = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Footer {
|
export class Footer extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
super();
|
||||||
this.restrict = 'E';
|
this.restrict = 'E';
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.controller = FooterCtrl;
|
this.controller = FooterCtrl;
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import template from '%/lock-screen.pug';
|
|
||||||
import { AppStateEvent } from '@/services/state';
|
|
||||||
import { PureCtrl } from './abstract/pure_ctrl';
|
|
||||||
|
|
||||||
const ELEMENT_ID_PASSCODE_INPUT = 'passcode-input';
|
|
||||||
|
|
||||||
class LockScreenCtrl extends PureCtrl {
|
|
||||||
/* @ngInject */
|
|
||||||
constructor(
|
|
||||||
$timeout,
|
|
||||||
) {
|
|
||||||
super($timeout);
|
|
||||||
this.formData = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
$onInit() {
|
|
||||||
super.$onInit();
|
|
||||||
this.puppet.focusInput = () => {
|
|
||||||
this.passcodeInput.focus();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
get passcodeInput() {
|
|
||||||
return document.getElementById(
|
|
||||||
ELEMENT_ID_PASSCODE_INPUT
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
async onAppStateEvent(eventName, data) {
|
|
||||||
if (eventName === AppStateEvent.WindowDidFocus) {
|
|
||||||
const input = this.passcodeInput;
|
|
||||||
if (input) {
|
|
||||||
input.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async submitPasscodeForm() {
|
|
||||||
if (
|
|
||||||
!this.formData.passcode ||
|
|
||||||
this.formData.passcode.length === 0
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.passcodeInput.blur();
|
|
||||||
this.onValue()(this.formData.passcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
forgotPasscode() {
|
|
||||||
this.formData.showRecovery = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
beginDeleteData() {
|
|
||||||
this.application.alertService.confirm({
|
|
||||||
text: "Are you sure you want to clear all local data?",
|
|
||||||
destructive: true,
|
|
||||||
onConfirm: async () => {
|
|
||||||
await this.application.signOut();
|
|
||||||
await this.application.restart();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LockScreen {
|
|
||||||
constructor() {
|
|
||||||
this.restrict = 'E';
|
|
||||||
this.template = template;
|
|
||||||
this.controller = LockScreenCtrl;
|
|
||||||
this.controllerAs = 'ctrl';
|
|
||||||
this.bindToController = true;
|
|
||||||
this.scope = {
|
|
||||||
onValue: '&',
|
|
||||||
puppet: '='
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,16 @@
|
|||||||
|
import { ApplicationManager } from './../applicationManager';
|
||||||
|
import { WebDirective } from './../types';
|
||||||
import template from '%/root.pug';
|
import template from '%/root.pug';
|
||||||
|
import { WebApplication } from '@/application';
|
||||||
|
|
||||||
class RootCtrl {
|
class RootCtrl {
|
||||||
|
|
||||||
|
private $timeout: ng.ITimeoutService
|
||||||
|
private applicationManager: ApplicationManager
|
||||||
|
public applications: WebApplication[] = []
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor($timeout, applicationManager) {
|
constructor($timeout: ng.ITimeoutService, applicationManager: ApplicationManager) {
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.applicationManager = applicationManager;
|
this.applicationManager = applicationManager;
|
||||||
this.applicationManager.addApplicationChangeObserver(() => {
|
this.applicationManager.addApplicationChangeObserver(() => {
|
||||||
@@ -17,8 +25,9 @@ class RootCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Root {
|
export class Root extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
super();
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.controller = RootCtrl;
|
this.controller = RootCtrl;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { WebApplication } from './application';
|
import { WebApplication } from './application';
|
||||||
import { SNAlertService } from "../../../../snjs/dist/@types";
|
import { SNAlertService } from "../../../../snjs/dist/@types";
|
||||||
|
import { RawPayload } from '../../../../snjs/dist/@types/protocol/payloads/generator';
|
||||||
|
|
||||||
const DB_NAME = 'standardnotes';
|
const DB_NAME = 'standardnotes';
|
||||||
const STORE_NAME = 'items';
|
const STORE_NAME = 'items';
|
||||||
@@ -105,7 +106,7 @@ export class Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAllPayloads() {
|
public async getAllPayloads(): Promise<any[]> {
|
||||||
const db = (await this.openDatabase())!;
|
const db = (await this.openDatabase())!;
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const objectStore =
|
const objectStore =
|
||||||
@@ -126,11 +127,11 @@ export class Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async savePayload(payload: any) {
|
public async savePayload(payload: any): Promise<void> {
|
||||||
return this.savePayloads([payload]);
|
return this.savePayloads([payload]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async savePayloads(payloads: any[]) {
|
public async savePayloads(payloads: any[]): Promise<void> {
|
||||||
if (payloads.length === 0) {
|
if (payloads.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -157,8 +158,8 @@ export class Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private putItems(objectStore: IDBObjectStore, items: any[]) {
|
private async putItems(objectStore: IDBObjectStore, items: any[]): Promise<void> {
|
||||||
return Promise.all(items.map((item) => {
|
await Promise.all(items.map((item) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const request = objectStore.put(item);
|
const request = objectStore.put(item);
|
||||||
request.onerror = resolve;
|
request.onerror = resolve;
|
||||||
@@ -167,19 +168,21 @@ export class Database {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deletePayload(uuid: string) {
|
public async deletePayload(uuid: string): Promise<void> {
|
||||||
const db = (await this.openDatabase())!;
|
const db = (await this.openDatabase())!;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const request =
|
const request =
|
||||||
db.transaction(STORE_NAME, READ_WRITE)
|
db.transaction(STORE_NAME, READ_WRITE)
|
||||||
.objectStore(STORE_NAME)
|
.objectStore(STORE_NAME)
|
||||||
.delete(uuid);
|
.delete(uuid);
|
||||||
request.onsuccess = resolve;
|
request.onsuccess = () => {
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
request.onerror = reject;
|
request.onerror = reject;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async clearAllPayloads() {
|
public async clearAllPayloads(): Promise<void> {
|
||||||
const deleteRequest = window.indexedDB.deleteDatabase(DB_NAME);
|
const deleteRequest = window.indexedDB.deleteDatabase(DB_NAME);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
deleteRequest.onerror = () => {
|
deleteRequest.onerror = () => {
|
||||||
@@ -200,7 +203,7 @@ export class Database {
|
|||||||
this.alertService!.alert(message);
|
this.alertService!.alert(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private showGenericError(error: {code: number, name: string}) {
|
private showGenericError(error: { code: number, name: string }) {
|
||||||
const message =
|
const message =
|
||||||
`Unable to save changes locally due to an unknown system issue. ` +
|
`Unable to save changes locally due to an unknown system issue. ` +
|
||||||
`Issue Code: ${error.code} Issue Name: ${error.name}.`;
|
`Issue Code: ${error.code} Issue Name: ${error.name}.`;
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
export class StatusManager {
|
|
||||||
constructor() {
|
|
||||||
this.statuses = [];
|
|
||||||
this.observers = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
statusFromString(string) {
|
|
||||||
return {string: string};
|
|
||||||
}
|
|
||||||
|
|
||||||
replaceStatusWithString(status, string) {
|
|
||||||
this.removeStatus(status);
|
|
||||||
return this.addStatusFromString(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
addStatusFromString(string) {
|
|
||||||
return this.addStatus(this.statusFromString(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
addStatus(status) {
|
|
||||||
if(typeof status !== "object") {
|
|
||||||
console.error("Attempting to set non-object status", status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.statuses.push(status);
|
|
||||||
this.notifyObservers();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeStatus(status) {
|
|
||||||
_.pull(this.statuses, status);
|
|
||||||
this.notifyObservers();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
getStatusString() {
|
|
||||||
let result = "";
|
|
||||||
this.statuses.forEach((status, index) => {
|
|
||||||
if(index > 0) {
|
|
||||||
result += " ";
|
|
||||||
}
|
|
||||||
result += status.string;
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyObservers() {
|
|
||||||
for(const observer of this.observers) {
|
|
||||||
observer(this.getStatusString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addStatusObserver(callback) {
|
|
||||||
this.observers.push(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeStatusObserver(callback) {
|
|
||||||
_.pull(this.statuses, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
60
app/assets/javascripts/services/statusManager.ts
Normal file
60
app/assets/javascripts/services/statusManager.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { removeFromArray } from 'snjs';
|
||||||
|
import { FooterStatus } from './../types';
|
||||||
|
|
||||||
|
type StatusCallback = (string: string) => void
|
||||||
|
|
||||||
|
export class StatusManager {
|
||||||
|
|
||||||
|
private statuses: FooterStatus[] = []
|
||||||
|
private observers: StatusCallback[] = []
|
||||||
|
|
||||||
|
statusFromString(string: string) {
|
||||||
|
return {string: string};
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceStatusWithString(status: FooterStatus, string: string) {
|
||||||
|
this.removeStatus(status);
|
||||||
|
return this.addStatusFromString(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
addStatusFromString(string: string) {
|
||||||
|
return this.addStatus(this.statusFromString(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
addStatus(status: FooterStatus) {
|
||||||
|
this.statuses.push(status);
|
||||||
|
this.notifyObservers();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeStatus(status: FooterStatus) {
|
||||||
|
removeFromArray(this.statuses, status);
|
||||||
|
this.notifyObservers();
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStatusString() {
|
||||||
|
let result = '';
|
||||||
|
this.statuses.forEach((status, index) => {
|
||||||
|
if(index > 0) {
|
||||||
|
result += ' ';
|
||||||
|
}
|
||||||
|
result += status.string;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyObservers() {
|
||||||
|
for(const observer of this.observers) {
|
||||||
|
observer(this.getStatusString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addStatusObserver(callback: StatusCallback) {
|
||||||
|
this.observers.push(callback);
|
||||||
|
return () => {
|
||||||
|
removeFromArray(this.observers, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { SNComponent } from 'snjs';
|
||||||
export class WebDirective implements ng.IDirective {
|
export class WebDirective implements ng.IDirective {
|
||||||
controller?: string | ng.Injectable<ng.IControllerConstructor>;
|
controller?: string | ng.Injectable<ng.IControllerConstructor>;
|
||||||
controllerAs?: string;
|
controllerAs?: string;
|
||||||
@@ -18,6 +19,17 @@ export interface PasswordWizardScope extends Partial<ng.IScope> {
|
|||||||
application: any
|
application: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PermissionsModalScope extends Partial<ng.IScope> {
|
||||||
|
application: any
|
||||||
|
component: SNComponent
|
||||||
|
permissionsString: string
|
||||||
|
callback: (approved: boolean) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModalComponentScope extends Partial<ng.IScope> {
|
||||||
|
component: SNComponent
|
||||||
|
}
|
||||||
|
|
||||||
export type PanelPuppet = {
|
export type PanelPuppet = {
|
||||||
onReady?: () => void
|
onReady?: () => void
|
||||||
ready?: boolean
|
ready?: boolean
|
||||||
@@ -25,4 +37,8 @@ export type PanelPuppet = {
|
|||||||
setLeft?: (left: number) => void
|
setLeft?: (left: number) => void
|
||||||
isCollapsed?: () => boolean
|
isCollapsed?: () => boolean
|
||||||
flash?: () => void
|
flash?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FooterStatus = {
|
||||||
|
string: string
|
||||||
}
|
}
|
||||||
@@ -8,10 +8,10 @@
|
|||||||
)
|
)
|
||||||
.sk-app-bar-item-column
|
.sk-app-bar-item-column
|
||||||
.sk-circle.small(
|
.sk-circle.small(
|
||||||
ng-class="ctrl.error ? 'danger' : (ctrl.user ? 'info' : 'neutral')"
|
ng-class="ctrl.hasError ? 'danger' : (ctrl.user ? 'info' : 'neutral')"
|
||||||
)
|
)
|
||||||
.sk-app-bar-item-column
|
.sk-app-bar-item-column
|
||||||
.sk-label.title(ng-class='{red: ctrl.error}') Account
|
.sk-label.title(ng-class='{red: ctrl.hasError}') Account
|
||||||
account-menu(
|
account-menu(
|
||||||
close-function='ctrl.closeAccountMenu()',
|
close-function='ctrl.closeAccountMenu()',
|
||||||
ng-click='$event.stopPropagation()',
|
ng-click='$event.stopPropagation()',
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
.sk-label {{room.name}}
|
.sk-label {{room.name}}
|
||||||
component-modal(
|
component-modal(
|
||||||
component='room',
|
component='room',
|
||||||
ng-if='room.showRoom',
|
ng-if='ctrl.roomShowState[room.uuid]',
|
||||||
on-dismiss='ctrl.onRoomDismiss()',
|
on-dismiss='ctrl.onRoomDismiss()',
|
||||||
application='ctrl.application'
|
application='ctrl.application'
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user