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