Improve event handling + restarts

This commit is contained in:
Mo Bitar
2020-02-12 14:21:58 -06:00
parent 0fcfd98e5d
commit a364a9ec03
19 changed files with 1202 additions and 814 deletions

View File

@@ -1,4 +1,6 @@
import { ApplicationEvents } from 'snjs';
export class PureCtrl {
/* @ngInject */
constructor(
$scope,
$timeout,
@@ -14,13 +16,22 @@ export class PureCtrl {
this.application = application;
this.state = {};
this.props = {};
this.addAppStateObserver();
this.addAppEventObserver();
$scope.$on('$destroy', () => {
this.unsubApp();
this.unsubState();
});
}
$onInit() {
this.addAppStateObserver();
this.addAppEventObserver();
}
/** @private */
async resetState() {
this.state = {};
await this.setState({});
}
async setState(state) {
return new Promise((resolve) => {
@@ -45,12 +56,28 @@ export class PureCtrl {
}
addAppEventObserver() {
this.unsubApp = this.application.addEventObserver((eventName) => {
this.onApplicationEvent(eventName);
if (this.application.isStarted()) {
this.onAppStart();
}
if (!this.appState.isLocked()) {
this.onAppUnlock();
}
this.unsubApp = this.application.addEventObserver(async (eventName) => {
this.onAppEvent(eventName);
if (eventName === ApplicationEvents.Started) {
await this.resetState();
await this.onAppStart();
} else if (eventName === ApplicationEvents.Unlocked) {
await this.onAppUnlock();
} else if (eventName === ApplicationEvents.CompletedSync) {
this.onAppSync();
} else if (eventName === ApplicationEvents.KeyStatusChange) {
this.onAppKeyChange();
}
});
}
onApplicationEvent(eventName) {
onAppEvent(eventName) {
/** Optional override */
}
@@ -58,4 +85,19 @@ export class PureCtrl {
/** Optional override */
}
async onAppStart() {
/** Optional override */
}
async onAppUnlock() {
/** Optional override */
}
async onAppKeyChange() {
/** Optional override */
}
onAppSync() {
/** Optional override */
}
}

View File

@@ -81,18 +81,18 @@ class EditorCtrl extends PureCtrl {
onReady: () => this.reloadPreferences()
};
this.addSyncStatusObserver();
this.registerKeyboardShortcuts();
application.onUnlock(() => {
this.streamItems();
this.registerComponentHandler();
});
this.registerKeyboardShortcuts();
/** Used by .pug template */
this.prefKeyMonospace = PrefKeys.EditorMonospaceEnabled;
this.prefKeySpellcheck = PrefKeys.EditorSpellcheck;
this.prefKeyMarginResizers = PrefKeys.EditorResizersEnabled;
}
onAppUnlock() {
super.onAppUnlock();
this.streamItems();
this.registerComponentHandler();
}
/** @override */
onAppStateEvent(eventName, data) {
@@ -107,7 +107,7 @@ class EditorCtrl extends PureCtrl {
}
/** @override */
onApplicationEvent(eventName) {
onAppEvent(eventName) {
if (!this.state.note) {
return;
}

View File

@@ -46,23 +46,24 @@ class FooterCtrl extends PureCtrl {
this.arbitraryStatusMessage = string;
});
});
}
application.onUnlock(() => {
this.application.hasPasscode().then((value) => {
this.setState({
hasPasscode: value
});
onAppUnlock() {
super.onAppUnlock();
this.application.hasPasscode().then((value) => {
this.setState({
hasPasscode: value
});
this.godService.checkForSecurityUpdate().then((available) => {
this.securityUpdateAvailable = available;
});
this.user = this.application.getUser();
this.updateOfflineStatus();
this.findErrors();
this.streamItems();
this.registerComponentHandler();
});
this.godService.checkForSecurityUpdate().then((available) => {
this.securityUpdateAvailable = available;
});
this.user = this.application.getUser();
this.updateOfflineStatus();
this.findErrors();
this.streamItems();
this.registerComponentHandler();
}
addRootScopeListeners() {
@@ -109,7 +110,7 @@ class FooterCtrl extends PureCtrl {
}
/** @override */
onApplicationEvent(eventName) {
onAppEvent(eventName) {
if (eventName === ApplicationEvents.EnteredOutOfSync) {
this.outOfSync = true;
} else if (eventName === ApplicationEvents.ExitedOutOfSync) {

View File

@@ -17,6 +17,7 @@ class LockScreenCtrl extends PureCtrl {
}
$onInit() {
super.$onInit();
this.puppet.focusInput = () => {
this.passcodeInput.focus();
};

View File

@@ -76,10 +76,12 @@ class NotesCtrl extends PureCtrl {
angular.element(document).ready(() => {
this.reloadPreferences();
});
application.onUnlock(() => {
this.streamNotesAndTags();
this.reloadPreferences();
});
}
onAppUnlock() {
super.onAppUnlock();
this.streamNotesAndTags();
this.reloadPreferences();
}
/** @override */
@@ -97,7 +99,7 @@ class NotesCtrl extends PureCtrl {
}
/** @override */
onApplicationEvent(eventName) {
onAppEvent(eventName) {
if (eventName === ApplicationEvents.SignedIn) {
/** Delete dummy note if applicable */
if (this.state.selectedNote && this.state.selectedNote.dummy) {
@@ -430,10 +432,17 @@ class NotesCtrl extends PureCtrl {
});
}
if (note.errorDecrypting) {
flags.push({
text: "Missing Keys",
class: 'danger'
});
if(note.waitingForKeys) {
flags.push({
text: "Waiting For Keys",
class: 'info'
});
} else {
flags.push({
text: "Missing Keys",
class: 'danger'
});
}
}
if (note.deleted) {
flags.push({

View File

@@ -36,20 +36,27 @@ class RootCtrl extends PureCtrl {
this.statusManager = statusManager;
this.themeManager = themeManager;
this.platformString = getPlatformString();
this.state = {
ready: false,
appClass: ''
};
this.state = { appClass: '' };
this.loadApplication();
this.addDragDropHandlers();
application.onUnlock(() => {
this.handleAutoSignInFromParams();
});
this.lockScreenPuppet = {
focusInput: () => { }
};
}
onAppStart() {
super.onAppStart();
this.setState({ ready: false });
}
onAppUnlock() {
super.onAppUnlock();
this.setState({ ready: true, needsUnlock: false });
this.application.componentManager.setDesktopManager(this.desktopManager);
this.application.registerService(this.themeManager);
this.handleAutoSignInFromParams();
}
async watchLockscreenValue() {
return new Promise((resolve) => {
const onLockscreenValue = (value) => {
@@ -86,24 +93,12 @@ class RootCtrl extends PureCtrl {
}
});
await this.application.launch();
this.setState({ ready: true });
// this.addSyncStatusObserver();
// this.addSyncEventHandler();
}
onUpdateAvailable() {
this.$rootScope.$broadcast('new-update-available');
};
/** @override */
async onApplicationEvent(eventName) {
if (eventName === ApplicationEvents.ApplicationUnlocked) {
this.setState({ needsUnlock: false });
this.application.componentManager.setDesktopManager(this.desktopManager);
this.application.registerService(this.themeManager);
}
}
/** @override */
async onAppStateEvent(eventName, data) {
if (eventName === AppStateEvents.PanelResized) {
@@ -118,7 +113,7 @@ class RootCtrl extends PureCtrl {
if (this.tagsCollapsed) { appClass += " collapsed-tags"; }
this.setState({ appClass });
} else if (eventName === AppStateEvents.WindowDidFocus) {
if (!(await this.application.isPasscodeLocked())) {
if (!(await this.application.isLocked())) {
this.application.sync();
}
}

View File

@@ -23,28 +23,31 @@ class TagsPanelCtrl extends PureCtrl {
onReady: () => this.loadPreferences()
};
this.state = {
tags: [],
smartTags: [],
noteCounts: {}
noteCounts: {},
};
}
onAppStart() {
super.onAppStart();
this.registerComponentHandler();
}
$onInit() {
this.application.onStart(() => {
this.registerComponentHandler();
});
this.application.onUnlock(() => {
this.loadPreferences();
this.beginStreamingItems();
const smartTags = this.application.getSmartTags();
this.setState({
smartTags: smartTags,
});
this.selectTag(smartTags[0]);
onAppUnlock() {
super.onAppUnlock();
this.loadPreferences();
this.beginStreamingItems();
const smartTags = this.application.getSmartTags();
this.setState({
smartTags: smartTags,
});
this.selectTag(smartTags[0]);
}
this.application.onSync(() => {
this.reloadNoteCounts();
});
onAppSync() {
super.onAppSync();
this.reloadNoteCounts();
}
beginStreamingItems() {
@@ -58,10 +61,10 @@ class TagsPanelCtrl extends PureCtrl {
this.reloadNoteCounts();
if (this.state.selectedTag) {
/** If the selected tag has been deleted, revert to All view. */
const selectedTag = items.find((tag) => {
const matchingTag = items.find((tag) => {
return tag.uuid === this.state.selectedTag.uuid;
});
if (selectedTag && selectedTag.deleted) {
if (!matchingTag || matchingTag.deleted) {
this.selectTag(this.state.smartTags[0]);
}
}

View File

@@ -2,11 +2,9 @@ import { isDesktopApplication, isNullOrUndefined } from '@/utils';
import template from '%/directives/account-menu.pug';
import { ProtectedActions } from 'snjs';
import { PureCtrl } from '@Controllers';
import { AppStateEvents } from '@/state';
import {
STRING_ACCOUNT_MENU_UNCHECK_MERGE,
STRING_SIGN_OUT_CONFIRMATION,
STRING_ERROR_DECRYPTING_IMPORT,
STRING_E2E_ENABLED,
STRING_LOCAL_ENC_ENABLED,
STRING_ENC_NOT_ENABLED,
@@ -51,6 +49,7 @@ class AccountMenuCtrl extends PureCtrl {
this.state = {
appVersion: 'v' + (window.electronAppVersion || appVersion),
passcodeAutoLockOptions: this.lockManager.getAutoLockIntervalOptions(),
user: this.application.getUser(),
formData: {
mergeLocal: true,
ephemeral: false,
@@ -59,18 +58,22 @@ class AccountMenuCtrl extends PureCtrl {
},
mutable: {}
};
application.onUnlock(async () => {
this.setState(await this.refreshedCredentialState());
this.loadHost();
this.checkForSecurityUpdate();
this.reloadAutoLockInterval();
this.loadBackupsAvailability();
});
application.onCredentialChange(async () => {
this.setState(await this.refreshedCredentialState());
});
this.syncStatus = this.application.getSyncStatus();
}
async onAppKeyChange() {
super.onAppKeyChange();
this.setState(await this.refreshedCredentialState());
}
async onAppUnlock() {
super.onAppUnlock();
this.setState(await this.refreshedCredentialState());
this.loadHost();
this.checkForSecurityUpdate();
this.reloadAutoLockInterval();
this.loadBackupsAvailability();
}
async refreshedCredentialState() {
return {
@@ -81,6 +84,7 @@ class AccountMenuCtrl extends PureCtrl {
}
$onInit() {
super.$onInit();
this.initProps({
closeFunction: this.closeFunction
});
@@ -88,7 +92,6 @@ class AccountMenuCtrl extends PureCtrl {
close() {
this.$timeout(() => {
console.log(" : AccountMenuCtrl -> close -> timeout");
this.props.closeFunction()();
});
}

View File

@@ -15,6 +15,7 @@ class ActionsMenuCtrl extends PureCtrl {
}
$onInit() {
super.$onInit();
this.initProps({
item: this.item
});

View File

@@ -17,6 +17,7 @@ class EditorMenuCtrl extends PureCtrl {
}
$onInit() {
super.$onInit();
const editors = this.application.componentManager.componentsForArea('editor-editor')
.sort((a, b) => {
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;

View File

@@ -1,21 +1,24 @@
import template from '%/directives/privileges-management-modal.pug';
import { PrivilegeCredentials } from 'snjs';
import { PureCtrl } from '@Controllers';
class PrivilegesManagementModalCtrl {
class PrivilegesManagementModalCtrl extends PureCtrl {
/* @ngInject */
constructor(
$timeout,
$element,
application
) {
super(null, $timeout);
this.$element = $element;
this.$timeout = $timeout;
this.application = application;
application.onUnlock(() => {
this.hasPasscode = application.hasPasscode();
this.hasAccount = !application.noAccount();
this.reloadPrivileges();
});
}
onAppUnlock() {
super.onAppUnlock();
this.hasPasscode = this.application.hasPasscode();
this.hasAccount = !this.application.noAccount();
this.reloadPrivileges();
}
displayInfoForCredential(credential) {

View File

@@ -92,7 +92,7 @@ export class LockManager {
async documentVisibilityChanged(visible) {
if(visible) {
const locked = await this.application.isPasscodeLocked();
const locked = await this.application.isLocked();
if(
!locked &&
this.lockAfterDate &&

View File

@@ -1,25 +1,31 @@
import { isDesktopApplication, dictToArray } from '@/utils';
import { SFPredicate, ContentTypes, CreateMaxPayloadFromAnyObject } from 'snjs';
import {
ApplicationEvents,
SFPredicate,
ContentTypes,
CreateMaxPayloadFromAnyObject
} from 'snjs';
const STREAM_ITEMS_PERMISSION = 'stream-items';
/** A class for handling installation of system extensions */
export class NativeExtManager {
/* @ngInject */
constructor(application, appState) {
constructor(application) {
this.application = application;
this.extManagerId = 'org.standardnotes.extensions-manager';
this.batchManagerId = 'org.standardnotes.batch-manager';
application.onUnlock(() => {
this.unsub = application.addSingleEventObserver(ApplicationEvents.Unlocked, () => {
this.reload();
this.streamChanges();
});
}
isSystemExtension(extension) {
return this.nativeExtIds.includes(extension.uuid);
}
streamChanges() {
this.application.streamItems({
contentType: ContentTypes.Component,
@@ -28,7 +34,7 @@ export class NativeExtManager {
}
});
}
reload() {
this.nativeExtIds = [];
// this.resolveExtensionsManager();
@@ -53,12 +59,12 @@ export class NativeExtManager {
{
name: STREAM_ITEMS_PERMISSION,
content_types: [
ContentTypes.Component,
ContentTypes.Theme,
ContentTypes.Component,
ContentTypes.Theme,
ContentTypes.ServerExtension,
ContentTypes.ActionsExtension,
ContentTypes.Mfa,
ContentTypes.Editor,
ContentTypes.ActionsExtension,
ContentTypes.Mfa,
ContentTypes.Editor,
ContentTypes.ExtensionRepo
]
}

View File

@@ -1,4 +1,4 @@
import { SFPredicate, ContentTypes, CreateMaxPayloadFromAnyObject } from 'snjs';
import { ApplicationEvents, SFPredicate, ContentTypes, CreateMaxPayloadFromAnyObject } from 'snjs';
export const PrefKeys = {
TagsPanelWidth: 'tagsPanelWidth',
@@ -24,8 +24,8 @@ export class PreferencesManager {
application
) {
this.application = application;
this.appState = appState;
application.onUnlock(() => {
this.appState = appState;
this.unsub = application.addSingleEventObserver(ApplicationEvents.Unlocked, () => {
this.streamPreferences();
this.loadSingleton();
});

View File

@@ -1,5 +1,5 @@
import _ from 'lodash';
import { ContentTypes, StorageValueModes, EncryptionIntents, PureService } from 'snjs';
import { ApplicationEvents, ContentTypes, StorageValueModes, EncryptionIntents, PureService } from 'snjs';
import { AppStateEvents } from '@/state';
const CACHED_THEMES_KEY = 'cachedThemes';
@@ -16,12 +16,17 @@ export class ThemeManager extends PureService {
this.appState = appState;
this.desktopManager = desktopManager;
this.activeThemes = [];
this.registerObservers();
application.onStart(() => {
if (!desktopManager.isDesktop) {
this.activateCachedThemes();
if (this.application.isStarted()) {
this.onAppStart();
}
this.unsub = application.addEventObserver((event) => {
if (event === ApplicationEvents.Started) {
this.onAppStart();
} else if(event === ApplicationEvents.SignedOut) {
this.deactivateAllThemes();
}
});
this.unsubState = appState.addObserver((eventName, data) => {
if (eventName === AppStateEvents.DesktopExtsReady) {
this.activateCachedThemes();
@@ -29,6 +34,13 @@ export class ThemeManager extends PureService {
});
}
onAppStart() {
this.registerObservers();
if (!this.desktopManager.isDesktop) {
this.activateCachedThemes();
}
}
/** @override */
async deinit() {
super.deinit();
@@ -72,8 +84,8 @@ export class ThemeManager extends PureService {
}
deactivateAllThemes() {
var activeThemes = this.application.componentManager.getActiveThemes();
for (var theme of activeThemes) {
const activeThemes = this.application.componentManager.getActiveThemes();
for (const theme of activeThemes) {
if (theme) {
this.application.componentManager.deactivateComponent(theme);
}
@@ -142,7 +154,7 @@ export class ThemeManager extends PureService {
);
if (cachedThemes) {
const themes = [];
for(const cachedTheme of cachedThemes) {
for (const cachedTheme of cachedThemes) {
const theme = await this.application.createItem({
contentType: ContentTypes.Theme,
content: cachedTheme.content

View File

@@ -1,6 +1,6 @@
import { isDesktopApplication } from '@/utils';
import pull from 'lodash/pull';
import { ProtectedActions } from 'snjs';
import { ProtectedActions, ApplicationEvents } from 'snjs';
export const AppStateEvents = {
TagChanged: 1,
@@ -33,7 +33,23 @@ export class AppState {
this.application = application;
this.godService = godService;
this.observers = [];
this.locked = true;
this.registerVisibilityObservers();
this.addAppEventObserver();
}
addAppEventObserver() {
this.unsubApp = this.application.addEventObserver(async (eventName) => {
if (eventName === ApplicationEvents.Started) {
this.locked = true;
} else if (eventName === ApplicationEvents.Unlocked) {
this.locked = false;
}
});
}
isLocked() {
return this.locked;
}
registerVisibilityObservers() {
@@ -87,9 +103,9 @@ export class AppState {
this.selectedTag = tag;
this.notifyEvent(
AppStateEvents.TagChanged,
{
{
tag: tag,
previousTag: previousTag
previousTag: previousTag
}
);
}

View File

@@ -17,4 +17,4 @@
footer(
ng-if='!self.state.needsUnlock'
)
)

1677
dist/javascripts/app.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long