This commit is contained in:
Mo Bitar
2020-02-09 12:07:18 -06:00
parent 046f6ca5b9
commit 1a87df0db8
18 changed files with 1151 additions and 1130 deletions

View File

@@ -1,13 +1,25 @@
export class PureCtrl {
constructor(
$timeout
$scope,
$timeout,
application,
appState
) {
if(!$timeout) {
if (!$scope || !$timeout || !application || !appState) {
throw 'Invalid PureCtrl construction.';
}
this.$scope = $scope;
this.$timeout = $timeout;
this.appState = appState;
this.application = application;
this.state = {};
this.props = {};
this.addAppStateObserver();
this.addAppEventObserver();
$scope.$on('$destroy', () => {
this.unsubApp();
this.unsubState();
});
}
async setState(state) {
@@ -25,4 +37,25 @@ export class PureCtrl {
}
this.props = Object.freeze(Object.assign({}, this.props, props));
}
addAppStateObserver() {
this.unsubState = this.appState.addObserver((eventName, data) => {
this.onAppStateEvent(eventName, data);
});
}
addAppEventObserver() {
this.unsubApp = this.application.addEventObserver((eventName) => {
this.onApplicationEvent(eventName);
});
}
onApplicationEvent(eventName) {
/** Optional override */
}
onAppStateEvent(eventName, data) {
/** Optional override */
}
}

View File

@@ -49,18 +49,17 @@ const Fonts = {
class EditorCtrl extends PureCtrl {
/* @ngInject */
constructor(
$scope,
$timeout,
$rootScope,
appState,
application,
appState,
desktopManager,
keyboardManager,
preferencesManager,
) {
super($timeout);
super($scope, $timeout, application, appState);
this.$rootScope = $rootScope;
this.application = application;
this.appState = appState;
this.desktopManager = desktopManager;
this.keyboardManager = keyboardManager;
this.preferencesManager = preferencesManager;
@@ -77,13 +76,10 @@ class EditorCtrl extends PureCtrl {
this.leftResizeControl = {};
this.rightResizeControl = {};
this.addAppStateObserver();
this.addAppEventObserver();
this.addSyncStatusObserver();
this.registerKeyboardShortcuts();
application.onReady(() => {
application.onUnlock(() => {
this.streamItems();
this.registerComponentHandler();
});
@@ -94,8 +90,8 @@ class EditorCtrl extends PureCtrl {
this.prefKeyMarginResizers = PrefKeys.EditorResizersEnabled;
}
addAppStateObserver() {
this.appState.addObserver((eventName, data) => {
/** @override */
onAppStateEvent(eventName, data) {
if (eventName === AppStateEvents.NoteChanged) {
this.handleNoteSelectionChange(
this.appState.getSelectedNote(),
@@ -104,7 +100,40 @@ class EditorCtrl extends PureCtrl {
} else if (eventName === AppStateEvents.PreferencesChanged) {
this.loadPreferences();
}
}
/** @override */
onApplicationEvent(eventName) {
if (!this.state.note) {
return;
}
if (eventName === ApplicationEvents.HighLatencySync) {
this.setState({
syncTakingTooLong: true
});
} else if (eventName === ApplicationEvents.CompletedSync) {
this.setState({
syncTakingTooLong: false
});
if (this.state.note.dirty) {
/** if we're still dirty, don't change status, a sync is likely upcoming. */
} else {
const saved = this.state.note.updated_at > this.state.note.lastSyncBegan;
const isInErrorState = this.state.saveError;
if (isInErrorState || saved) {
this.showAllChangesSavedStatus();
}
}
} else if (eventName === ApplicationEvents.FailedSync) {
/**
* Only show error status in editor if the note is dirty.
* Otherwise, it means the originating sync came from somewhere else
* and we don't want to display an error here.
*/
if (this.state.note.dirty) {
this.showErrorStatus();
}
}
}
streamItems() {
@@ -176,42 +205,6 @@ class EditorCtrl extends PureCtrl {
});
}
addAppEventObserver() {
this.application.addEventObserver((eventName) => {
if (!this.state.note) {
return;
}
if (eventName === ApplicationEvents.HighLatencySync) {
this.setState({
syncTakingTooLong: true
});
} else if (eventName === ApplicationEvents.CompletedSync) {
this.setState({
syncTakingTooLong: false
});
if (this.state.note.dirty) {
/** if we're still dirty, don't change status, a sync is likely upcoming. */
} else {
const saved = this.state.note.updated_at > this.state.note.lastSyncBegan;
const isInErrorState = this.state.saveError;
if (isInErrorState || saved) {
this.showAllChangesSavedStatus();
}
}
} else if (eventName === ApplicationEvents.FailedSync) {
/**
* Only show error status in editor if the note is dirty.
* Otherwise, it means the originating sync came from somewhere else
* and we don't want to display an error here.
*/
if (this.state.note.dirty) {
this.showErrorStatus();
}
}
});
}
async handleNoteSelectionChange(note, previousNote) {
this.setState({
note: this.appState.getSelectedNote(),

View File

@@ -11,23 +11,23 @@ import {
STRING_GENERIC_SYNC_ERROR,
STRING_NEW_UPDATE_READY
} from '@/strings';
import { PureCtrl } from '@Controllers';
class FooterCtrl {
class FooterCtrl extends PureCtrl {
/* @ngInject */
constructor(
$scope,
$rootScope,
$timeout,
appState,
application,
appState,
nativeExtManager,
statusManager,
godService
) {
super($scope, $timeout, application, appState);
this.$rootScope = $rootScope;
this.$timeout = $timeout;
this.application = application;
this.appState = appState;
this.nativeExtManager = nativeExtManager;
this.statusManager = statusManager;
this.godService = godService;
@@ -36,7 +36,6 @@ class FooterCtrl {
this.themesWithIcons = [];
this.showSyncResolution = false;
this.addAppStateObserver();
this.addRootScopeListeners();
this.statusManager.addStatusObserver((string) => {
@@ -45,7 +44,7 @@ class FooterCtrl {
});
});
application.onReady(() => {
application.onUnlock(() => {
this.application.hasPasscode().then((value) => {
this.hasPasscode = value;
});
@@ -76,8 +75,8 @@ class FooterCtrl {
});
}
addAppStateObserver() {
this.appState.addObserver((eventName, data) => {
/** @override */
onAppStateEvent(eventName, data) {
if (eventName === AppStateEvents.EditorFocused) {
if (data.eventSource === EventSources.UserInteraction) {
this.closeAllRooms();
@@ -103,11 +102,10 @@ class FooterCtrl {
this.backupStatus = this.statusManager.removeStatus(this.backupStatus);
}, 2000);
}
});
}
addAppEventObserver() {
this.application.addEventObserver((eventName) => {
/** @override */
onApplicationEvent(eventName) {
if (eventName === ApplicationEvents.LoadedLocalData) {
if (this.offline && this.application.getNoteCount() === 0) {
this.showAccountMenu = true;
@@ -124,7 +122,6 @@ class FooterCtrl {
this.findErrors();
this.updateOfflineStatus();
}
});
}
streamItems() {

View File

@@ -1,21 +1,19 @@
import template from '%/lock-screen.pug';
import { AppStateEvents } from '@/state';
import { PureCtrl } from './abstract/pure_ctrl';
const ELEMENT_ID_PASSCODE_INPUT = 'passcode-input';
class LockScreenCtrl {
class LockScreenCtrl extends PureCtrl {
/* @ngInject */
constructor(
$scope,
$timeout,
application,
appState
) {
this.$scope = $scope;
this.application = application;
this.appState = appState;
super($scope, $timeout, application, appState);
this.formData = {};
this.addVisibilityObserver();
this.addDestroyHandler();
}
$onInit() {
@@ -30,21 +28,14 @@ class LockScreenCtrl {
);
}
addDestroyHandler() {
this.$scope.$on('$destroy', () => {
this.unregisterObserver();
});
}
addVisibilityObserver() {
this.unregisterObserver = this.appState.addObserver((eventName, data) => {
/** @override */
async onAppStateEvent(eventName, data) {
if (eventName === AppStateEvents.WindowDidFocus) {
const input = this.passcodeInput;
if (input) {
input.focus();
}
}
});
}
async submitPasscodeForm($event) {

View File

@@ -32,6 +32,7 @@ class NotesCtrl extends PureCtrl {
/* @ngInject */
constructor(
$scope,
$timeout,
$rootScope,
application,
@@ -40,7 +41,7 @@ class NotesCtrl extends PureCtrl {
keyboardManager,
preferencesManager,
) {
super($timeout);
super($scope, $timeout, application, appState);
this.$rootScope = $rootScope;
this.application = application;
this.appState = appState;
@@ -68,22 +69,19 @@ class NotesCtrl extends PureCtrl {
keepCurrentIfLarger: true
});
};
this.addAppStateObserver();
this.addAppEventObserver();
this.resetPagination();
this.registerKeyboardShortcuts();
angular.element(document).ready(() => {
this.reloadPreferences();
});
application.onReady(() => {
application.onUnlock(() => {
this.streamNotesAndTags();
this.reloadPreferences();
});
}
addAppStateObserver() {
this.appState.addObserver((eventName, data) => {
/** @override */
onAppStateEvent(eventName, data) {
if (eventName === AppStateEvents.TagChanged) {
this.handleTagChange(this.appState.getSelectedTag(), data.previousTag);
} else if (eventName === AppStateEvents.NoteChanged) {
@@ -94,11 +92,10 @@ class NotesCtrl extends PureCtrl {
} else if (eventName === AppStateEvents.EditorFocused) {
this.setShowMenuFalse();
}
});
}
addAppEventObserver() {
this.application.addEventObserver((eventName) => {
/** @override */
onApplicationEvent(eventName) {
if (eventName === ApplicationEvents.SignedIn) {
/** Delete dummy note if applicable */
if (this.state.selectedNote && this.state.selectedNote.dummy) {
@@ -119,7 +116,6 @@ class NotesCtrl extends PureCtrl {
this.createNewNote();
}
}
});
}
streamNotesAndTags() {
@@ -157,11 +153,9 @@ class NotesCtrl extends PureCtrl {
}
await this.selectNote(null);
}
await this.setState({
tag: tag
});
this.resetScrollPosition();
this.setShowMenuFalse();
this.setNoteFilterText('');
@@ -348,7 +342,7 @@ class NotesCtrl extends PureCtrl {
resetPagination({ keepCurrentIfLarger } = {}) {
const clientHeight = document.documentElement.clientHeight;
this.pageSize = clientHeight / MIN_NOTE_CELL_HEIGHT;
this.pageSize = Math.ceil(clientHeight / MIN_NOTE_CELL_HEIGHT);
if (this.pageSize === 0) {
this.pageSize = DEFAULT_LIST_NUM_NOTES;
}

View File

@@ -17,39 +17,34 @@ class RootCtrl extends PureCtrl {
/* @ngInject */
constructor(
$location,
$scope,
$rootScope,
$timeout,
application,
appState,
desktopManager,
lockManager,
preferencesManager,
themeManager /** Unused below, required to load globally */,
preferencesManager /** Unused below, required to load globally */,
themeManager,
statusManager,
) {
super($timeout);
super($scope, $timeout, application, appState);
this.$location = $location;
this.$rootScope = $rootScope;
this.$timeout = $timeout;
this.application = application;
this.appState = appState;
this.desktopManager = desktopManager;
this.lockManager = lockManager;
this.preferencesManager = preferencesManager;
this.statusManager = statusManager;
this.themeManager = themeManager;
this.platformString = getPlatformString();
this.state = {
needsUnlock: false,
needsUnlock: true,
appClass: ''
};
this.loadApplication();
this.addAppStateObserver();
this.addDragDropHandlers();
application.onReady(() => {
application.onUnlock(() => {
this.handleAutoSignInFromParams();
});
this.lockScreenPuppet = {
focusInput: () => { }
};
@@ -87,16 +82,13 @@ class RootCtrl extends PureCtrl {
});
}
}
},
onReady: async () => {
await this.appState.setApplicationReady();
}
}
});
await this.application.launch();
this.setState({ needsUnlock: false });
this.application.componentManager.setDesktopManager(this.desktopManager);
this.preferencesManager.initialize();
this.application.registerService(this.themeManager);
// this.addSyncStatusObserver();
// this.addSyncEventHandler();
}
@@ -105,8 +97,8 @@ class RootCtrl extends PureCtrl {
this.$rootScope.$broadcast('new-update-available');
};
addAppStateObserver() {
this.appState.addObserver(async (eventName, data) => {
/** @override */
async onAppStateEvent(eventName, data) {
if (eventName === AppStateEvents.PanelResized) {
if (data.panel === PANEL_NAME_NOTES) {
this.notesCollapsed = data.collapsed;
@@ -123,7 +115,6 @@ class RootCtrl extends PureCtrl {
this.application.sync();
}
}
});
}
// addSyncStatusObserver() {

View File

@@ -9,26 +9,24 @@ import { PureCtrl } from '@Controllers';
class TagsPanelCtrl extends PureCtrl {
/* @ngInject */
constructor(
$scope,
$rootScope,
$timeout,
application,
appState,
preferencesManager
) {
super($timeout);
super($scope, $timeout, application, appState);
this.$rootScope = $rootScope;
this.application = application;
this.appState = appState;
this.preferencesManager = preferencesManager;
this.panelController = {};
this.addAppStateObserver();
this.loadPreferences();
this.registerComponentHandler();
this.state = {
smartTags: [],
noteCounts: {}
};
application.onReady(() => {
application.onUnlock(() => {
this.beginStreamingItems();
const smartTags = this.application.getSmartTags();
this.setState({
@@ -64,8 +62,8 @@ class TagsPanelCtrl extends PureCtrl {
});
}
addAppStateObserver() {
this.appState.addObserver((eventName, data) => {
/** @override */
onAppStateEvent(eventName, data) {
if (eventName === AppStateEvents.PreferencesChanged) {
this.loadPreferences();
} else if (eventName === AppStateEvents.TagChanged) {
@@ -73,7 +71,6 @@ class TagsPanelCtrl extends PureCtrl {
selectedTag: this.appState.getSelectedTag()
});
}
});
}
reloadNoteCounts() {

View File

@@ -40,10 +40,8 @@ class AccountMenuCtrl extends PureCtrl {
godService,
lockManager,
) {
super($timeout);
this.$scope = $scope;
super($scope, $timeout, application, appState);
this.$rootScope = $rootScope;
this.$timeout = $timeout;
this.appState = appState;
this.application = application;
this.archiveManager = archiveManager;
@@ -59,7 +57,7 @@ class AccountMenuCtrl extends PureCtrl {
},
mutable: {}
};
application.onReady(async () => {
application.onUnlock(async () => {
this.setState(await this.refreshedCredentialState());
this.loadHost();
this.checkForSecurityUpdate();

View File

@@ -4,13 +4,13 @@ import { PureCtrl } from '@Controllers';
class ActionsMenuCtrl extends PureCtrl {
/* @ngInject */
constructor(
$scope,
$timeout,
application,
appState,
godService
) {
super($timeout);
this.$timeout = $timeout;
this.application = application;
super($scope, $timeout, application, appState);
this.godService = godService;
}

View File

@@ -5,11 +5,12 @@ import { PureCtrl } from '@Controllers';
class EditorMenuCtrl extends PureCtrl {
/* @ngInject */
constructor(
$scope,
$timeout,
application
application,
appState
) {
super($timeout);
this.application = application;
super($scope, $timeout, application, appState);
this.state = {
isDesktop: isDesktopApplication()
};

View File

@@ -11,7 +11,7 @@ class PrivilegesManagementModalCtrl {
this.$element = $element;
this.$timeout = $timeout;
this.application = application;
application.onReady(() => {
application.onUnlock(() => {
this.hasPasscode = application.hasPasscode();
this.hasAccount = !application.noAccount();
this.reloadPrivileges();

View File

@@ -15,8 +15,9 @@ export class NativeExtManager {
this.resolveExtensionsManager();
this.resolveBatchManager();
application.onReady(() => {
this.initialize();
application.onUnlock(() => {
this.resolveExtensionsManager();
this.resolveBatchManager();
});
}
@@ -24,11 +25,6 @@ export class NativeExtManager {
return this.systemExtensions.includes(extension.uuid);
}
async initialize() {
this.resolveExtensionsManager();
this.resolveBatchManager();
}
extensionsManagerTemplatePayload() {
const url = window._extensions_manager_location;
if (!url) {

View File

@@ -1,5 +1,4 @@
import { SFPredicate, CreateMaxPayloadFromAnyObject } from 'snjs';
import { AppStateEvents } from '../state';
export const PrefKeys = {
TagsPanelWidth: 'tagsPanelWidth',
@@ -26,14 +25,10 @@ export class PreferencesManager {
) {
this.application = application;
this.appState = appState;
application.onReady(() => {
this.initialize();
});
}
async initialize() {
application.onUnlock(() => {
this.streamPreferences();
await this.loadSingleton();
this.loadSingleton();
});
}
streamPreferences() {

View File

@@ -1,33 +1,40 @@
import _ from 'lodash';
import { ContentTypes, StorageValueModes, EncryptionIntents } from 'snjs';
import { ContentTypes, StorageValueModes, EncryptionIntents, PureService } from 'snjs';
import { AppStateEvents } from '@/state';
const CACHED_THEMES_KEY = 'cachedThemes';
export class ThemeManager {
export class ThemeManager extends PureService {
/* @ngInject */
constructor(
application,
appState,
desktopManager,
) {
super();
this.application = application;
this.appState = appState;
this.desktopManager = desktopManager;
this.activeThemes = [];
this.registerObservers();
application.onReady(() => {
application.onStart(() => {
if (!desktopManager.isDesktop) {
this.activateCachedThemes();
}
});
appState.addObserver((eventName, data) => {
this.unsubState = appState.addObserver((eventName, data) => {
if (eventName === AppStateEvents.DesktopExtsReady) {
this.activateCachedThemes();
}
});
}
/** @override */
async deinit() {
super.deinit();
this.unsubState();
}
async activateCachedThemes() {
const cachedThemes = await this.getCachedThemes();
const writeToCache = false;

View File

@@ -13,8 +13,6 @@ export const AppStateEvents = {
DesktopExtsReady: 8,
WindowDidFocus: 9,
WindowDidBlur: 10,
/** Register observers and streamers on this event */
ApplicationReady: 11
};
export const EventSources = {
@@ -80,11 +78,6 @@ export class AppState {
});
}
async setApplicationReady() {
this.applicationReady = true;
await this.notifyEvent(AppStateEvents.ApplicationReady);
}
setSelectedTag(tag) {
if (this.selectedTag === tag) {
return;
@@ -93,7 +86,10 @@ export class AppState {
this.selectedTag = tag;
this.notifyEvent(
AppStateEvents.TagChanged,
{ previousTag: previousTag }
{
tag: tag,
previousTag: previousTag
}
);
}

View File

@@ -109,9 +109,9 @@
threshold='200'
)
.note(
ng-class="{'selected' : self.state.selectedNote == note}",
ng-click='self.selectNote(note, true)',
ng-repeat='note in self.state.renderedNotes track by note.uuid'
ng-class="{'selected' : self.state.selectedNote == note}"
ng-click='self.selectNote(note, true)'
)
.note-flags(ng-show='note.flags.length > 0')
.flag(ng-class='flag.class', ng-repeat='flag in note.flags')

1606
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