ApplicationManager and better memory management
This commit is contained in:
@@ -4,20 +4,16 @@ import angular from 'angular';
|
|||||||
import { configRoutes } from './routes';
|
import { configRoutes } from './routes';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Application
|
ApplicationManager
|
||||||
} from './application';
|
} from './applicationManager';
|
||||||
|
|
||||||
import {
|
|
||||||
AppState
|
|
||||||
} from './state';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Root,
|
Root,
|
||||||
|
ApplicationView,
|
||||||
TagsPanel,
|
TagsPanel,
|
||||||
NotesPanel,
|
NotesPanel,
|
||||||
EditorPanel,
|
EditorPanel,
|
||||||
Footer,
|
Footer
|
||||||
LockScreen
|
|
||||||
} from './controllers';
|
} from './controllers';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -54,18 +50,6 @@ import {
|
|||||||
|
|
||||||
import { trusted } from './filters';
|
import { trusted } from './filters';
|
||||||
|
|
||||||
import {
|
|
||||||
ArchiveManager,
|
|
||||||
DesktopManager,
|
|
||||||
KeyboardManager,
|
|
||||||
GodService,
|
|
||||||
LockManager,
|
|
||||||
NativeExtManager,
|
|
||||||
PreferencesManager,
|
|
||||||
StatusManager,
|
|
||||||
ThemeManager,
|
|
||||||
} from './services';
|
|
||||||
|
|
||||||
angular.module('app', ['ngSanitize']);
|
angular.module('app', ['ngSanitize']);
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
@@ -78,11 +62,12 @@ angular
|
|||||||
angular
|
angular
|
||||||
.module('app')
|
.module('app')
|
||||||
.directive('root', () => new Root())
|
.directive('root', () => new Root())
|
||||||
|
.directive('applicationView', () => new ApplicationView())
|
||||||
.directive('tagsPanel', () => new TagsPanel())
|
.directive('tagsPanel', () => new TagsPanel())
|
||||||
.directive('notesPanel', () => new NotesPanel())
|
.directive('notesPanel', () => new NotesPanel())
|
||||||
.directive('editorPanel', () => new EditorPanel())
|
.directive('editorPanel', () => new EditorPanel())
|
||||||
.directive('footer', () => new Footer())
|
.directive('footer', () => new Footer())
|
||||||
.directive('lockScreen', () => new LockScreen());
|
// .directive('lockScreen', () => new LockScreen());
|
||||||
|
|
||||||
// Directives - Functional
|
// Directives - Functional
|
||||||
angular
|
angular
|
||||||
@@ -93,9 +78,6 @@ angular
|
|||||||
.directive('elemReady', elemReady)
|
.directive('elemReady', elemReady)
|
||||||
.directive('fileChange', fileChange)
|
.directive('fileChange', fileChange)
|
||||||
.directive('infiniteScroll', [
|
.directive('infiniteScroll', [
|
||||||
'$rootScope',
|
|
||||||
'$window',
|
|
||||||
'$timeout',
|
|
||||||
infiniteScroll
|
infiniteScroll
|
||||||
])
|
])
|
||||||
.directive('lowercase', lowercase)
|
.directive('lowercase', lowercase)
|
||||||
@@ -134,16 +116,4 @@ angular
|
|||||||
.filter('trusted', ['$sce', trusted]);
|
.filter('trusted', ['$sce', trusted]);
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
angular
|
angular.module('app').service('applicationManager', ApplicationManager);
|
||||||
.module('app')
|
|
||||||
.service('appState', AppState)
|
|
||||||
.service('application', Application)
|
|
||||||
.service('archiveManager', ArchiveManager)
|
|
||||||
.service('desktopManager', DesktopManager)
|
|
||||||
.service('godService', GodService)
|
|
||||||
.service('keyboardManager', KeyboardManager)
|
|
||||||
.service('lockManager', LockManager)
|
|
||||||
.service('nativeExtManager', NativeExtManager)
|
|
||||||
.service('preferencesManager', PreferencesManager)
|
|
||||||
.service('statusManager', StatusManager)
|
|
||||||
.service('themeManager', ThemeManager);
|
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ import {
|
|||||||
Environments,
|
Environments,
|
||||||
platformFromString
|
platformFromString
|
||||||
} from 'snjs';
|
} from 'snjs';
|
||||||
|
import angular from 'angular';
|
||||||
import { getPlatformString } from '@/utils';
|
import { getPlatformString } from '@/utils';
|
||||||
import { AlertService } from '@/services/alertService';
|
import { AlertService } from '@/services/alertService';
|
||||||
import { WebDeviceInterface } from '@/web_device_interface';
|
import { WebDeviceInterface } from '@/web_device_interface';
|
||||||
|
|
||||||
export class Application extends SNApplication {
|
export class WebApplication extends SNApplication {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor($timeout) {
|
constructor($compile, $timeout, scope, onDeinit) {
|
||||||
const deviceInterface = new WebDeviceInterface({ timeout: $timeout });
|
const deviceInterface = new WebDeviceInterface({ timeout: $timeout });
|
||||||
super({
|
super({
|
||||||
environment: Environments.Web,
|
environment: Environments.Web,
|
||||||
@@ -25,6 +26,189 @@ export class Application extends SNApplication {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
this.$compile = $compile;
|
||||||
|
this.scope = scope;
|
||||||
|
this.onDeinit = onDeinit;
|
||||||
deviceInterface.setApplication(this);
|
deviceInterface.setApplication(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
deinit() {
|
||||||
|
for (const key of Object.keys(this.webServices)) {
|
||||||
|
const service = this.webServices[key];
|
||||||
|
if(service.deinit) {
|
||||||
|
service.deinit();
|
||||||
|
}
|
||||||
|
service.application = null;
|
||||||
|
delete this.webServices[key];
|
||||||
|
}
|
||||||
|
this.webServices = {};
|
||||||
|
this.onDeinit(this);
|
||||||
|
this.onDeinit = null;
|
||||||
|
this.$compile = null;
|
||||||
|
this.$timeout = null;
|
||||||
|
this.scope.application = null;
|
||||||
|
this.scope.$destroy();
|
||||||
|
this.scope = null;
|
||||||
|
super.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @access public
|
||||||
|
* @param {object} services
|
||||||
|
*/
|
||||||
|
setWebServices(services) {
|
||||||
|
this.webServices = services;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getAppState() {
|
||||||
|
return this.webServices.appState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getDesktopService() {
|
||||||
|
return this.webServices.desktopService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getLockService() {
|
||||||
|
return this.webServices.lockService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getArchiveService() {
|
||||||
|
return this.webServices.archiveService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getNativeExtService() {
|
||||||
|
return this.webServices.nativeExtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getStatusService() {
|
||||||
|
return this.webServices.statusService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getThemeService() {
|
||||||
|
return this.webServices.themeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getPrefsService() {
|
||||||
|
return this.webServices.prefsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getKeyboardService() {
|
||||||
|
return this.webServices.keyboardService;
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkForSecurityUpdate() {
|
||||||
|
return this.protocolUpgradeAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
presentPasswordWizard(type) {
|
||||||
|
const scope = this.scope.$new(true);
|
||||||
|
scope.type = type;
|
||||||
|
scope.application = this;
|
||||||
|
const el = this.$compile("<password-wizard application='application' type='type'></password-wizard>")(scope);
|
||||||
|
angular.element(document.body).append(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
promptForChallenge(challenge, orchestrator) {
|
||||||
|
const scope = this.scope.$new(true);
|
||||||
|
scope.challenge = challenge;
|
||||||
|
scope.orchestrator = orchestrator;
|
||||||
|
scope.application = this;
|
||||||
|
const el = this.$compile(
|
||||||
|
"<challenge-modal " +
|
||||||
|
"class='sk-modal' application='application' challenge='challenge' orchestrator='orchestrator'>" +
|
||||||
|
"</challenge-modal>"
|
||||||
|
)(scope);
|
||||||
|
angular.element(document.body).append(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
async performProtocolUpgrade() {
|
||||||
|
const errors = await this.upgradeProtocolVersion();
|
||||||
|
if (errors.length === 0) {
|
||||||
|
this.alertService.alert({
|
||||||
|
text: "Success! Your encryption version has been upgraded." +
|
||||||
|
" You'll be asked to enter your credentials again on other devices you're signed into."
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.alertService.alert({
|
||||||
|
text: "Unable to upgrade encryption version. Please try again."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async presentPrivilegesModal(action, onSuccess, onCancel) {
|
||||||
|
if (this.authenticationInProgress()) {
|
||||||
|
onCancel && onCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const customSuccess = async () => {
|
||||||
|
onSuccess && await onSuccess();
|
||||||
|
this.currentAuthenticationElement = null;
|
||||||
|
};
|
||||||
|
const customCancel = async () => {
|
||||||
|
onCancel && await onCancel();
|
||||||
|
this.currentAuthenticationElement = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const scope = this.scope.$new(true);
|
||||||
|
scope.action = action;
|
||||||
|
scope.onSuccess = customSuccess;
|
||||||
|
scope.onCancel = customCancel;
|
||||||
|
scope.application = this;
|
||||||
|
const el = this.$compile(`
|
||||||
|
<privileges-auth-modal application='application' action='action' on-success='onSuccess'
|
||||||
|
on-cancel='onCancel' class='sk-modal'></privileges-auth-modal>
|
||||||
|
`)(scope);
|
||||||
|
angular.element(document.body).append(el);
|
||||||
|
|
||||||
|
this.currentAuthenticationElement = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
presentPrivilegesManagementModal() {
|
||||||
|
const scope = this.scope.$new(true);
|
||||||
|
scope.application = this;
|
||||||
|
const el = this.$compile("<privileges-management-modal application='application' class='sk-modal'></privileges-management-modal>")(scope);
|
||||||
|
angular.element(document.body).append(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticationInProgress() {
|
||||||
|
return this.currentAuthenticationElement != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
presentPasswordModal(callback) {
|
||||||
|
const scope = this.scope.$new(true);
|
||||||
|
scope.type = "password";
|
||||||
|
scope.title = "Decryption Assistance";
|
||||||
|
scope.message = `Unable to decrypt this item with your current keys.
|
||||||
|
Please enter your account password at the time of this revision.`;
|
||||||
|
scope.callback = callback;
|
||||||
|
const el = this.$compile(
|
||||||
|
`<input-modal type='type' message='message'
|
||||||
|
title='title' callback='callback'></input-modal>`
|
||||||
|
)(scope);
|
||||||
|
angular.element(document.body).append(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
presentRevisionPreviewModal(uuid, content) {
|
||||||
|
const scope = this.scope.$new(true);
|
||||||
|
scope.uuid = uuid;
|
||||||
|
scope.content = content;
|
||||||
|
scope.application = this;
|
||||||
|
const el = this.$compile(
|
||||||
|
`<revision-preview-modal application='application' uuid='uuid' content='content'
|
||||||
|
class='sk-modal'></revision-preview-modal>`
|
||||||
|
)(scope);
|
||||||
|
angular.element(document.body).append(el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
125
app/assets/javascripts/applicationManager.js
Normal file
125
app/assets/javascripts/applicationManager.js
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import { WebApplication } from './application';
|
||||||
|
import { removeFromArray } from 'snjs';
|
||||||
|
import {
|
||||||
|
ArchiveManager,
|
||||||
|
DesktopManager,
|
||||||
|
KeyboardManager,
|
||||||
|
LockManager,
|
||||||
|
NativeExtManager,
|
||||||
|
PreferencesManager,
|
||||||
|
StatusManager,
|
||||||
|
ThemeManager,
|
||||||
|
AppState
|
||||||
|
} from './services';
|
||||||
|
|
||||||
|
export class ApplicationManager {
|
||||||
|
/* @ngInject */
|
||||||
|
constructor($compile, $rootScope, $timeout) {
|
||||||
|
this.$compile = $compile;
|
||||||
|
this.$timeout = $timeout;
|
||||||
|
this.$rootScope = $rootScope;
|
||||||
|
this.applications = [];
|
||||||
|
this.changeObservers = [];
|
||||||
|
this.onApplicationDeinit = this.onApplicationDeinit.bind(this);
|
||||||
|
this.createDefaultApplication();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access private */
|
||||||
|
createDefaultApplication() {
|
||||||
|
this.activeApplication = this.createNewApplication();
|
||||||
|
this.applications.push(this.activeApplication);
|
||||||
|
this.notifyObserversOfAppChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @callback */
|
||||||
|
onApplicationDeinit(application) {
|
||||||
|
removeFromArray(this.applications, application);
|
||||||
|
if(this.activeApplication === application) {
|
||||||
|
this.activeApplication = null;
|
||||||
|
}
|
||||||
|
if (this.applications.length === 0) {
|
||||||
|
this.createDefaultApplication();
|
||||||
|
}
|
||||||
|
this.notifyObserversOfAppChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access private */
|
||||||
|
createNewApplication() {
|
||||||
|
const scope = this.$rootScope.$new(true);
|
||||||
|
const application = new WebApplication(
|
||||||
|
this.$compile,
|
||||||
|
this.$timeout,
|
||||||
|
scope,
|
||||||
|
this.onApplicationDeinit
|
||||||
|
);
|
||||||
|
const appState = new AppState(
|
||||||
|
this.$rootScope,
|
||||||
|
this.$timeout,
|
||||||
|
application
|
||||||
|
);
|
||||||
|
const archiveService = new ArchiveManager(
|
||||||
|
application
|
||||||
|
);
|
||||||
|
const desktopService = new DesktopManager(
|
||||||
|
this.$rootScope,
|
||||||
|
this.$timeout,
|
||||||
|
application
|
||||||
|
);
|
||||||
|
const keyboardService = new KeyboardManager();
|
||||||
|
const lockService = new LockManager(
|
||||||
|
application
|
||||||
|
);
|
||||||
|
const nativeExtService = new NativeExtManager(
|
||||||
|
application
|
||||||
|
);
|
||||||
|
const prefsService = new PreferencesManager(
|
||||||
|
application
|
||||||
|
);
|
||||||
|
const statusService = new StatusManager();
|
||||||
|
const themeService = new ThemeManager(
|
||||||
|
application,
|
||||||
|
);
|
||||||
|
application.setWebServices({
|
||||||
|
appState,
|
||||||
|
archiveService,
|
||||||
|
desktopService,
|
||||||
|
keyboardService,
|
||||||
|
lockService,
|
||||||
|
nativeExtService,
|
||||||
|
prefsService,
|
||||||
|
statusService,
|
||||||
|
themeService
|
||||||
|
});
|
||||||
|
return application;
|
||||||
|
}
|
||||||
|
|
||||||
|
get application() {
|
||||||
|
return this.activeApplication;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
getApplications() {
|
||||||
|
return this.applications.slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies observer when the active application has changed.
|
||||||
|
* Any application which is no longer active is destroyed, and
|
||||||
|
* must be removed from the interface.
|
||||||
|
* @access public
|
||||||
|
* @param {function} callback
|
||||||
|
*/
|
||||||
|
addApplicationChangeObserver(callback) {
|
||||||
|
this.changeObservers.push(callback);
|
||||||
|
if (this.application) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyObserversOfAppChange() {
|
||||||
|
for (const observer of this.changeObservers) {
|
||||||
|
observer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,34 +1,38 @@
|
|||||||
import { ApplicationService } from 'snjs';
|
import { ApplicationEvents } from 'snjs';
|
||||||
|
|
||||||
export class PureCtrl extends ApplicationService {
|
export class PureCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor($timeout) {
|
||||||
$scope,
|
if(!$timeout) {
|
||||||
$timeout,
|
throw Error('$timeout must not be null');
|
||||||
application,
|
|
||||||
appState
|
|
||||||
) {
|
|
||||||
if (!$scope || !$timeout || !application || !appState) {
|
|
||||||
throw 'Invalid PureCtrl construction.';
|
|
||||||
}
|
}
|
||||||
super(application);
|
|
||||||
this.$scope = $scope;
|
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.appState = appState;
|
|
||||||
this.props = {};
|
this.props = {};
|
||||||
this.state = {};
|
this.state = {};
|
||||||
/* Allow caller constructor to finish setting instance variables */
|
/* Allow caller constructor to finish setting instance variables */
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this.state = this.getInitialState();
|
this.state = this.getInitialState();
|
||||||
});
|
});
|
||||||
$scope.$on('$destroy', () => {
|
}
|
||||||
this.unsubState();
|
|
||||||
this.deinit();
|
$onInit() {
|
||||||
});
|
this.addAppEventObserver();
|
||||||
|
this.addAppStateObserver();
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
deinit() {
|
||||||
this.addAppStateObserver();
|
this.unsubApp();
|
||||||
|
this.unsubState();
|
||||||
|
this.unsubApp = null;
|
||||||
|
this.unsubState = null;
|
||||||
|
this.application = null;
|
||||||
|
if (this.stateTimeout) {
|
||||||
|
this.$timeout.cancel(this.stateTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$onDestroy() {
|
||||||
|
this.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
@@ -43,8 +47,11 @@ export class PureCtrl extends ApplicationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setState(state) {
|
async setState(state) {
|
||||||
|
if(!this.$timeout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this.$timeout(() => {
|
this.stateTimeout = this.$timeout(() => {
|
||||||
this.state = Object.freeze(Object.assign({}, this.state, state));
|
this.state = Object.freeze(Object.assign({}, this.state, state));
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
@@ -59,7 +66,7 @@ export class PureCtrl extends ApplicationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addAppStateObserver() {
|
addAppStateObserver() {
|
||||||
this.unsubState = this.appState.addObserver((eventName, data) => {
|
this.unsubState = this.application.getAppState().addObserver((eventName, data) => {
|
||||||
this.onAppStateEvent(eventName, data);
|
this.onAppStateEvent(eventName, data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -68,9 +75,46 @@ export class PureCtrl extends ApplicationService {
|
|||||||
/** Optional override */
|
/** Optional override */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addAppEventObserver() {
|
||||||
|
if (this.application.isStarted()) {
|
||||||
|
this.onAppStart();
|
||||||
|
}
|
||||||
|
if (this.application.isLaunched()) {
|
||||||
|
this.onAppLaunch();
|
||||||
|
}
|
||||||
|
this.unsubApp = this.application.addEventObserver(async (eventName) => {
|
||||||
|
this.onAppEvent(eventName);
|
||||||
|
if (eventName === ApplicationEvents.Started) {
|
||||||
|
await this.onAppStart();
|
||||||
|
} else if (eventName === ApplicationEvents.Launched) {
|
||||||
|
await this.onAppLaunch();
|
||||||
|
} else if (eventName === ApplicationEvents.CompletedSync) {
|
||||||
|
this.onAppSync();
|
||||||
|
} else if (eventName === ApplicationEvents.KeyStatusChanged) {
|
||||||
|
this.onAppKeyChange();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onAppEvent(eventName) {
|
||||||
|
/** Optional override */
|
||||||
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async onAppStart() {
|
async onAppStart() {
|
||||||
await this.resetState();
|
await this.resetState();
|
||||||
return super.onAppStart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onAppLaunch() {
|
||||||
|
/** Optional override */
|
||||||
|
}
|
||||||
|
|
||||||
|
async onAppKeyChange() {
|
||||||
|
/** Optional override */
|
||||||
|
}
|
||||||
|
|
||||||
|
onAppSync() {
|
||||||
|
/** Optional override */
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
281
app/assets/javascripts/controllers/applicationView.js
Normal file
281
app/assets/javascripts/controllers/applicationView.js
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
import { getPlatformString } from '@/utils';
|
||||||
|
import template from '%/application-view.pug';
|
||||||
|
import { AppStateEvents } from '@/services/state';
|
||||||
|
import { ApplicationEvents } from 'snjs';
|
||||||
|
import angular from 'angular';
|
||||||
|
import {
|
||||||
|
PANEL_NAME_NOTES,
|
||||||
|
PANEL_NAME_TAGS
|
||||||
|
} from '@/controllers/constants';
|
||||||
|
import {
|
||||||
|
STRING_SESSION_EXPIRED,
|
||||||
|
STRING_DEFAULT_FILE_ERROR
|
||||||
|
} from '@/strings';
|
||||||
|
import { PureCtrl } from './abstract/pure_ctrl';
|
||||||
|
|
||||||
|
class ApplicationViewCtrl extends PureCtrl {
|
||||||
|
/* @ngInject */
|
||||||
|
constructor(
|
||||||
|
$compile,
|
||||||
|
$location,
|
||||||
|
$rootScope,
|
||||||
|
$timeout
|
||||||
|
) {
|
||||||
|
super($timeout);
|
||||||
|
this.$location = $location;
|
||||||
|
this.$rootScope = $rootScope;
|
||||||
|
this.$compile = $compile;
|
||||||
|
this.platformString = getPlatformString();
|
||||||
|
this.state = { appClass: '' };
|
||||||
|
this.onDragDrop = this.onDragDrop.bind(this);
|
||||||
|
this.onDragOver = this.onDragOver.bind(this);
|
||||||
|
this.openModalComponent = this.openModalComponent.bind(this);
|
||||||
|
this.presentPermissionsDialog = this.presentPermissionsDialog.bind(this);
|
||||||
|
this.addDragDropHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.$location = null;
|
||||||
|
this.$rootScope = null;
|
||||||
|
this.$compile = null;
|
||||||
|
this.application = null;
|
||||||
|
this.lockScreenPuppet = null;
|
||||||
|
window.removeEventListener('dragover', this.onDragOver, true);
|
||||||
|
window.removeEventListener('drop', this.onDragDrop, true);
|
||||||
|
this.onDragDrop = null;
|
||||||
|
this.onDragOver = null;
|
||||||
|
this.openModalComponent = null;
|
||||||
|
this.presentPermissionsDialog = null;
|
||||||
|
super.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
super.$onInit();
|
||||||
|
this.loadApplication();
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadApplication() {
|
||||||
|
await this.application.prepareForLaunch({
|
||||||
|
callbacks: {
|
||||||
|
receiveChallenge: async (challenge, orchestrator) => {
|
||||||
|
this.application.promptForChallenge(challenge, orchestrator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await this.application.launch();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onAppStart() {
|
||||||
|
super.onAppStart();
|
||||||
|
this.overrideComponentManagerFunctions();
|
||||||
|
this.application.componentManager.setDesktopManager(this.application.getDesktopService());
|
||||||
|
this.setState({
|
||||||
|
ready: true,
|
||||||
|
needsUnlock: this.application.hasPasscode()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onAppLaunch() {
|
||||||
|
super.onAppLaunch();
|
||||||
|
this.setState({ needsUnlock: false });
|
||||||
|
this.handleAutoSignInFromParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
onUpdateAvailable() {
|
||||||
|
this.$rootScope.$broadcast('new-update-available');
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async onAppEvent(eventName) {
|
||||||
|
super.onAppEvent(eventName);
|
||||||
|
if (eventName === ApplicationEvents.LocalDataIncrementalLoad) {
|
||||||
|
this.updateLocalDataStatus();
|
||||||
|
} else if (eventName === ApplicationEvents.SyncStatusChanged) {
|
||||||
|
this.updateSyncStatus();
|
||||||
|
} else if (eventName === ApplicationEvents.LocalDataLoaded) {
|
||||||
|
this.updateLocalDataStatus();
|
||||||
|
} else if (eventName === ApplicationEvents.WillSync) {
|
||||||
|
if (!this.completedInitialSync) {
|
||||||
|
this.syncStatus = this.application.getStatusService().replaceStatusWithString(
|
||||||
|
this.syncStatus,
|
||||||
|
"Syncing..."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (eventName === ApplicationEvents.CompletedSync) {
|
||||||
|
if (!this.completedInitialSync) {
|
||||||
|
this.syncStatus = this.application.getStatusService().removeStatus(this.syncStatus);
|
||||||
|
this.completedInitialSync = true;
|
||||||
|
}
|
||||||
|
} else if (eventName === ApplicationEvents.InvalidSyncSession) {
|
||||||
|
this.showInvalidSessionAlert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async onAppStateEvent(eventName, data) {
|
||||||
|
if (eventName === AppStateEvents.PanelResized) {
|
||||||
|
if (data.panel === PANEL_NAME_NOTES) {
|
||||||
|
this.notesCollapsed = data.collapsed;
|
||||||
|
}
|
||||||
|
if (data.panel === PANEL_NAME_TAGS) {
|
||||||
|
this.tagsCollapsed = data.collapsed;
|
||||||
|
}
|
||||||
|
let appClass = "";
|
||||||
|
if (this.notesCollapsed) { appClass += "collapsed-notes"; }
|
||||||
|
if (this.tagsCollapsed) { appClass += " collapsed-tags"; }
|
||||||
|
this.setState({ appClass });
|
||||||
|
} else if (eventName === AppStateEvents.WindowDidFocus) {
|
||||||
|
if (!(await this.application.isLocked())) {
|
||||||
|
this.application.sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLocalDataStatus() {
|
||||||
|
const syncStatus = this.application.getSyncStatus();
|
||||||
|
const stats = syncStatus.getStats();
|
||||||
|
const encryption = this.application.isEncryptionAvailable();
|
||||||
|
if (stats.localDataDone) {
|
||||||
|
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,
|
||||||
|
loadingStatus
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSyncStatus() {
|
||||||
|
const syncStatus = this.application.getSyncStatus();
|
||||||
|
const stats = syncStatus.getStats();
|
||||||
|
if (stats.downloadCount > 20) {
|
||||||
|
const text = `Downloading ${stats.downloadCount} items. Keep app open.`;
|
||||||
|
this.syncStatus = this.application.getStatusService().replaceStatusWithString(
|
||||||
|
this.syncStatus,
|
||||||
|
text
|
||||||
|
);
|
||||||
|
this.showingDownloadStatus = true;
|
||||||
|
} else if (this.showingDownloadStatus) {
|
||||||
|
this.showingDownloadStatus = false;
|
||||||
|
const text = "Download Complete.";
|
||||||
|
this.syncStatus = this.application.getStatusService().replaceStatusWithString(
|
||||||
|
this.syncStatus,
|
||||||
|
text
|
||||||
|
);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.syncStatus = this.application.getStatusService().removeStatus(this.syncStatus);
|
||||||
|
}, 2000);
|
||||||
|
} else if (stats.uploadTotalCount > 20) {
|
||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openModalComponent(component) {
|
||||||
|
const scope = this.$rootScope.$new(true);
|
||||||
|
scope.component = component;
|
||||||
|
const el = this.$compile("<component-modal component='component' class='sk-modal'></component-modal>")(scope);
|
||||||
|
angular.element(document.body).append(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
presentPermissionsDialog(dialog) {
|
||||||
|
const scope = this.$rootScope.$new(true);
|
||||||
|
scope.permissionsString = dialog.permissionsString;
|
||||||
|
scope.component = dialog.component;
|
||||||
|
scope.callback = dialog.callback;
|
||||||
|
const el = this.$compile("<permissions-modal component='component' permissions-string='permissionsString' callback='callback' class='sk-modal'></permissions-modal>")(scope);
|
||||||
|
angular.element(document.body).append(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
overrideComponentManagerFunctions() {
|
||||||
|
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();
|
||||||
|
setTimeout(() => {
|
||||||
|
this.alertService.alert({
|
||||||
|
text: STRING_SESSION_EXPIRED
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addDragDropHandlers() {
|
||||||
|
/**
|
||||||
|
* Disable dragging and dropping of files (but allow text) into main SN interface.
|
||||||
|
* both 'dragover' and 'drop' are required to prevent dropping of files.
|
||||||
|
* This will not prevent extensions from receiving drop events.
|
||||||
|
*/
|
||||||
|
window.addEventListener('dragover', this.onDragOver, true);
|
||||||
|
window.addEventListener('drop', this.onDragDrop, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragOver(event) {
|
||||||
|
if (event.dataTransfer.files.length > 0) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragDrop(event) {
|
||||||
|
if (event.dataTransfer.files.length > 0) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.application.alertService.alert({
|
||||||
|
text: STRING_DEFAULT_FILE_ERROR
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleAutoSignInFromParams() {
|
||||||
|
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();
|
||||||
|
if (user) {
|
||||||
|
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.setHost(server);
|
||||||
|
this.application.signIn({
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ApplicationView {
|
||||||
|
constructor() {
|
||||||
|
this.template = template;
|
||||||
|
this.controller = ApplicationViewCtrl;
|
||||||
|
this.replace = true;
|
||||||
|
this.controllerAs = 'self';
|
||||||
|
this.bindToController = {
|
||||||
|
application: '='
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import { isDesktopApplication } from '@/utils';
|
|||||||
import { KeyboardModifiers, KeyboardKeys } from '@/services/keyboardManager';
|
import { KeyboardModifiers, KeyboardKeys } from '@/services/keyboardManager';
|
||||||
import template from '%/editor.pug';
|
import template from '%/editor.pug';
|
||||||
import { PureCtrl } from '@Controllers';
|
import { PureCtrl } from '@Controllers';
|
||||||
import { AppStateEvents, EventSources } from '@/state';
|
import { AppStateEvents, EventSources } from '@/services/state';
|
||||||
import {
|
import {
|
||||||
STRING_DELETED_NOTE,
|
STRING_DELETED_NOTE,
|
||||||
STRING_INVALID_NOTE,
|
STRING_INVALID_NOTE,
|
||||||
@@ -48,35 +48,34 @@ const Fonts = {
|
|||||||
|
|
||||||
class EditorCtrl extends PureCtrl {
|
class EditorCtrl extends PureCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor($timeout) {
|
||||||
$scope,
|
super($timeout);
|
||||||
$timeout,
|
|
||||||
$rootScope,
|
|
||||||
application,
|
|
||||||
appState,
|
|
||||||
desktopManager,
|
|
||||||
keyboardManager,
|
|
||||||
preferencesManager,
|
|
||||||
) {
|
|
||||||
super($scope, $timeout, application, appState);
|
|
||||||
this.$rootScope = $rootScope;
|
|
||||||
this.desktopManager = desktopManager;
|
|
||||||
this.keyboardManager = keyboardManager;
|
|
||||||
this.preferencesManager = preferencesManager;
|
|
||||||
this.leftPanelPuppet = {
|
this.leftPanelPuppet = {
|
||||||
onReady: () => this.reloadPreferences()
|
onReady: () => this.reloadPreferences()
|
||||||
};
|
};
|
||||||
this.rightPanelPuppet = {
|
this.rightPanelPuppet = {
|
||||||
onReady: () => this.reloadPreferences()
|
onReady: () => this.reloadPreferences()
|
||||||
};
|
};
|
||||||
this.addSyncStatusObserver();
|
|
||||||
this.registerKeyboardShortcuts();
|
|
||||||
/** Used by .pug template */
|
/** Used by .pug template */
|
||||||
this.prefKeyMonospace = PrefKeys.EditorMonospaceEnabled;
|
this.prefKeyMonospace = PrefKeys.EditorMonospaceEnabled;
|
||||||
this.prefKeySpellcheck = PrefKeys.EditorSpellcheck;
|
this.prefKeySpellcheck = PrefKeys.EditorSpellcheck;
|
||||||
this.prefKeyMarginResizers = PrefKeys.EditorResizersEnabled;
|
this.prefKeyMarginResizers = PrefKeys.EditorResizersEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.removeTabObserver();
|
||||||
|
this.leftPanelPuppet = null;
|
||||||
|
this.rightPanelPuppet = null;
|
||||||
|
this.onEditorLoad = null;
|
||||||
|
super.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
super.$onInit();
|
||||||
|
this.addSyncStatusObserver();
|
||||||
|
this.registerKeyboardShortcuts();
|
||||||
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return {
|
return {
|
||||||
@@ -100,7 +99,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
onAppStateEvent(eventName, data) {
|
onAppStateEvent(eventName, data) {
|
||||||
if (eventName === AppStateEvents.NoteChanged) {
|
if (eventName === AppStateEvents.NoteChanged) {
|
||||||
this.handleNoteSelectionChange(
|
this.handleNoteSelectionChange(
|
||||||
this.appState.getSelectedNote(),
|
this.application.getAppState().getSelectedNote(),
|
||||||
data.previousNote
|
data.previousNote
|
||||||
);
|
);
|
||||||
} else if (eventName === AppStateEvents.PreferencesChanged) {
|
} else if (eventName === AppStateEvents.PreferencesChanged) {
|
||||||
@@ -209,7 +208,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
|
|
||||||
async handleNoteSelectionChange(note, previousNote) {
|
async handleNoteSelectionChange(note, previousNote) {
|
||||||
this.setState({
|
this.setState({
|
||||||
note: this.appState.getSelectedNote(),
|
note: this.application.getAppState().getSelectedNote(),
|
||||||
showExtensions: false,
|
showExtensions: false,
|
||||||
showOptionsMenu: false,
|
showOptionsMenu: false,
|
||||||
altKeyDown: false,
|
altKeyDown: false,
|
||||||
@@ -504,7 +503,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onContentFocus() {
|
onContentFocus() {
|
||||||
this.appState.editorDidFocus(this.lastEditorFocusEventSource);
|
this.application.getAppState().editorDidFocus(this.lastEditorFocusEventSource);
|
||||||
this.lastEditorFocusEventSource = null;
|
this.lastEditorFocusEventSource = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +551,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
dontUpdatePreviews: true
|
dontUpdatePreviews: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.appState.setSelectedNote(null);
|
this.application.getAppState().setSelectedNote(null);
|
||||||
this.setMenuState('showOptionsMenu', false);
|
this.setMenuState('showOptionsMenu', false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -561,7 +560,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
ProtectedActions.DeleteNote
|
ProtectedActions.DeleteNote
|
||||||
);
|
);
|
||||||
if (requiresPrivilege) {
|
if (requiresPrivilege) {
|
||||||
this.godService.presentPrivilegesModal(
|
this.application.presentPrivilegesModal(
|
||||||
ProtectedActions.DeleteNote,
|
ProtectedActions.DeleteNote,
|
||||||
() => {
|
() => {
|
||||||
run();
|
run();
|
||||||
@@ -592,7 +591,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
bypassDebouncer: true,
|
bypassDebouncer: true,
|
||||||
dontUpdatePreviews: true
|
dontUpdatePreviews: true
|
||||||
});
|
});
|
||||||
this.appState.setSelectedNote(null);
|
this.application.getAppState().setSelectedNote(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteNotePermanantely() {
|
deleteNotePermanantely() {
|
||||||
@@ -649,7 +648,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
ProtectedActions.ViewProtectedNotes
|
ProtectedActions.ViewProtectedNotes
|
||||||
).then((configured) => {
|
).then((configured) => {
|
||||||
if (!configured) {
|
if (!configured) {
|
||||||
this.godService.presentPrivilegesManagementModal();
|
this.application.presentPrivilegesManagementModal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -743,13 +742,13 @@ class EditorCtrl extends PureCtrl {
|
|||||||
|
|
||||||
onPanelResizeFinish = (width, left, isMaxWidth) => {
|
onPanelResizeFinish = (width, left, isMaxWidth) => {
|
||||||
if (isMaxWidth) {
|
if (isMaxWidth) {
|
||||||
this.preferencesManager.setUserPrefValue(
|
this.application.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.EditorWidth,
|
PrefKeys.EditorWidth,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (width !== undefined && width !== null) {
|
if (width !== undefined && width !== null) {
|
||||||
this.preferencesManager.setUserPrefValue(
|
this.application.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.EditorWidth,
|
PrefKeys.EditorWidth,
|
||||||
width
|
width
|
||||||
);
|
);
|
||||||
@@ -757,25 +756,25 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (left !== undefined && left !== null) {
|
if (left !== undefined && left !== null) {
|
||||||
this.preferencesManager.setUserPrefValue(
|
this.application.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.EditorLeft,
|
PrefKeys.EditorLeft,
|
||||||
left
|
left
|
||||||
);
|
);
|
||||||
this.rightPanelPuppet.setLeft(left);
|
this.rightPanelPuppet.setLeft(left);
|
||||||
}
|
}
|
||||||
this.preferencesManager.syncUserPreferences();
|
this.application.getPrefsService().syncUserPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadPreferences() {
|
reloadPreferences() {
|
||||||
const monospaceEnabled = this.preferencesManager.getValue(
|
const monospaceEnabled = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.EditorMonospaceEnabled,
|
PrefKeys.EditorMonospaceEnabled,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
const spellcheck = this.preferencesManager.getValue(
|
const spellcheck = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.EditorSpellcheck,
|
PrefKeys.EditorSpellcheck,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
const marginResizersEnabled = this.preferencesManager.getValue(
|
const marginResizersEnabled = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.EditorResizersEnabled,
|
PrefKeys.EditorResizersEnabled,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
@@ -797,7 +796,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
this.leftPanelPuppet.ready &&
|
this.leftPanelPuppet.ready &&
|
||||||
this.rightPanelPuppet.ready
|
this.rightPanelPuppet.ready
|
||||||
) {
|
) {
|
||||||
const width = this.preferencesManager.getValue(
|
const width = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.EditorWidth,
|
PrefKeys.EditorWidth,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
@@ -805,7 +804,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
this.leftPanelPuppet.setWidth(width);
|
this.leftPanelPuppet.setWidth(width);
|
||||||
this.rightPanelPuppet.setWidth(width);
|
this.rightPanelPuppet.setWidth(width);
|
||||||
}
|
}
|
||||||
const left = this.preferencesManager.getValue(
|
const left = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.EditorLeft,
|
PrefKeys.EditorLeft,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
@@ -836,7 +835,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
|
|
||||||
async toggleKey(key) {
|
async toggleKey(key) {
|
||||||
this[key] = !this[key];
|
this[key] = !this[key];
|
||||||
this.preferencesManager.setUserPrefValue(
|
this.application.getPrefsService().setUserPrefValue(
|
||||||
key,
|
key,
|
||||||
this[key],
|
this[key],
|
||||||
true
|
true
|
||||||
@@ -863,7 +862,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
/** @components */
|
/** @components */
|
||||||
|
|
||||||
onEditorLoad = (editor) => {
|
onEditorLoad = (editor) => {
|
||||||
this.desktopManager.redoSearch();
|
this.application.getDesktopService().redoSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
registerComponentHandler() {
|
registerComponentHandler() {
|
||||||
@@ -1047,7 +1046,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerKeyboardShortcuts() {
|
registerKeyboardShortcuts() {
|
||||||
this.altKeyObserver = this.keyboardManager.addKeyObserver({
|
this.altKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
||||||
modifiers: [
|
modifiers: [
|
||||||
KeyboardModifiers.Alt
|
KeyboardModifiers.Alt
|
||||||
],
|
],
|
||||||
@@ -1063,7 +1062,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.trashKeyObserver = this.keyboardManager.addKeyObserver({
|
this.trashKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
||||||
key: KeyboardKeys.Backspace,
|
key: KeyboardKeys.Backspace,
|
||||||
notElementIds: [
|
notElementIds: [
|
||||||
ElementIds.NoteTextEditor,
|
ElementIds.NoteTextEditor,
|
||||||
@@ -1075,7 +1074,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.deleteKeyObserver = this.keyboardManager.addKeyObserver({
|
this.deleteKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
||||||
key: KeyboardKeys.Backspace,
|
key: KeyboardKeys.Backspace,
|
||||||
modifiers: [
|
modifiers: [
|
||||||
KeyboardModifiers.Meta,
|
KeyboardModifiers.Meta,
|
||||||
@@ -1090,10 +1089,9 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSystemEditorLoad() {
|
onSystemEditorLoad() {
|
||||||
if (this.loadedTabListener) {
|
if (this.tabObserver) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.loadedTabListener = true;
|
|
||||||
/**
|
/**
|
||||||
* Insert 4 spaces when a tab key is pressed,
|
* Insert 4 spaces when a tab key is pressed,
|
||||||
* only used when inside of the text editor.
|
* only used when inside of the text editor.
|
||||||
@@ -1103,7 +1101,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
const editor = document.getElementById(
|
const editor = document.getElementById(
|
||||||
ElementIds.NoteTextEditor
|
ElementIds.NoteTextEditor
|
||||||
);
|
);
|
||||||
this.tabObserver = this.keyboardManager.addKeyObserver({
|
this.tabObserver = this.application.getKeyboardService().addKeyObserver({
|
||||||
element: editor,
|
element: editor,
|
||||||
key: KeyboardKeys.Tab,
|
key: KeyboardKeys.Tab,
|
||||||
onKeyDown: (event) => {
|
onKeyDown: (event) => {
|
||||||
@@ -1144,19 +1142,29 @@ class EditorCtrl extends PureCtrl {
|
|||||||
* Handles when the editor is destroyed,
|
* Handles when the editor is destroyed,
|
||||||
* (and not when our controller is destroyed.)
|
* (and not when our controller is destroyed.)
|
||||||
*/
|
*/
|
||||||
angular.element(editor).on('$destroy', () => {
|
angular.element(editor).one('$destroy', () => {
|
||||||
if (this.tabObserver) {
|
this.removeTabObserver();
|
||||||
this.keyboardManager.removeKeyObserver(this.tabObserver);
|
|
||||||
this.loadedTabListener = false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
|
removeTabObserver() {
|
||||||
|
if (!this.application) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const keyboardService = this.application.getKeyboardService();
|
||||||
|
if (this.tabObserver && keyboardService) {
|
||||||
|
keyboardService.removeKeyObserver(this.tabObserver);
|
||||||
|
this.tabObserver = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EditorPanel {
|
export class EditorPanel {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.restrict = 'E';
|
this.restrict = 'E';
|
||||||
this.scope = {};
|
this.scope = {
|
||||||
|
application: '='
|
||||||
|
};
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controller = EditorCtrl;
|
this.controller = EditorCtrl;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
ContentTypes
|
ContentTypes
|
||||||
} from 'snjs';
|
} from 'snjs';
|
||||||
import template from '%/footer.pug';
|
import template from '%/footer.pug';
|
||||||
import { AppStateEvents, EventSources } from '@/state';
|
import { AppStateEvents, EventSources } from '@/services/state';
|
||||||
import {
|
import {
|
||||||
STRING_GENERIC_SYNC_ERROR,
|
STRING_GENERIC_SYNC_ERROR,
|
||||||
STRING_NEW_UPDATE_READY
|
STRING_NEW_UPDATE_READY
|
||||||
@@ -17,25 +17,32 @@ class FooterCtrl extends PureCtrl {
|
|||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$scope,
|
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$timeout,
|
$timeout,
|
||||||
application,
|
|
||||||
appState,
|
|
||||||
nativeExtManager,
|
|
||||||
statusManager,
|
|
||||||
godService
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.$rootScope = $rootScope;
|
this.$rootScope = $rootScope;
|
||||||
this.nativeExtManager = nativeExtManager;
|
|
||||||
this.statusManager = statusManager;
|
|
||||||
this.godService = godService;
|
|
||||||
this.rooms = [];
|
this.rooms = [];
|
||||||
this.themesWithIcons = [];
|
this.themesWithIcons = [];
|
||||||
this.showSyncResolution = false;
|
this.showSyncResolution = false;
|
||||||
this.addRootScopeListeners();
|
this.addRootScopeListeners();
|
||||||
this.statusManager.addStatusObserver((string) => {
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.rooms.length = 0;
|
||||||
|
this.themesWithIcons.length = 0;
|
||||||
|
this.rootScopeListener1();
|
||||||
|
this.rootScopeListener2();
|
||||||
|
this.rootScopeListener1 = null;
|
||||||
|
this.rootScopeListener2 = null;
|
||||||
|
this.closeAccountMenu = null;
|
||||||
|
this.toggleSyncResolutionMenu = null;
|
||||||
|
super.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
super.$onInit();
|
||||||
|
this.application.getStatusService().addStatusObserver((string) => {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.arbitraryStatusMessage = string;
|
this.arbitraryStatusMessage = string;
|
||||||
});
|
});
|
||||||
@@ -49,7 +56,7 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reloadUpgradeStatus() {
|
reloadUpgradeStatus() {
|
||||||
this.godService.checkForSecurityUpdate().then((available) => {
|
this.application.checkForSecurityUpdate().then((available) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
dataUpgradeAvailable: available
|
dataUpgradeAvailable: available
|
||||||
});
|
});
|
||||||
@@ -72,10 +79,10 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addRootScopeListeners() {
|
addRootScopeListeners() {
|
||||||
this.$rootScope.$on("reload-ext-data", () => {
|
this.rootScopeListener1 = this.$rootScope.$on("reload-ext-data", () => {
|
||||||
this.reloadExtendedData();
|
this.reloadExtendedData();
|
||||||
});
|
});
|
||||||
this.$rootScope.$on("new-update-available", () => {
|
this.rootScopeListener2 = this.$rootScope.$on("new-update-available", () => {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.onNewUpdateAvailable();
|
this.onNewUpdateAvailable();
|
||||||
});
|
});
|
||||||
@@ -90,23 +97,23 @@ class FooterCtrl extends PureCtrl {
|
|||||||
this.closeAccountMenu();
|
this.closeAccountMenu();
|
||||||
}
|
}
|
||||||
} else if (eventName === AppStateEvents.BeganBackupDownload) {
|
} else if (eventName === AppStateEvents.BeganBackupDownload) {
|
||||||
this.backupStatus = this.statusManager.addStatusFromString(
|
this.backupStatus = this.application.getStatusService().addStatusFromString(
|
||||||
"Saving local backup..."
|
"Saving local backup..."
|
||||||
);
|
);
|
||||||
} else if (eventName === AppStateEvents.EndedBackupDownload) {
|
} else if (eventName === AppStateEvents.EndedBackupDownload) {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
this.backupStatus = this.statusManager.replaceStatusWithString(
|
this.backupStatus = this.application.getStatusService().replaceStatusWithString(
|
||||||
this.backupStatus,
|
this.backupStatus,
|
||||||
"Successfully saved backup."
|
"Successfully saved backup."
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.backupStatus = this.statusManager.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.statusManager.removeStatus(this.backupStatus);
|
this.backupStatus = this.application.getStatusService().removeStatus(this.backupStatus);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,7 +212,7 @@ 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.nativeExtManager.extManagerId;
|
return room.package_info.identifier === this.application.getNativeExtService().extManagerId;
|
||||||
});
|
});
|
||||||
if (!extWindow) {
|
if (!extWindow) {
|
||||||
this.queueExtReload = true;
|
this.queueExtReload = true;
|
||||||
@@ -225,7 +232,7 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openSecurityUpdate() {
|
openSecurityUpdate() {
|
||||||
this.godService.performProtocolUpgrade();
|
this.application.performProtocolUpgrade();
|
||||||
}
|
}
|
||||||
|
|
||||||
findErrors() {
|
findErrors() {
|
||||||
@@ -347,7 +354,7 @@ class FooterCtrl extends PureCtrl {
|
|||||||
ProtectedActions.ManageExtensions
|
ProtectedActions.ManageExtensions
|
||||||
);
|
);
|
||||||
if (requiresPrivilege) {
|
if (requiresPrivilege) {
|
||||||
this.godService.presentPrivilegesModal(
|
this.application.presentPrivilegesModal(
|
||||||
ProtectedActions.ManageExtensions,
|
ProtectedActions.ManageExtensions,
|
||||||
run
|
run
|
||||||
);
|
);
|
||||||
@@ -360,7 +367,7 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clickOutsideAccountMenu() {
|
clickOutsideAccountMenu() {
|
||||||
if (this.godService.authenticationInProgress()) {
|
if (this.application && this.application.authenticationInProgress()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.showAccountMenu = false;
|
this.showAccountMenu = false;
|
||||||
@@ -370,11 +377,12 @@ class FooterCtrl extends PureCtrl {
|
|||||||
export class Footer {
|
export class Footer {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.restrict = 'E';
|
this.restrict = 'E';
|
||||||
this.scope = {};
|
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.controller = FooterCtrl;
|
this.controller = FooterCtrl;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controllerAs = 'ctrl';
|
this.controllerAs = 'ctrl';
|
||||||
this.bindToController = true;
|
this.bindToController = {
|
||||||
|
application: '='
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ export { Footer } from './footer';
|
|||||||
export { NotesPanel } from './notes/notes';
|
export { NotesPanel } from './notes/notes';
|
||||||
export { TagsPanel } from './tags';
|
export { TagsPanel } from './tags';
|
||||||
export { Root } from './root';
|
export { Root } from './root';
|
||||||
export { LockScreen } from './lockScreen';
|
export { ApplicationView } from './applicationView';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import template from '%/lock-screen.pug';
|
import template from '%/lock-screen.pug';
|
||||||
import { AppStateEvents } from '@/state';
|
import { AppStateEvents } from '@/services/state';
|
||||||
import { PureCtrl } from './abstract/pure_ctrl';
|
import { PureCtrl } from './abstract/pure_ctrl';
|
||||||
|
|
||||||
const ELEMENT_ID_PASSCODE_INPUT = 'passcode-input';
|
const ELEMENT_ID_PASSCODE_INPUT = 'passcode-input';
|
||||||
@@ -7,12 +7,9 @@ const ELEMENT_ID_PASSCODE_INPUT = 'passcode-input';
|
|||||||
class LockScreenCtrl extends PureCtrl {
|
class LockScreenCtrl extends PureCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$scope,
|
|
||||||
$timeout,
|
$timeout,
|
||||||
application,
|
|
||||||
appState
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.formData = {};
|
this.formData = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@ import angular from 'angular';
|
|||||||
import template from '%/notes.pug';
|
import template from '%/notes.pug';
|
||||||
import { ApplicationEvents, ContentTypes, removeFromArray } from 'snjs';
|
import { ApplicationEvents, ContentTypes, removeFromArray } from 'snjs';
|
||||||
import { PureCtrl } from '@Controllers';
|
import { PureCtrl } from '@Controllers';
|
||||||
import { AppStateEvents } from '@/state';
|
import { AppStateEvents } from '@/services/state';
|
||||||
import { KeyboardModifiers, KeyboardKeys } from '@/services/keyboardManager';
|
import { KeyboardModifiers, KeyboardKeys } from '@/services/keyboardManager';
|
||||||
import {
|
import {
|
||||||
PrefKeys
|
PrefKeys
|
||||||
@@ -31,24 +31,10 @@ class NotesCtrl extends PureCtrl {
|
|||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$scope,
|
|
||||||
$timeout,
|
$timeout,
|
||||||
$rootScope,
|
|
||||||
application,
|
|
||||||
appState,
|
|
||||||
desktopManager,
|
|
||||||
keyboardManager,
|
|
||||||
preferencesManager,
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.$rootScope = $rootScope;
|
|
||||||
this.application = application;
|
|
||||||
this.appState = appState;
|
|
||||||
this.desktopManager = desktopManager;
|
|
||||||
this.keyboardManager = keyboardManager;
|
|
||||||
this.preferencesManager = preferencesManager;
|
|
||||||
this.resetPagination();
|
this.resetPagination();
|
||||||
this.registerKeyboardShortcuts();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
@@ -59,11 +45,24 @@ class NotesCtrl extends PureCtrl {
|
|||||||
this.panelPuppet = {
|
this.panelPuppet = {
|
||||||
onReady: () => this.reloadPreferences()
|
onReady: () => this.reloadPreferences()
|
||||||
};
|
};
|
||||||
window.onresize = (event) => {
|
this.onWindowResize = this.onWindowResize.bind(this);
|
||||||
this.resetPagination({
|
window.addEventListener('resize', this.onWindowResize, true);
|
||||||
keepCurrentIfLarger: true
|
this.registerKeyboardShortcuts();
|
||||||
});
|
}
|
||||||
};
|
|
||||||
|
onWindowResize() {
|
||||||
|
this.resetPagination({
|
||||||
|
keepCurrentIfLarger: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.panelPuppet.onReady = null;
|
||||||
|
this.panelPuppet = null;
|
||||||
|
window.removeEventListener('resize', this.onWindowResize, true);
|
||||||
|
this.onWindowResize = null;
|
||||||
|
this.onPanelResize = null;
|
||||||
|
super.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
@@ -91,9 +90,9 @@ class NotesCtrl extends PureCtrl {
|
|||||||
/** @override */
|
/** @override */
|
||||||
onAppStateEvent(eventName, data) {
|
onAppStateEvent(eventName, data) {
|
||||||
if (eventName === AppStateEvents.TagChanged) {
|
if (eventName === AppStateEvents.TagChanged) {
|
||||||
this.handleTagChange(this.appState.getSelectedTag(), data.previousTag);
|
this.handleTagChange(this.application.getAppState().getSelectedTag(), data.previousTag);
|
||||||
} else if (eventName === AppStateEvents.NoteChanged) {
|
} else if (eventName === AppStateEvents.NoteChanged) {
|
||||||
this.handleNoteSelection(this.appState.getSelectedNote());
|
this.handleNoteSelection(this.application.getAppState().getSelectedNote());
|
||||||
} else if (eventName === AppStateEvents.PreferencesChanged) {
|
} else if (eventName === AppStateEvents.PreferencesChanged) {
|
||||||
this.reloadPreferences();
|
this.reloadPreferences();
|
||||||
this.reloadNotes();
|
this.reloadNotes();
|
||||||
@@ -129,8 +128,8 @@ class NotesCtrl extends PureCtrl {
|
|||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
async createPlaceholderNote() {
|
async createPlaceholderNote() {
|
||||||
const selectedTag = this.appState.getSelectedTag();
|
const selectedTag = this.application.getAppState().getSelectedTag();
|
||||||
if(selectedTag.isSmartTag() && !selectedTag.content.isAllTag) {
|
if (selectedTag.isSmartTag() && !selectedTag.content.isAllTag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return this.createNewNote();
|
return this.createNewNote();
|
||||||
@@ -163,11 +162,11 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async selectNote(note) {
|
async selectNote(note) {
|
||||||
this.appState.setSelectedNote(note);
|
this.application.getAppState().setSelectedNote(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNewNote() {
|
async createNewNote() {
|
||||||
const selectedTag = this.appState.getSelectedTag();
|
const selectedTag = this.application.getAppState().getSelectedTag();
|
||||||
if (!selectedTag) {
|
if (!selectedTag) {
|
||||||
throw 'Attempting to create note with no selected tag';
|
throw 'Attempting to create note with no selected tag';
|
||||||
}
|
}
|
||||||
@@ -209,11 +208,11 @@ class NotesCtrl extends PureCtrl {
|
|||||||
await this.selectNote(null);
|
await this.selectNote(null);
|
||||||
}
|
}
|
||||||
await this.setState({ tag: tag });
|
await this.setState({ tag: tag });
|
||||||
|
|
||||||
this.resetScrollPosition();
|
this.resetScrollPosition();
|
||||||
this.setShowMenuFalse();
|
this.setShowMenuFalse();
|
||||||
await this.setNoteFilterText('');
|
await this.setNoteFilterText('');
|
||||||
this.desktopManager.searchText();
|
this.application.getDesktopService().searchText();
|
||||||
this.resetPagination();
|
this.resetPagination();
|
||||||
|
|
||||||
/* Capture db load state before beginning reloadNotes, since this status may change during reload */
|
/* Capture db load state before beginning reloadNotes, since this status may change during reload */
|
||||||
@@ -307,14 +306,14 @@ class NotesCtrl extends PureCtrl {
|
|||||||
this.application.saveItem({ item: note });
|
this.application.saveItem({ item: note });
|
||||||
}
|
}
|
||||||
if (this.isFiltering()) {
|
if (this.isFiltering()) {
|
||||||
this.desktopManager.searchText(this.state.noteFilter.text);
|
this.application.getDesktopService().searchText(this.state.noteFilter.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadPreferences() {
|
reloadPreferences() {
|
||||||
const viewOptions = {};
|
const viewOptions = {};
|
||||||
const prevSortValue = this.state.sortBy;
|
const prevSortValue = this.state.sortBy;
|
||||||
let sortBy = this.preferencesManager.getValue(
|
let sortBy = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.SortNotesBy,
|
PrefKeys.SortNotesBy,
|
||||||
SORT_KEY_CREATED_AT
|
SORT_KEY_CREATED_AT
|
||||||
);
|
);
|
||||||
@@ -323,27 +322,27 @@ class NotesCtrl extends PureCtrl {
|
|||||||
sortBy = SORT_KEY_CLIENT_UPDATED_AT;
|
sortBy = SORT_KEY_CLIENT_UPDATED_AT;
|
||||||
}
|
}
|
||||||
viewOptions.sortBy = sortBy;
|
viewOptions.sortBy = sortBy;
|
||||||
viewOptions.sortReverse = this.preferencesManager.getValue(
|
viewOptions.sortReverse = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.SortNotesReverse,
|
PrefKeys.SortNotesReverse,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.showArchived = this.preferencesManager.getValue(
|
viewOptions.showArchived = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.NotesShowArchived,
|
PrefKeys.NotesShowArchived,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.hidePinned = this.preferencesManager.getValue(
|
viewOptions.hidePinned = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.NotesHidePinned,
|
PrefKeys.NotesHidePinned,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.hideNotePreview = this.preferencesManager.getValue(
|
viewOptions.hideNotePreview = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.NotesHideNotePreview,
|
PrefKeys.NotesHideNotePreview,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.hideDate = this.preferencesManager.getValue(
|
viewOptions.hideDate = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.NotesHideDate,
|
PrefKeys.NotesHideDate,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.hideTags = this.preferencesManager.getValue(
|
viewOptions.hideTags = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.NotesHideTags,
|
PrefKeys.NotesHideTags,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
@@ -353,13 +352,13 @@ class NotesCtrl extends PureCtrl {
|
|||||||
if (prevSortValue && prevSortValue !== sortBy) {
|
if (prevSortValue && prevSortValue !== sortBy) {
|
||||||
this.selectFirstNote();
|
this.selectFirstNote();
|
||||||
}
|
}
|
||||||
const width = this.preferencesManager.getValue(
|
const width = this.application.getPrefsService().getValue(
|
||||||
PrefKeys.NotesPanelWidth
|
PrefKeys.NotesPanelWidth
|
||||||
);
|
);
|
||||||
if (width && this.panelPuppet.ready) {
|
if (width && this.panelPuppet.ready) {
|
||||||
this.panelPuppet.setWidth(width);
|
this.panelPuppet.setWidth(width);
|
||||||
if (this.panelPuppet.isCollapsed()) {
|
if (this.panelPuppet.isCollapsed()) {
|
||||||
this.appState.panelDidResize({
|
this.application.getAppState().panelDidResize({
|
||||||
name: PANEL_NAME_NOTES,
|
name: PANEL_NAME_NOTES,
|
||||||
collapsed: this.panelPuppet.isCollapsed()
|
collapsed: this.panelPuppet.isCollapsed()
|
||||||
});
|
});
|
||||||
@@ -368,12 +367,12 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onPanelResize = (newWidth, lastLeft, isAtMaxWidth, isCollapsed) => {
|
onPanelResize = (newWidth, lastLeft, isAtMaxWidth, isCollapsed) => {
|
||||||
this.preferencesManager.setUserPrefValue(
|
this.application.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.NotesPanelWidth,
|
PrefKeys.NotesPanelWidth,
|
||||||
newWidth
|
newWidth
|
||||||
);
|
);
|
||||||
this.preferencesManager.syncUserPreferences();
|
this.application.getPrefsService().syncUserPreferences();
|
||||||
this.appState.panelDidResize({
|
this.application.getAppState().panelDidResize({
|
||||||
name: PANEL_NAME_NOTES,
|
name: PANEL_NAME_NOTES,
|
||||||
collapsed: isCollapsed
|
collapsed: isCollapsed
|
||||||
});
|
});
|
||||||
@@ -383,7 +382,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
this.notesToDisplay += this.pageSize;
|
this.notesToDisplay += this.pageSize;
|
||||||
this.reloadNotes();
|
this.reloadNotes();
|
||||||
if (this.searchSubmitted) {
|
if (this.searchSubmitted) {
|
||||||
this.desktopManager.searchText(this.state.noteFilter.text);
|
this.application.getDesktopService().searchText(this.state.noteFilter.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,7 +583,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
* enter before highlighting desktop search results.
|
* enter before highlighting desktop search results.
|
||||||
*/
|
*/
|
||||||
this.searchSubmitted = true;
|
this.searchSubmitted = true;
|
||||||
this.desktopManager.searchText(this.state.noteFilter.text);
|
this.application.getDesktopService().searchText(this.state.noteFilter.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedMenuItem() {
|
selectedMenuItem() {
|
||||||
@@ -592,8 +591,8 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
togglePrefKey(key) {
|
togglePrefKey(key) {
|
||||||
this.preferencesManager.setUserPrefValue(key, !this.state[key]);
|
this.application.getPrefsService().setUserPrefValue(key, !this.state[key]);
|
||||||
this.preferencesManager.syncUserPreferences();
|
this.application.getPrefsService().syncUserPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedSortByCreated() {
|
selectedSortByCreated() {
|
||||||
@@ -610,19 +609,19 @@ class NotesCtrl extends PureCtrl {
|
|||||||
|
|
||||||
toggleReverseSort() {
|
toggleReverseSort() {
|
||||||
this.selectedMenuItem();
|
this.selectedMenuItem();
|
||||||
this.preferencesManager.setUserPrefValue(
|
this.application.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.SortNotesReverse,
|
PrefKeys.SortNotesReverse,
|
||||||
!this.state.sortReverse
|
!this.state.sortReverse
|
||||||
);
|
);
|
||||||
this.preferencesManager.syncUserPreferences();
|
this.application.getPrefsService().syncUserPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
setSortBy(type) {
|
setSortBy(type) {
|
||||||
this.preferencesManager.setUserPrefValue(
|
this.application.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.SortNotesBy,
|
PrefKeys.SortNotesBy,
|
||||||
type
|
type
|
||||||
);
|
);
|
||||||
this.preferencesManager.syncUserPreferences();
|
this.application.getPrefsService().syncUserPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldShowTagsForNote(note) {
|
shouldShowTagsForNote(note) {
|
||||||
@@ -652,7 +651,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
* use Control modifier as well. These rules don't apply to desktop, but
|
* use Control modifier as well. These rules don't apply to desktop, but
|
||||||
* probably better to be consistent.
|
* probably better to be consistent.
|
||||||
*/
|
*/
|
||||||
this.newNoteKeyObserver = this.keyboardManager.addKeyObserver({
|
this.newNoteKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
||||||
key: 'n',
|
key: 'n',
|
||||||
modifiers: [
|
modifiers: [
|
||||||
KeyboardModifiers.Meta,
|
KeyboardModifiers.Meta,
|
||||||
@@ -664,7 +663,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.nextNoteKeyObserver = this.keyboardManager.addKeyObserver({
|
this.nextNoteKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
||||||
key: KeyboardKeys.Down,
|
key: KeyboardKeys.Down,
|
||||||
elements: [
|
elements: [
|
||||||
document.body,
|
document.body,
|
||||||
@@ -679,7 +678,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.nextNoteKeyObserver = this.keyboardManager.addKeyObserver({
|
this.nextNoteKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
||||||
key: KeyboardKeys.Up,
|
key: KeyboardKeys.Up,
|
||||||
element: document.body,
|
element: document.body,
|
||||||
onKeyDown: (event) => {
|
onKeyDown: (event) => {
|
||||||
@@ -687,7 +686,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.searchKeyObserver = this.keyboardManager.addKeyObserver({
|
this.searchKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
||||||
key: "f",
|
key: "f",
|
||||||
modifiers: [
|
modifiers: [
|
||||||
KeyboardModifiers.Meta,
|
KeyboardModifiers.Meta,
|
||||||
@@ -703,11 +702,13 @@ class NotesCtrl extends PureCtrl {
|
|||||||
|
|
||||||
export class NotesPanel {
|
export class NotesPanel {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.scope = {};
|
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controller = NotesCtrl;
|
this.controller = NotesCtrl;
|
||||||
this.controllerAs = 'self';
|
this.controllerAs = 'self';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
|
this.scope = {
|
||||||
|
application: '='
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,258 +1,16 @@
|
|||||||
import { getPlatformString } from '@/utils';
|
|
||||||
import template from '%/root.pug';
|
import template from '%/root.pug';
|
||||||
import { AppStateEvents } from '@/state';
|
|
||||||
import { ApplicationEvents } from 'snjs';
|
|
||||||
import angular from 'angular';
|
|
||||||
import {
|
|
||||||
PANEL_NAME_NOTES,
|
|
||||||
PANEL_NAME_TAGS
|
|
||||||
} from '@/controllers/constants';
|
|
||||||
import {
|
|
||||||
STRING_SESSION_EXPIRED,
|
|
||||||
STRING_DEFAULT_FILE_ERROR,
|
|
||||||
} from '@/strings';
|
|
||||||
import { PureCtrl } from './abstract/pure_ctrl';
|
|
||||||
|
|
||||||
class RootCtrl extends PureCtrl {
|
class RootCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(applicationManager) {
|
||||||
$compile,
|
this.applicationManager = applicationManager;
|
||||||
$location,
|
this.applicationManager.addApplicationChangeObserver(() => {
|
||||||
$scope,
|
this.reload();
|
||||||
$rootScope,
|
|
||||||
$timeout,
|
|
||||||
application,
|
|
||||||
appState,
|
|
||||||
desktopManager,
|
|
||||||
godService,
|
|
||||||
lockManager,
|
|
||||||
preferencesManager /** Unused below, required to load globally */,
|
|
||||||
themeManager,
|
|
||||||
statusManager,
|
|
||||||
) {
|
|
||||||
super($scope, $timeout, application, appState);
|
|
||||||
this.$location = $location;
|
|
||||||
this.$rootScope = $rootScope;
|
|
||||||
this.$compile = $compile;
|
|
||||||
this.desktopManager = desktopManager;
|
|
||||||
this.godService = godService;
|
|
||||||
this.lockManager = lockManager;
|
|
||||||
this.statusManager = statusManager;
|
|
||||||
this.themeManager = themeManager;
|
|
||||||
this.platformString = getPlatformString();
|
|
||||||
this.state = { appClass: '' };
|
|
||||||
this.loadApplication();
|
|
||||||
this.addDragDropHandlers();
|
|
||||||
this.lockScreenPuppet = {
|
|
||||||
focusInput: () => { }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadApplication() {
|
|
||||||
await this.application.prepareForLaunch({
|
|
||||||
callbacks: {
|
|
||||||
receiveChallenge: async (challenge, orchestrator) => {
|
|
||||||
this.godService.promptForChallenge(challenge, orchestrator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await this.application.launch();
|
|
||||||
}
|
|
||||||
|
|
||||||
onAppStart() {
|
|
||||||
super.onAppStart();
|
|
||||||
this.overrideComponentManagerFunctions();
|
|
||||||
this.application.componentManager.setDesktopManager(this.desktopManager);
|
|
||||||
this.setState({
|
|
||||||
ready: true,
|
|
||||||
needsUnlock: this.application.hasPasscode()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onAppLaunch() {
|
reload() {
|
||||||
super.onAppLaunch();
|
this.applications = this.applicationManager.getApplications();
|
||||||
this.setState({ needsUnlock: false });
|
|
||||||
this.handleAutoSignInFromParams();
|
|
||||||
}
|
|
||||||
|
|
||||||
onUpdateAvailable() {
|
|
||||||
this.$rootScope.$broadcast('new-update-available');
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
async onAppEvent(eventName) {
|
|
||||||
super.onAppEvent(eventName);
|
|
||||||
if (eventName === ApplicationEvents.LocalDataIncrementalLoad) {
|
|
||||||
this.updateLocalDataStatus();
|
|
||||||
} else if (eventName === ApplicationEvents.SyncStatusChanged) {
|
|
||||||
this.updateSyncStatus();
|
|
||||||
} else if (eventName === ApplicationEvents.LocalDataLoaded) {
|
|
||||||
this.updateLocalDataStatus();
|
|
||||||
} else if (eventName === ApplicationEvents.WillSync) {
|
|
||||||
if (!this.completedInitialSync) {
|
|
||||||
this.syncStatus = this.statusManager.replaceStatusWithString(
|
|
||||||
this.syncStatus,
|
|
||||||
"Syncing..."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (eventName === ApplicationEvents.CompletedSync) {
|
|
||||||
if (!this.completedInitialSync) {
|
|
||||||
this.syncStatus = this.statusManager.removeStatus(this.syncStatus);
|
|
||||||
this.completedInitialSync = true;
|
|
||||||
}
|
|
||||||
} else if (eventName === ApplicationEvents.InvalidSyncSession) {
|
|
||||||
this.showInvalidSessionAlert();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
async onAppStateEvent(eventName, data) {
|
|
||||||
if (eventName === AppStateEvents.PanelResized) {
|
|
||||||
if (data.panel === PANEL_NAME_NOTES) {
|
|
||||||
this.notesCollapsed = data.collapsed;
|
|
||||||
}
|
|
||||||
if (data.panel === PANEL_NAME_TAGS) {
|
|
||||||
this.tagsCollapsed = data.collapsed;
|
|
||||||
}
|
|
||||||
let appClass = "";
|
|
||||||
if (this.notesCollapsed) { appClass += "collapsed-notes"; }
|
|
||||||
if (this.tagsCollapsed) { appClass += " collapsed-tags"; }
|
|
||||||
this.setState({ appClass });
|
|
||||||
} else if (eventName === AppStateEvents.WindowDidFocus) {
|
|
||||||
if (!(await this.application.isLocked())) {
|
|
||||||
this.application.sync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateLocalDataStatus() {
|
|
||||||
const syncStatus = this.application.getSyncStatus();
|
|
||||||
const stats = syncStatus.getStats();
|
|
||||||
const encryption = this.application.isEncryptionAvailable();
|
|
||||||
if (stats.localDataDone) {
|
|
||||||
this.syncStatus = this.statusManager.removeStatus(this.syncStatus);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const notesString = `${stats.localDataCurrent}/${stats.localDataTotal} items...`;
|
|
||||||
const loadingStatus = encryption
|
|
||||||
? `Decrypting ${notesString}`
|
|
||||||
: `Loading ${notesString}`;
|
|
||||||
this.syncStatus = this.statusManager.replaceStatusWithString(
|
|
||||||
this.syncStatus,
|
|
||||||
loadingStatus
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSyncStatus() {
|
|
||||||
const syncStatus = this.application.getSyncStatus();
|
|
||||||
const stats = syncStatus.getStats();
|
|
||||||
if (stats.downloadCount > 20) {
|
|
||||||
const text = `Downloading ${stats.downloadCount} items. Keep app open.`;
|
|
||||||
this.syncStatus = this.statusManager.replaceStatusWithString(
|
|
||||||
this.syncStatus,
|
|
||||||
text
|
|
||||||
);
|
|
||||||
this.showingDownloadStatus = true;
|
|
||||||
} else if (this.showingDownloadStatus) {
|
|
||||||
this.showingDownloadStatus = false;
|
|
||||||
const text = "Download Complete.";
|
|
||||||
this.syncStatus = this.statusManager.replaceStatusWithString(
|
|
||||||
this.syncStatus,
|
|
||||||
text
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
|
||||||
this.syncStatus = this.statusManager.removeStatus(this.syncStatus);
|
|
||||||
}, 2000);
|
|
||||||
} else if (stats.uploadTotalCount > 20) {
|
|
||||||
this.uploadSyncStatus = this.statusManager.replaceStatusWithString(
|
|
||||||
this.uploadSyncStatus,
|
|
||||||
`Syncing ${stats.uploadCompletionCount}/${stats.uploadTotalCount} items...`
|
|
||||||
);
|
|
||||||
} else if (this.uploadSyncStatus) {
|
|
||||||
this.uploadSyncStatus = this.statusManager.removeStatus(
|
|
||||||
this.uploadSyncStatus
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
overrideComponentManagerFunctions() {
|
|
||||||
function openModalComponent(component) {
|
|
||||||
const scope = this.$rootScope.$new(true);
|
|
||||||
scope.component = component;
|
|
||||||
const el = this.$compile("<component-modal component='component' class='sk-modal'></component-modal>")(scope);
|
|
||||||
angular.element(document.body).append(el);
|
|
||||||
}
|
|
||||||
function presentPermissionsDialog(dialog) {
|
|
||||||
const scope = this.$rootScope.$new(true);
|
|
||||||
scope.permissionsString = dialog.permissionsString;
|
|
||||||
scope.component = dialog.component;
|
|
||||||
scope.callback = dialog.callback;
|
|
||||||
const el = this.$compile("<permissions-modal component='component' permissions-string='permissionsString' callback='callback' class='sk-modal'></permissions-modal>")(scope);
|
|
||||||
angular.element(document.body).append(el);
|
|
||||||
}
|
|
||||||
this.application.componentManager.openModalComponent = openModalComponent.bind(this);
|
|
||||||
this.application.componentManager.presentPermissionsDialog = presentPermissionsDialog.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
setTimeout(() => {
|
|
||||||
this.alertService.alert({
|
|
||||||
text: STRING_SESSION_EXPIRED
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addDragDropHandlers() {
|
|
||||||
/**
|
|
||||||
* Disable dragging and dropping of files (but allow text) into main SN interface.
|
|
||||||
* both 'dragover' and 'drop' are required to prevent dropping of files.
|
|
||||||
* This will not prevent extensions from receiving drop events.
|
|
||||||
*/
|
|
||||||
window.addEventListener('dragover', (event) => {
|
|
||||||
if (event.dataTransfer.files.length > 0) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
window.addEventListener('drop', (event) => {
|
|
||||||
if (event.dataTransfer.files.length > 0) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.application.alertService.alert({
|
|
||||||
text: STRING_DEFAULT_FILE_ERROR
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
async handleAutoSignInFromParams() {
|
|
||||||
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();
|
|
||||||
if (user) {
|
|
||||||
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.setHost(server);
|
|
||||||
this.application.signIn({
|
|
||||||
email: email,
|
|
||||||
password: password,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { SNNote, SNSmartTag, ContentTypes, ApplicationEvents } from 'snjs';
|
import { SNNote, SNSmartTag, ContentTypes, ApplicationEvents } from 'snjs';
|
||||||
import template from '%/tags.pug';
|
import template from '%/tags.pug';
|
||||||
import { AppStateEvents } from '@/state';
|
import { AppStateEvents } from '@/services/state';
|
||||||
import { PANEL_NAME_TAGS } from '@/controllers/constants';
|
import { PANEL_NAME_TAGS } from '@/controllers/constants';
|
||||||
import { PrefKeys } from '@/services/preferencesManager';
|
import { PrefKeys } from '@/services/preferencesManager';
|
||||||
import { STRING_DELETE_TAG } from '@/strings';
|
import { STRING_DELETE_TAG } from '@/strings';
|
||||||
@@ -9,16 +9,9 @@ import { PureCtrl } from '@Controllers';
|
|||||||
class TagsPanelCtrl extends PureCtrl {
|
class TagsPanelCtrl extends PureCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$scope,
|
|
||||||
$rootScope,
|
|
||||||
$timeout,
|
$timeout,
|
||||||
application,
|
|
||||||
appState,
|
|
||||||
preferencesManager
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.$rootScope = $rootScope;
|
|
||||||
this.preferencesManager = preferencesManager;
|
|
||||||
this.panelPuppet = {
|
this.panelPuppet = {
|
||||||
onReady: () => this.loadPreferences()
|
onReady: () => this.loadPreferences()
|
||||||
};
|
};
|
||||||
@@ -92,7 +85,7 @@ class TagsPanelCtrl extends PureCtrl {
|
|||||||
this.loadPreferences();
|
this.loadPreferences();
|
||||||
} else if (eventName === AppStateEvents.TagChanged) {
|
} else if (eventName === AppStateEvents.TagChanged) {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedTag: this.appState.getSelectedTag()
|
selectedTag: this.application.getAppState().getSelectedTag()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,11 +129,11 @@ class TagsPanelCtrl extends PureCtrl {
|
|||||||
if (!this.panelPuppet.ready) {
|
if (!this.panelPuppet.ready) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const width = this.preferencesManager.getValue(PrefKeys.TagsPanelWidth);
|
const width = this.application.getPrefsService().getValue(PrefKeys.TagsPanelWidth);
|
||||||
if (width) {
|
if (width) {
|
||||||
this.panelPuppet.setWidth(width);
|
this.panelPuppet.setWidth(width);
|
||||||
if (this.panelPuppet.isCollapsed()) {
|
if (this.panelPuppet.isCollapsed()) {
|
||||||
this.appState.panelDidResize({
|
this.application.getAppState().panelDidResize({
|
||||||
name: PANEL_NAME_TAGS,
|
name: PANEL_NAME_TAGS,
|
||||||
collapsed: this.panelPuppet.isCollapsed()
|
collapsed: this.panelPuppet.isCollapsed()
|
||||||
});
|
});
|
||||||
@@ -149,12 +142,12 @@ class TagsPanelCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onPanelResize = (newWidth, lastLeft, isAtMaxWidth, isCollapsed) => {
|
onPanelResize = (newWidth, lastLeft, isAtMaxWidth, isCollapsed) => {
|
||||||
this.preferencesManager.setUserPrefValue(
|
this.application.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.TagsPanelWidth,
|
PrefKeys.TagsPanelWidth,
|
||||||
newWidth,
|
newWidth,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
this.appState.panelDidResize({
|
this.application.getAppState().panelDidResize({
|
||||||
name: PANEL_NAME_TAGS,
|
name: PANEL_NAME_TAGS,
|
||||||
collapsed: isCollapsed
|
collapsed: isCollapsed
|
||||||
});
|
});
|
||||||
@@ -202,7 +195,7 @@ class TagsPanelCtrl extends PureCtrl {
|
|||||||
tag.content.conflict_of = null;
|
tag.content.conflict_of = null;
|
||||||
this.application.saveItem({ item: tag });
|
this.application.saveItem({ item: tag });
|
||||||
}
|
}
|
||||||
this.appState.setSelectedTag(tag);
|
this.application.getAppState().setSelectedTag(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
async clickedAddNewTag() {
|
async clickedAddNewTag() {
|
||||||
@@ -299,7 +292,9 @@ class TagsPanelCtrl extends PureCtrl {
|
|||||||
export class TagsPanel {
|
export class TagsPanel {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.restrict = 'E';
|
this.restrict = 'E';
|
||||||
this.scope = {};
|
this.scope = {
|
||||||
|
application: '='
|
||||||
|
};
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controller = TagsPanelCtrl;
|
this.controller = TagsPanelCtrl;
|
||||||
|
|||||||
@@ -3,27 +3,38 @@ export function clickOutside($document) {
|
|||||||
return {
|
return {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
replace: false,
|
replace: false,
|
||||||
link: function($scope, $element, attrs) {
|
link: function ($scope, $element, attrs) {
|
||||||
var didApplyClickOutside = false;
|
// Causes memory leak as-is:
|
||||||
|
// let didApplyClickOutside = false;
|
||||||
|
|
||||||
$element.bind('click', function(e) {
|
// $scope.$on('$destroy', () => {
|
||||||
didApplyClickOutside = false;
|
// attrs.clickOutside = null;
|
||||||
if (attrs.isOpen) {
|
// $element.unbind('click', $scope.onElementClick);
|
||||||
e.stopPropagation();
|
// $document.unbind('click', $scope.onDocumentClick);
|
||||||
}
|
// $scope.onElementClick = null;
|
||||||
});
|
// $scope.onDocumentClick = null;
|
||||||
|
// });
|
||||||
|
|
||||||
$document.bind('click', function() {
|
// $scope.onElementClick = (event) => {
|
||||||
// Ignore click if on SKAlert
|
// didApplyClickOutside = false;
|
||||||
if (event.target.closest(".sk-modal")) {
|
// if (attrs.isOpen) {
|
||||||
return;
|
// event.stopPropagation();
|
||||||
}
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// $scope.onDocumentClick = (event) => {
|
||||||
|
// /* Ignore click if on SKAlert */
|
||||||
|
// if (event.target.closest('.sk-modal')) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// if (!didApplyClickOutside) {
|
||||||
|
// $scope.$apply(attrs.clickOutside);
|
||||||
|
// didApplyClickOutside = true;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
if (!didApplyClickOutside) {
|
// $element.bind('click', $scope.onElementClick);
|
||||||
$scope.$apply(attrs.clickOutside);
|
// $document.bind('click', $scope.onDocumentClick);
|
||||||
didApplyClickOutside = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
export function infiniteScroll($rootScope, $window, $timeout) {
|
export function infiniteScroll() {
|
||||||
return {
|
return {
|
||||||
link: function(scope, elem, attrs) {
|
link: function(scope, elem, attrs) {
|
||||||
const offset = parseInt(attrs.threshold) || 0;
|
const offset = parseInt(attrs.threshold) || 0;
|
||||||
const e = elem[0];
|
const e = elem[0];
|
||||||
elem.on('scroll', function() {
|
scope.onScroll = () => {
|
||||||
if (
|
if (
|
||||||
scope.$eval(attrs.canLoad) &&
|
scope.$eval(attrs.canLoad) &&
|
||||||
e.scrollTop + e.offsetHeight >= e.scrollHeight - offset
|
e.scrollTop + e.offsetHeight >= e.scrollHeight - offset
|
||||||
) {
|
) {
|
||||||
scope.$apply(attrs.infiniteScroll);
|
scope.$apply(attrs.infiniteScroll);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
elem.on('scroll', scope.onScroll);
|
||||||
|
scope.$on('$destroy', () => {
|
||||||
|
elem.off('scroll', scope.onScroll);;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,32 +28,18 @@ const ELEMENT_NAME_AUTH_PASSWORD_CONF = 'password_conf';
|
|||||||
class AccountMenuCtrl extends PureCtrl {
|
class AccountMenuCtrl extends PureCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$scope,
|
|
||||||
$rootScope,
|
|
||||||
$timeout,
|
$timeout,
|
||||||
appVersion,
|
appVersion,
|
||||||
application,
|
|
||||||
appState,
|
|
||||||
archiveManager,
|
|
||||||
godService,
|
|
||||||
lockManager,
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.$rootScope = $rootScope;
|
|
||||||
this.appState = appState;
|
|
||||||
this.application = application;
|
|
||||||
this.archiveManager = archiveManager;
|
|
||||||
this.godService = godService;
|
|
||||||
this.lockManager = lockManager;
|
|
||||||
this.appVersion = appVersion;
|
this.appVersion = appVersion;
|
||||||
this.syncStatus = this.application.getSyncStatus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return {
|
return {
|
||||||
appVersion: 'v' + (window.electronAppVersion || this.appVersion),
|
appVersion: 'v' + (window.electronAppVersion || this.appVersion),
|
||||||
passcodeAutoLockOptions: this.lockManager.getAutoLockIntervalOptions(),
|
passcodeAutoLockOptions: this.application.getLockService().getAutoLockIntervalOptions(),
|
||||||
user: this.application.getUser(),
|
user: this.application.getUser(),
|
||||||
formData: {
|
formData: {
|
||||||
mergeLocal: true,
|
mergeLocal: true,
|
||||||
@@ -90,11 +76,12 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
this.initProps({
|
this.initProps({
|
||||||
closeFunction: this.closeFunction
|
closeFunction: this.closeFunction
|
||||||
});
|
});
|
||||||
|
this.syncStatus = this.application.getSyncStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.props.closeFunction()();
|
this.props.closeFunction();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,19 +264,19 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
|
|
||||||
openPasswordWizard() {
|
openPasswordWizard() {
|
||||||
this.close();
|
this.close();
|
||||||
this.godService.presentPasswordWizard();
|
this.application.presentPasswordWizard();
|
||||||
}
|
}
|
||||||
|
|
||||||
async openPrivilegesModal() {
|
async openPrivilegesModal() {
|
||||||
this.close();
|
this.close();
|
||||||
const run = () => {
|
const run = () => {
|
||||||
this.godService.presentPrivilegesManagementModal();
|
this.application.presentPrivilegesManagementModal();
|
||||||
};
|
};
|
||||||
const needsPrivilege = await this.application.privilegesService.actionRequiresPrivilege(
|
const needsPrivilege = await this.application.privilegesService.actionRequiresPrivilege(
|
||||||
ProtectedActions.ManagePrivileges
|
ProtectedActions.ManagePrivileges
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.godService.presentPrivilegesModal(
|
this.application.presentPrivilegesModal(
|
||||||
ProtectedActions.ManagePrivileges,
|
ProtectedActions.ManagePrivileges,
|
||||||
() => {
|
() => {
|
||||||
run();
|
run();
|
||||||
@@ -366,7 +353,7 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
ProtectedActions.ManageBackups
|
ProtectedActions.ManageBackups
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.godService.presentPrivilegesModal(
|
this.application.presentPrivilegesModal(
|
||||||
ProtectedActions.ManageBackups,
|
ProtectedActions.ManageBackups,
|
||||||
run
|
run
|
||||||
);
|
);
|
||||||
@@ -416,7 +403,7 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async downloadDataArchive() {
|
async downloadDataArchive() {
|
||||||
this.archiveManager.downloadBackup(this.state.mutable.backupEncrypted);
|
this.application.getArchiveService().downloadBackup(this.state.mutable.backupEncrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
notesAndTagsCount() {
|
notesAndTagsCount() {
|
||||||
@@ -434,7 +421,7 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async reloadAutoLockInterval() {
|
async reloadAutoLockInterval() {
|
||||||
const interval = await this.lockManager.getAutoLockInterval();
|
const interval = await this.application.getLockService().getAutoLockInterval();
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedAutoLockInterval: interval
|
selectedAutoLockInterval: interval
|
||||||
});
|
});
|
||||||
@@ -442,14 +429,14 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
|
|
||||||
async selectAutoLockInterval(interval) {
|
async selectAutoLockInterval(interval) {
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
await this.lockManager.setAutoLockInterval(interval);
|
await this.application.getLockService().setAutoLockInterval(interval);
|
||||||
this.reloadAutoLockInterval();
|
this.reloadAutoLockInterval();
|
||||||
};
|
};
|
||||||
const needsPrivilege = await this.application.privilegesService.actionRequiresPrivilege(
|
const needsPrivilege = await this.application.privilegesService.actionRequiresPrivilege(
|
||||||
ProtectedActions.ManagePasscode
|
ProtectedActions.ManagePasscode
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.godService.presentPrivilegesModal(
|
this.application.presentPrivilegesModal(
|
||||||
ProtectedActions.ManagePasscode,
|
ProtectedActions.ManagePasscode,
|
||||||
() => {
|
() => {
|
||||||
run();
|
run();
|
||||||
@@ -508,7 +495,7 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
ProtectedActions.ManagePasscode
|
ProtectedActions.ManagePasscode
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.godService.presentPrivilegesModal(
|
this.application.presentPrivilegesModal(
|
||||||
ProtectedActions.ManagePasscode,
|
ProtectedActions.ManagePasscode,
|
||||||
run
|
run
|
||||||
);
|
);
|
||||||
@@ -536,7 +523,7 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
ProtectedActions.ManagePasscode
|
ProtectedActions.ManagePasscode
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.godService.presentPrivilegesModal(
|
this.application.presentPrivilegesModal(
|
||||||
ProtectedActions.ManagePasscode,
|
ProtectedActions.ManagePasscode,
|
||||||
run
|
run
|
||||||
);
|
);
|
||||||
@@ -558,7 +545,8 @@ export class AccountMenu {
|
|||||||
this.controllerAs = 'self';
|
this.controllerAs = 'self';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
this.scope = {
|
this.scope = {
|
||||||
closeFunction: '&'
|
closeFunction: '&',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,9 @@ import { PureCtrl } from '@Controllers';
|
|||||||
class ActionsMenuCtrl extends PureCtrl {
|
class ActionsMenuCtrl extends PureCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$scope,
|
$timeout
|
||||||
$timeout,
|
|
||||||
application,
|
|
||||||
appState,
|
|
||||||
godService
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.godService = godService;
|
|
||||||
this.state = {
|
this.state = {
|
||||||
extensions: []
|
extensions: []
|
||||||
};
|
};
|
||||||
@@ -77,7 +72,7 @@ class ActionsMenuCtrl extends PureCtrl {
|
|||||||
switch (action.verb) {
|
switch (action.verb) {
|
||||||
case 'render': {
|
case 'render': {
|
||||||
const item = result.item;
|
const item = result.item;
|
||||||
this.godService.presentRevisionPreviewModal(
|
this.application.presentRevisionPreviewModal(
|
||||||
item.uuid,
|
item.uuid,
|
||||||
item.content
|
item.content
|
||||||
);
|
);
|
||||||
@@ -111,7 +106,8 @@ export class ActionsMenu {
|
|||||||
this.controllerAs = 'self';
|
this.controllerAs = 'self';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
this.scope = {
|
this.scope = {
|
||||||
item: '='
|
item: '=',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,10 @@ import { PureCtrl } from '@Controllers';
|
|||||||
class ChallengeModalCtrl extends PureCtrl {
|
class ChallengeModalCtrl extends PureCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$scope,
|
|
||||||
$element,
|
$element,
|
||||||
$timeout,
|
$timeout
|
||||||
application,
|
|
||||||
appState
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.processingTypes = [];
|
this.processingTypes = [];
|
||||||
}
|
}
|
||||||
@@ -48,6 +45,13 @@ class ChallengeModalCtrl extends PureCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.application = null;
|
||||||
|
this.orchestrator = null;
|
||||||
|
this.challenge = null;
|
||||||
|
super.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
reloadProcessingStatus() {
|
reloadProcessingStatus() {
|
||||||
this.setState({
|
this.setState({
|
||||||
processing: this.processingTypes.length > 0
|
processing: this.processingTypes.length > 0
|
||||||
@@ -106,7 +110,10 @@ class ChallengeModalCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {
|
||||||
this.$element.remove();
|
const elem = this.$element;
|
||||||
|
const scope = elem.scope();
|
||||||
|
scope.$destroy();
|
||||||
|
elem.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,11 +123,10 @@ export class ChallengeModal {
|
|||||||
this.template = template;
|
this.template = template;
|
||||||
this.controller = ChallengeModalCtrl;
|
this.controller = ChallengeModalCtrl;
|
||||||
this.controllerAs = 'ctrl';
|
this.controllerAs = 'ctrl';
|
||||||
this.bindToController = true;
|
this.bindToController = {
|
||||||
this.scope = {
|
|
||||||
onSubmit: '=',
|
|
||||||
challenge: '=',
|
challenge: '=',
|
||||||
orchestrator: '='
|
orchestrator: '=',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,19 @@ import template from '%/directives/component-modal.pug';
|
|||||||
|
|
||||||
export class ComponentModalCtrl {
|
export class ComponentModalCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor($scope, $element) {
|
constructor($element) {
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.$scope = $scope;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss(callback) {
|
dismiss(callback) {
|
||||||
this.$element.remove();
|
if(this.onDismiss) {
|
||||||
this.$scope.$destroy();
|
this.onDismiss(this.component);
|
||||||
if(this.onDismiss && this.onDismiss()) {
|
|
||||||
this.onDismiss()(this.component);
|
|
||||||
}
|
}
|
||||||
callback && callback();
|
this.callback && this.callback();
|
||||||
|
const elem = this.$element;
|
||||||
|
const scope = elem.scope();
|
||||||
|
scope.$destroy();
|
||||||
|
elem.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,26 +14,41 @@ class ComponentViewCtrl {
|
|||||||
$scope,
|
$scope,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$timeout,
|
$timeout,
|
||||||
application,
|
|
||||||
desktopManager,
|
|
||||||
themeManager
|
|
||||||
) {
|
) {
|
||||||
this.$rootScope = $rootScope;
|
this.$rootScope = $rootScope;
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.application = application;
|
|
||||||
this.themeManager = themeManager;
|
|
||||||
this.desktopManager = desktopManager;
|
|
||||||
this.componentValid = true;
|
this.componentValid = true;
|
||||||
|
this.cleanUpWatch = $scope.$watch('ctrl.component', (component, prevComponent) => {
|
||||||
$scope.$watch('ctrl.component', (component, prevComponent) => {
|
|
||||||
this.componentValueDidSet(component, prevComponent);
|
this.componentValueDidSet(component, prevComponent);
|
||||||
});
|
});
|
||||||
$scope.$on('ext-reload-complete', () => {
|
this.cleanUpOn = $scope.$on('ext-reload-complete', () => {
|
||||||
this.reloadStatus(false);
|
this.reloadStatus(false);
|
||||||
});
|
});
|
||||||
$scope.$on('$destroy', () => {
|
|
||||||
this.destroy();
|
/** To allow for registering events */
|
||||||
});
|
this.onVisibilityChange = this.onVisibilityChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
$onDestroy() {
|
||||||
|
this.cleanUpWatch();
|
||||||
|
this.cleanUpOn();
|
||||||
|
this.cleanUpWatch = null;
|
||||||
|
this.cleanUpOn = null;
|
||||||
|
this.application.componentManager.deregisterHandler(this.themeHandlerIdentifier);
|
||||||
|
this.application.componentManager.deregisterHandler(this.identifier);
|
||||||
|
if (this.component && !this.manualDealloc) {
|
||||||
|
const dontSync = true;
|
||||||
|
this.application.componentManager.deactivateComponent(this.component, dontSync);
|
||||||
|
}
|
||||||
|
this.application.getDesktopService().deregisterUpdateObserver(this.updateObserver);
|
||||||
|
document.removeEventListener(
|
||||||
|
VISIBILITY_CHANGE_LISTENER_KEY,
|
||||||
|
this.onVisibilityChange
|
||||||
|
);
|
||||||
|
this.component = null;
|
||||||
|
this.onLoad = null;
|
||||||
|
this.application = null;
|
||||||
|
this.onVisibilityChange = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
@@ -42,12 +57,12 @@ class ComponentViewCtrl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
registerPackageUpdateObserver() {
|
registerPackageUpdateObserver() {
|
||||||
this.updateObserver = this.desktopManager
|
this.updateObserver = this.application.getDesktopService()
|
||||||
.registerUpdateObserver((component) => {
|
.registerUpdateObserver((component) => {
|
||||||
if(component === this.component && component.active) {
|
if (component === this.component && component.active) {
|
||||||
this.reloadComponent();
|
this.reloadComponent();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
registerComponentHandlers() {
|
registerComponentHandlers() {
|
||||||
@@ -65,7 +80,7 @@ class ComponentViewCtrl {
|
|||||||
identifier: this.identifier,
|
identifier: this.identifier,
|
||||||
areas: [this.component.area],
|
areas: [this.component.area],
|
||||||
activationHandler: (component) => {
|
activationHandler: (component) => {
|
||||||
if(component !== this.component) {
|
if (component !== this.component) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
@@ -73,7 +88,7 @@ class ComponentViewCtrl {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
actionHandler: (component, action, data) => {
|
actionHandler: (component, action, data) => {
|
||||||
if(action === 'set-size') {
|
if (action === 'set-size') {
|
||||||
this.application.componentManager.handleSetSizeEvent(component, data);
|
this.application.componentManager.handleSetSizeEvent(component, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,10 +96,10 @@ class ComponentViewCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onVisibilityChange() {
|
onVisibilityChange() {
|
||||||
if(document.visibilityState === 'hidden') {
|
if (document.visibilityState === 'hidden') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(this.issueLoading) {
|
if (this.issueLoading) {
|
||||||
this.reloadComponent();
|
this.reloadComponent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,34 +115,34 @@ class ComponentViewCtrl {
|
|||||||
const component = this.component;
|
const component = this.component;
|
||||||
const previouslyValid = this.componentValid;
|
const previouslyValid = this.componentValid;
|
||||||
const offlineRestricted = component.offlineOnly && !isDesktopApplication();
|
const offlineRestricted = component.offlineOnly && !isDesktopApplication();
|
||||||
const hasUrlError = function(){
|
const hasUrlError = function () {
|
||||||
if(isDesktopApplication()) {
|
if (isDesktopApplication()) {
|
||||||
return !component.local_url && !component.hasValidHostedUrl();
|
return !component.local_url && !component.hasValidHostedUrl();
|
||||||
} else {
|
} else {
|
||||||
return !component.hasValidHostedUrl();
|
return !component.hasValidHostedUrl();
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
this.expired = component.valid_until && component.valid_until <= new Date();
|
this.expired = component.valid_until && component.valid_until <= new Date();
|
||||||
if(!component.lockReadonly) {
|
if (!component.lockReadonly) {
|
||||||
component.readonly = this.expired;
|
component.readonly = this.expired;
|
||||||
}
|
}
|
||||||
this.componentValid = !offlineRestricted && !hasUrlError;
|
this.componentValid = !offlineRestricted && !hasUrlError;
|
||||||
if(!this.componentValid) {
|
if (!this.componentValid) {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
if(offlineRestricted) {
|
if (offlineRestricted) {
|
||||||
this.error = 'offline-restricted';
|
this.error = 'offline-restricted';
|
||||||
} else if(hasUrlError) {
|
} else if (hasUrlError) {
|
||||||
this.error = 'url-missing';
|
this.error = 'url-missing';
|
||||||
} else {
|
} else {
|
||||||
this.error = null;
|
this.error = null;
|
||||||
}
|
}
|
||||||
if(this.componentValid !== previouslyValid) {
|
if (this.componentValid !== previouslyValid) {
|
||||||
if(this.componentValid) {
|
if (this.componentValid) {
|
||||||
this.application.componentManager.reloadComponent(component, true);
|
this.application.componentManager.reloadComponent(component, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.expired && doManualReload) {
|
if (this.expired && doManualReload) {
|
||||||
this.$rootScope.$broadcast('reload-ext-dat');
|
this.$rootScope.$broadcast('reload-ext-dat');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,17 +152,17 @@ class ComponentViewCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleActivation() {
|
handleActivation() {
|
||||||
if(!this.component.active) {
|
if (!this.component.active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const iframe = this.application.componentManager.iframeForComponent(
|
const iframe = this.application.componentManager.iframeForComponent(
|
||||||
this.component
|
this.component
|
||||||
);
|
);
|
||||||
if(!iframe) {
|
if (!iframe) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
if(this.loadTimeout) {
|
if (this.loadTimeout) {
|
||||||
this.$timeout.cancel(this.loadTimeout);
|
this.$timeout.cancel(this.loadTimeout);
|
||||||
}
|
}
|
||||||
this.loadTimeout = this.$timeout(() => {
|
this.loadTimeout = this.$timeout(() => {
|
||||||
@@ -160,16 +175,16 @@ class ComponentViewCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async handleIframeLoadTimeout() {
|
async handleIframeLoadTimeout() {
|
||||||
if(this.loading) {
|
if (this.loading) {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.issueLoading = true;
|
this.issueLoading = true;
|
||||||
if(!this.didAttemptReload) {
|
if (!this.didAttemptReload) {
|
||||||
this.didAttemptReload = true;
|
this.didAttemptReload = true;
|
||||||
this.reloadComponent();
|
this.reloadComponent();
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
VISIBILITY_CHANGE_LISTENER_KEY,
|
VISIBILITY_CHANGE_LISTENER_KEY,
|
||||||
this.onVisibilityChange.bind(this)
|
this.onVisibilityChange
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,13 +192,13 @@ class ComponentViewCtrl {
|
|||||||
|
|
||||||
async handleIframeLoad(iframe) {
|
async handleIframeLoad(iframe) {
|
||||||
let desktopError = false;
|
let desktopError = false;
|
||||||
if(isDesktopApplication()) {
|
if (isDesktopApplication()) {
|
||||||
try {
|
try {
|
||||||
/** Accessing iframe.contentWindow.origin only allowed in desktop app. */
|
/** Accessing iframe.contentWindow.origin only allowed in desktop app. */
|
||||||
if(!iframe.contentWindow.origin || iframe.contentWindow.origin === 'null') {
|
if (!iframe.contentWindow.origin || iframe.contentWindow.origin === 'null') {
|
||||||
desktopError = true;
|
desktopError = true;
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) { }
|
||||||
}
|
}
|
||||||
this.$timeout.cancel(this.loadTimeout);
|
this.$timeout.cancel(this.loadTimeout);
|
||||||
await this.application.componentManager.registerComponentWindow(
|
await this.application.componentManager.registerComponentWindow(
|
||||||
@@ -201,13 +216,13 @@ class ComponentViewCtrl {
|
|||||||
|
|
||||||
componentValueDidSet(component, prevComponent) {
|
componentValueDidSet(component, prevComponent) {
|
||||||
const dontSync = true;
|
const dontSync = true;
|
||||||
if(prevComponent && component !== prevComponent) {
|
if (prevComponent && component !== prevComponent) {
|
||||||
this.application.componentManager.deactivateComponent(
|
this.application.componentManager.deactivateComponent(
|
||||||
prevComponent,
|
prevComponent,
|
||||||
dontSync
|
dontSync
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if(component) {
|
if (component) {
|
||||||
this.application.componentManager.activateComponent(
|
this.application.componentManager.activateComponent(
|
||||||
component,
|
component,
|
||||||
dontSync
|
dontSync
|
||||||
@@ -217,7 +232,7 @@ class ComponentViewCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disableActiveTheme() {
|
disableActiveTheme() {
|
||||||
this.themeManager.deactivateAllThemes();
|
this.application.getThemeService().deactivateAllThemes();
|
||||||
}
|
}
|
||||||
|
|
||||||
getUrl() {
|
getUrl() {
|
||||||
@@ -225,21 +240,6 @@ class ComponentViewCtrl {
|
|||||||
this.component.runningLocally = (url === this.component.local_url);
|
this.component.runningLocally = (url === this.component.local_url);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
|
||||||
this.application.componentManager.deregisterHandler(this.themeHandlerIdentifier);
|
|
||||||
this.application.componentManager.deregisterHandler(this.identifier);
|
|
||||||
if(this.component && !this.manualDealloc) {
|
|
||||||
const dontSync = true;
|
|
||||||
this.application.componentManager.deactivateComponent(this.component, dontSync);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.desktopManager.deregisterUpdateObserver(this.updateObserver);
|
|
||||||
document.removeEventListener(
|
|
||||||
VISIBILITY_CHANGE_LISTENER_KEY,
|
|
||||||
this.onVisibilityChange.bind(this)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ComponentView {
|
export class ComponentView {
|
||||||
@@ -249,7 +249,8 @@ export class ComponentView {
|
|||||||
this.scope = {
|
this.scope = {
|
||||||
component: '=',
|
component: '=',
|
||||||
onLoad: '=?',
|
onLoad: '=?',
|
||||||
manualDealloc: '=?'
|
manualDealloc: '=?',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
this.controller = ComponentViewCtrl;
|
this.controller = ComponentViewCtrl;
|
||||||
this.controllerAs = 'ctrl';
|
this.controllerAs = 'ctrl';
|
||||||
|
|||||||
@@ -2,14 +2,8 @@ import template from '%/directives/conflict-resolution-modal.pug';
|
|||||||
|
|
||||||
class ConflictResolutionCtrl {
|
class ConflictResolutionCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor($element) {
|
||||||
$element,
|
|
||||||
archiveManager,
|
|
||||||
application
|
|
||||||
) {
|
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.application = application;
|
|
||||||
this.archiveManager = archiveManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
@@ -56,7 +50,7 @@ class ConflictResolutionCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export() {
|
export() {
|
||||||
this.archiveManager.downloadBackupOfItems(
|
this.application.getArchiveService().downloadBackupOfItems(
|
||||||
[this.item1, this.item2],
|
[this.item1, this.item2],
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
@@ -67,7 +61,10 @@ class ConflictResolutionCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {
|
||||||
this.$element.remove();
|
const elem = this.$element;
|
||||||
|
const scope = elem.scope();
|
||||||
|
scope.$destroy();
|
||||||
|
elem.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +78,8 @@ export class ConflictResolutionModal {
|
|||||||
this.scope = {
|
this.scope = {
|
||||||
item1: '=',
|
item1: '=',
|
||||||
item2: '=',
|
item2: '=',
|
||||||
callback: '='
|
callback: '=',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,9 @@ import { PureCtrl } from '@Controllers';
|
|||||||
class EditorMenuCtrl extends PureCtrl {
|
class EditorMenuCtrl extends PureCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$scope,
|
|
||||||
$timeout,
|
$timeout,
|
||||||
application,
|
|
||||||
appState
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.state = {
|
this.state = {
|
||||||
isDesktop: isDesktopApplication()
|
isDesktop: isDesktopApplication()
|
||||||
};
|
};
|
||||||
@@ -98,7 +95,8 @@ export class EditorMenu {
|
|||||||
this.scope = {
|
this.scope = {
|
||||||
callback: '&',
|
callback: '&',
|
||||||
selectedEditor: '=',
|
selectedEditor: '=',
|
||||||
currentItem: '='
|
currentItem: '=',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,16 @@ import template from '%/directives/input-modal.pug';
|
|||||||
class InputModalCtrl {
|
class InputModalCtrl {
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor($scope, $element) {
|
constructor($element) {
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.formData = {};
|
this.formData = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {
|
||||||
this.$element.remove();
|
const elem = this.$element;
|
||||||
this.$scope.$destroy();
|
const scope = elem.scope();
|
||||||
|
scope.$destroy();
|
||||||
|
elem.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
|
|||||||
@@ -26,13 +26,17 @@ class PanelResizerCtrl {
|
|||||||
constructor(
|
constructor(
|
||||||
$compile,
|
$compile,
|
||||||
$element,
|
$element,
|
||||||
$scope,
|
|
||||||
$timeout,
|
$timeout,
|
||||||
) {
|
) {
|
||||||
this.$compile = $compile;
|
this.$compile = $compile;
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.$scope = $scope;
|
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
|
|
||||||
|
/** To allow for registering events */
|
||||||
|
this.handleResize = this.handleResize.bind(this);
|
||||||
|
this.onMouseMove = this.onMouseMove.bind(this);
|
||||||
|
this.onMouseUp = this.onMouseUp.bind(this);
|
||||||
|
this.onMouseDown = this.onMouseDown.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
@@ -45,6 +49,19 @@ class PanelResizerCtrl {
|
|||||||
this.addMouseUpListener();
|
this.addMouseUpListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$onDestroy() {
|
||||||
|
this.onResizeFinish = null;
|
||||||
|
this.control = null;
|
||||||
|
window.removeEventListener(WINDOW_EVENT_RESIZE, this.handleResize);
|
||||||
|
document.removeEventListener(MouseEvents.Move, this.onMouseMove);
|
||||||
|
document.removeEventListener(MouseEvents.Up, this.onMouseUp);
|
||||||
|
this.resizerColumn.removeEventListener(MouseEvents.Down, this.onMouseDown);
|
||||||
|
this.handleResize = null;
|
||||||
|
this.onMouseMove = null;
|
||||||
|
this.onMouseUp = null;
|
||||||
|
this.onMouseDown = null;
|
||||||
|
}
|
||||||
|
|
||||||
configureControl() {
|
configureControl() {
|
||||||
this.control.setWidth = (value) => {
|
this.control.setWidth = (value) => {
|
||||||
this.setWidth(value, true);
|
this.setWidth(value, true);
|
||||||
@@ -96,17 +113,17 @@ class PanelResizerCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configureRightPanel() {
|
configureRightPanel() {
|
||||||
const handleResize = debounce(event => {
|
window.addEventListener(WINDOW_EVENT_RESIZE, this.handleResize);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleResize() {
|
||||||
|
debounce(() => {
|
||||||
this.reloadDefaultValues();
|
this.reloadDefaultValues();
|
||||||
this.handleWidthEvent();
|
this.handleWidthEvent();
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.finishSettingWidth();
|
this.finishSettingWidth();
|
||||||
});
|
});
|
||||||
}, 250);
|
}, 250);
|
||||||
window.addEventListener(WINDOW_EVENT_RESIZE, handleResize);
|
|
||||||
this.$scope.$on('$destroy', () => {
|
|
||||||
window.removeEventListener(WINDOW_EVENT_RESIZE, handleResize);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getParentRect() {
|
getParentRect() {
|
||||||
@@ -135,7 +152,7 @@ class PanelResizerCtrl {
|
|||||||
this.finishSettingWidth();
|
this.finishSettingWidth();
|
||||||
|
|
||||||
const newCollapseState = !preClickCollapseState;
|
const newCollapseState = !preClickCollapseState;
|
||||||
this.onResizeFinish()(
|
this.onResizeFinish(
|
||||||
this.lastWidth,
|
this.lastWidth,
|
||||||
this.lastLeft,
|
this.lastLeft,
|
||||||
this.isAtMaxWidth(),
|
this.isAtMaxWidth(),
|
||||||
@@ -146,31 +163,35 @@ class PanelResizerCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addMouseDownListener() {
|
addMouseDownListener() {
|
||||||
this.resizerColumn.addEventListener(MouseEvents.Down, (event) => {
|
this.resizerColumn.addEventListener(MouseEvents.Down, this.onMouseDown);
|
||||||
this.addInvisibleOverlay();
|
}
|
||||||
this.pressed = true;
|
|
||||||
this.lastDownX = event.clientX;
|
onMouseDown(event) {
|
||||||
this.startWidth = this.panel.scrollWidth;
|
this.addInvisibleOverlay();
|
||||||
this.startLeft = this.panel.offsetLeft;
|
this.pressed = true;
|
||||||
this.panel.classList.add(CssClasses.NoSelection);
|
this.lastDownX = event.clientX;
|
||||||
if (this.hoverable) {
|
this.startWidth = this.panel.scrollWidth;
|
||||||
this.resizerColumn.classList.add(CssClasses.Dragging);
|
this.startLeft = this.panel.offsetLeft;
|
||||||
}
|
this.panel.classList.add(CssClasses.NoSelection);
|
||||||
});
|
if (this.hoverable) {
|
||||||
|
this.resizerColumn.classList.add(CssClasses.Dragging);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addMouseMoveListener() {
|
addMouseMoveListener() {
|
||||||
document.addEventListener(MouseEvents.Move, (event) => {
|
document.addEventListener(MouseEvents.Move, this.onMouseMove);
|
||||||
if (!this.pressed) {
|
}
|
||||||
return;
|
|
||||||
}
|
onMouseMove(event) {
|
||||||
event.preventDefault();
|
if (!this.pressed) {
|
||||||
if (this.property && this.property === PanelSides.Left) {
|
return;
|
||||||
this.handleLeftEvent(event);
|
}
|
||||||
} else {
|
event.preventDefault();
|
||||||
this.handleWidthEvent(event);
|
if (this.property && this.property === PanelSides.Left) {
|
||||||
}
|
this.handleLeftEvent(event);
|
||||||
});
|
} else {
|
||||||
|
this.handleWidthEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleWidthEvent(event) {
|
handleWidthEvent(event) {
|
||||||
@@ -186,9 +207,6 @@ class PanelResizerCtrl {
|
|||||||
const deltaX = x - this.lastDownX;
|
const deltaX = x - this.lastDownX;
|
||||||
const newWidth = this.startWidth + deltaX;
|
const newWidth = this.startWidth + deltaX;
|
||||||
this.setWidth(newWidth, false);
|
this.setWidth(newWidth, false);
|
||||||
if (this.onResize()) {
|
|
||||||
this.onResize()(this.lastWidth, this.panel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLeftEvent(event) {
|
handleLeftEvent(event) {
|
||||||
@@ -216,24 +234,27 @@ class PanelResizerCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addMouseUpListener() {
|
addMouseUpListener() {
|
||||||
document.addEventListener(MouseEvents.Up, event => {
|
document.addEventListener(MouseEvents.Up, this.onMouseUp);
|
||||||
this.removeInvisibleOverlay();
|
}
|
||||||
if (this.pressed) {
|
|
||||||
this.pressed = false;
|
onMouseUp() {
|
||||||
this.resizerColumn.classList.remove(CssClasses.Dragging);
|
this.removeInvisibleOverlay();
|
||||||
this.panel.classList.remove(CssClasses.NoSelection);
|
if (!this.pressed) {
|
||||||
const isMaxWidth = this.isAtMaxWidth();
|
return;
|
||||||
if (this.onResizeFinish) {
|
}
|
||||||
this.onResizeFinish()(
|
this.pressed = false;
|
||||||
this.lastWidth,
|
this.resizerColumn.classList.remove(CssClasses.Dragging);
|
||||||
this.lastLeft,
|
this.panel.classList.remove(CssClasses.NoSelection);
|
||||||
isMaxWidth,
|
const isMaxWidth = this.isAtMaxWidth();
|
||||||
this.isCollapsed()
|
if (this.onResizeFinish) {
|
||||||
);
|
this.onResizeFinish(
|
||||||
}
|
this.lastWidth,
|
||||||
this.finishSettingWidth();
|
this.lastLeft,
|
||||||
}
|
isMaxWidth,
|
||||||
});
|
this.isCollapsed()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.finishSettingWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
isAtMaxWidth() {
|
isAtMaxWidth() {
|
||||||
@@ -301,7 +322,7 @@ class PanelResizerCtrl {
|
|||||||
if (this.overlay) {
|
if (this.overlay) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.overlay = this.$compile(`<div id='resizer-overlay'></div>`)(this.$scope);
|
this.overlay = this.$compile(`<div id='resizer-overlay'></div>`)(this);
|
||||||
angular.element(document.body).prepend(this.overlay);
|
angular.element(document.body).prepend(this.overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +357,6 @@ export class PanelResizer {
|
|||||||
hoverable: '=',
|
hoverable: '=',
|
||||||
index: '=',
|
index: '=',
|
||||||
minWidth: '=',
|
minWidth: '=',
|
||||||
onResize: '&',
|
|
||||||
onResizeFinish: '&',
|
onResizeFinish: '&',
|
||||||
panelId: '=',
|
panelId: '=',
|
||||||
property: '='
|
property: '='
|
||||||
|
|||||||
@@ -11,15 +11,11 @@ class PasswordWizardCtrl extends PureCtrl {
|
|||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$element,
|
$element,
|
||||||
$scope,
|
|
||||||
$timeout,
|
$timeout,
|
||||||
application,
|
|
||||||
appState
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.$scope = $scope;
|
|
||||||
this.registerWindowUnloadStopper();
|
this.registerWindowUnloadStopper();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,14 +34,16 @@ class PasswordWizardCtrl extends PureCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$onDestroy() {
|
||||||
|
super.$onDestroy();
|
||||||
|
window.onbeforeunload = null;
|
||||||
|
}
|
||||||
|
|
||||||
/** Confirms with user before closing tab */
|
/** Confirms with user before closing tab */
|
||||||
registerWindowUnloadStopper() {
|
registerWindowUnloadStopper() {
|
||||||
window.onbeforeunload = (e) => {
|
window.onbeforeunload = (e) => {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
this.$scope.$on("$destroy", () => {
|
|
||||||
window.onbeforeunload = null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resetContinueState() {
|
resetContinueState() {
|
||||||
@@ -190,8 +188,10 @@ class PasswordWizardCtrl extends PureCtrl {
|
|||||||
text: "Cannot close window until pending tasks are complete."
|
text: "Cannot close window until pending tasks are complete."
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.$element.remove();
|
const elem = this.$element;
|
||||||
this.$scope.$destroy();
|
const scope = elem.scope();
|
||||||
|
scope.$destroy();
|
||||||
|
elem.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,8 @@ export class PasswordWizard {
|
|||||||
this.controllerAs = 'ctrl';
|
this.controllerAs = 'ctrl';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
this.scope = {
|
this.scope = {
|
||||||
type: '='
|
type: '=',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ class PermissionsModalCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {
|
||||||
this.$element.remove();
|
const elem = this.$element;
|
||||||
|
const scope = elem.scope();
|
||||||
|
scope.$destroy();
|
||||||
|
elem.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
accept() {
|
accept() {
|
||||||
|
|||||||
@@ -4,12 +4,10 @@ class PrivilegesAuthModalCtrl {
|
|||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$element,
|
$element,
|
||||||
$timeout,
|
$timeout
|
||||||
application
|
|
||||||
) {
|
) {
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.application = application;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
@@ -83,7 +81,10 @@ class PrivilegesAuthModalCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {
|
||||||
this.$element.remove();
|
const elem = this.$element;
|
||||||
|
const scope = elem.scope();
|
||||||
|
scope.$destroy();
|
||||||
|
elem.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +98,8 @@ export class PrivilegesAuthModal {
|
|||||||
this.scope = {
|
this.scope = {
|
||||||
action: '=',
|
action: '=',
|
||||||
onSuccess: '=',
|
onSuccess: '=',
|
||||||
onCancel: '='
|
onCancel: '=',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,11 @@ import { PureCtrl } from '@Controllers';
|
|||||||
class PrivilegesManagementModalCtrl extends PureCtrl {
|
class PrivilegesManagementModalCtrl extends PureCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$scope,
|
|
||||||
$timeout,
|
$timeout,
|
||||||
$element,
|
$element
|
||||||
application,
|
|
||||||
appState
|
|
||||||
) {
|
) {
|
||||||
super($scope, $timeout, application, appState);
|
super($timeout);
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.application = application;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onAppLaunch() {
|
onAppLaunch() {
|
||||||
@@ -78,7 +74,10 @@ class PrivilegesManagementModalCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {
|
||||||
this.$element.remove();
|
const elem = this.$element;
|
||||||
|
const scope = elem.scope();
|
||||||
|
scope.$destroy();
|
||||||
|
elem.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +88,8 @@ export class PrivilegesManagementModal {
|
|||||||
this.controller = PrivilegesManagementModalCtrl;
|
this.controller = PrivilegesManagementModalCtrl;
|
||||||
this.controllerAs = 'ctrl';
|
this.controllerAs = 'ctrl';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
this.scope = {};
|
this.scope = {
|
||||||
|
application: '='
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,24 +8,21 @@ class RevisionPreviewModalCtrl {
|
|||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$element,
|
$element,
|
||||||
$scope,
|
$timeout
|
||||||
$timeout,
|
|
||||||
application
|
|
||||||
) {
|
) {
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.$scope = $scope;
|
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.application = application;
|
|
||||||
$scope.$on('$destroy', () => {
|
|
||||||
if (this.identifier) {
|
|
||||||
this.application.componentManager.deregisterHandler(this.identifier);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
this.configure();
|
this.configure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$onDestroy() {
|
||||||
|
if (this.identifier) {
|
||||||
|
this.application.componentManager.deregisterHandler(this.identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async configure() {
|
async configure() {
|
||||||
this.note = await this.application.createTemplateItem({
|
this.note = await this.application.createTemplateItem({
|
||||||
@@ -110,8 +107,10 @@ class RevisionPreviewModalCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {
|
||||||
this.$element.remove();
|
const elem = this.$element;
|
||||||
this.$scope.$destroy();
|
const scope = elem.scope();
|
||||||
|
scope.$destroy();
|
||||||
|
elem.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +123,8 @@ export class RevisionPreviewModal {
|
|||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
this.scope = {
|
this.scope = {
|
||||||
uuid: '=',
|
uuid: '=',
|
||||||
content: '='
|
content: '=',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,15 @@ import template from '%/directives/session-history-menu.pug';
|
|||||||
class SessionHistoryMenuCtrl {
|
class SessionHistoryMenuCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$timeout,
|
$timeout
|
||||||
godService,
|
|
||||||
application,
|
|
||||||
) {
|
) {
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.godService = godService;
|
|
||||||
this.application = application;
|
|
||||||
this.diskEnabled = this.application.historyManager.isDiskEnabled();
|
|
||||||
this.autoOptimize = this.application.historyManager.isAutoOptimizeEnabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
this.reloadHistory();
|
this.reloadHistory();
|
||||||
|
this.diskEnabled = this.application.historyManager.isDiskEnabled();
|
||||||
|
this.autoOptimize = this.application.historyManager.isAutoOptimizeEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadHistory() {
|
reloadHistory() {
|
||||||
@@ -27,7 +23,7 @@ class SessionHistoryMenuCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openRevision(revision) {
|
openRevision(revision) {
|
||||||
this.godService.presentRevisionPreviewModal(
|
this.application.presentRevisionPreviewModal(
|
||||||
revision.item.uuid,
|
revision.item.uuid,
|
||||||
revision.item.content
|
revision.item.content
|
||||||
);
|
);
|
||||||
@@ -110,7 +106,8 @@ export class SessionHistoryMenu {
|
|||||||
this.controllerAs = 'ctrl';
|
this.controllerAs = 'ctrl';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
this.scope = {
|
this.scope = {
|
||||||
item: '='
|
item: '=',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,18 +3,14 @@ import template from '%/directives/sync-resolution-menu.pug';
|
|||||||
class SyncResolutionMenuCtrl {
|
class SyncResolutionMenuCtrl {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$timeout,
|
$timeout
|
||||||
archiveManager,
|
|
||||||
application
|
|
||||||
) {
|
) {
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.archiveManager = archiveManager;
|
|
||||||
this.application = application;
|
|
||||||
this.status = {};
|
this.status = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadBackup(encrypted) {
|
downloadBackup(encrypted) {
|
||||||
this.archiveManager.downloadBackup(encrypted);
|
this.application.getArchiveService().downloadBackup(encrypted);
|
||||||
this.status.backupFinished = true;
|
this.status.backupFinished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +34,7 @@ class SyncResolutionMenuCtrl {
|
|||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this.closeFunction()();
|
this.closeFunction();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +47,8 @@ export class SyncResolutionMenu {
|
|||||||
this.controllerAs = 'ctrl';
|
this.controllerAs = 'ctrl';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
this.scope = {
|
this.scope = {
|
||||||
closeFunction: '&'
|
closeFunction: '&',
|
||||||
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
import { EncryptionIntents, ProtectedActions } from 'snjs';
|
import { EncryptionIntents, ProtectedActions } from 'snjs';
|
||||||
|
|
||||||
export class ArchiveManager {
|
export class ArchiveManager {
|
||||||
/* @ngInject */
|
constructor(application) {
|
||||||
constructor(lockManager, application, godService) {
|
|
||||||
this.lockManager = lockManager;
|
|
||||||
this.application = application;
|
this.application = application;
|
||||||
this.godService = godService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Public
|
|
||||||
*/
|
|
||||||
/** @public */
|
/** @public */
|
||||||
async downloadBackup(encrypted) {
|
async downloadBackup(encrypted) {
|
||||||
return this.downloadBackupOfItems(this.application.modelManager.allItems, encrypted);
|
return this.downloadBackupOfItems(this.application.modelManager.allItems, encrypted);
|
||||||
@@ -37,7 +31,7 @@ export class ArchiveManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (await this.application.privilegesService.actionRequiresPrivilege(ProtectedActions.ManageBackups)) {
|
if (await this.application.privilegesService.actionRequiresPrivilege(ProtectedActions.ManageBackups)) {
|
||||||
this.godService.presentPrivilegesModal(ProtectedActions.ManageBackups, () => {
|
this.application.presentPrivilegesModal(ProtectedActions.ManageBackups, () => {
|
||||||
run();
|
run();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -9,23 +9,25 @@ const COMPONENT_CONTENT_KEY_PACKAGE_INFO = 'package_info';
|
|||||||
const COMPONENT_CONTENT_KEY_LOCAL_URL = 'local_url';
|
const COMPONENT_CONTENT_KEY_LOCAL_URL = 'local_url';
|
||||||
|
|
||||||
export class DesktopManager extends ApplicationService {
|
export class DesktopManager extends ApplicationService {
|
||||||
/* @ngInject */
|
|
||||||
constructor(
|
constructor(
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$timeout,
|
$timeout,
|
||||||
application,
|
application
|
||||||
appState,
|
|
||||||
) {
|
) {
|
||||||
super(application);
|
super(application);
|
||||||
this.$rootScope = $rootScope;
|
this.$rootScope = $rootScope;
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.appState = appState;
|
|
||||||
this.application = application;
|
|
||||||
this.componentActivationObservers = [];
|
this.componentActivationObservers = [];
|
||||||
this.updateObservers = [];
|
this.updateObservers = [];
|
||||||
this.isDesktop = isDesktopApplication();
|
this.isDesktop = isDesktopApplication();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.componentActivationObservers.length = 0;
|
||||||
|
this.updateObservers.length = 0;
|
||||||
|
super.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
onAppEvent(eventName) {
|
onAppEvent(eventName) {
|
||||||
super.onAppEvent(eventName);
|
super.onAppEvent(eventName);
|
||||||
@@ -177,7 +179,7 @@ export class DesktopManager extends ApplicationService {
|
|||||||
/* Used to resolve 'sn://' */
|
/* Used to resolve 'sn://' */
|
||||||
desktop_setExtServerHost(host) {
|
desktop_setExtServerHost(host) {
|
||||||
this.extServerHost = host;
|
this.extServerHost = host;
|
||||||
this.appState.desktopExtensionsReady();
|
this.application.getAppState().desktopExtensionsReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
desktop_setComponentInstallationSyncHandler(handler) {
|
desktop_setComponentInstallationSyncHandler(handler) {
|
||||||
@@ -207,11 +209,11 @@ export class DesktopManager extends ApplicationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
desktop_didBeginBackup() {
|
desktop_didBeginBackup() {
|
||||||
this.appState.beganBackupDownload();
|
this.application.getAppState().beganBackupDownload();
|
||||||
}
|
}
|
||||||
|
|
||||||
desktop_didFinishBackup(success) {
|
desktop_didFinishBackup(success) {
|
||||||
this.appState.endedBackupDownload({
|
this.application.getAppState().endedBackupDownload({
|
||||||
success: success
|
success: success
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,114 +0,0 @@
|
|||||||
import angular from 'angular';
|
|
||||||
|
|
||||||
export class GodService {
|
|
||||||
/* @ngInject */
|
|
||||||
constructor(
|
|
||||||
$rootScope,
|
|
||||||
$compile,
|
|
||||||
application
|
|
||||||
) {
|
|
||||||
this.$rootScope = $rootScope;
|
|
||||||
this.$compile = $compile;
|
|
||||||
this.application = application;
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkForSecurityUpdate() {
|
|
||||||
return this.application.protocolUpgradeAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
presentPasswordWizard(type) {
|
|
||||||
const scope = this.$rootScope.$new(true);
|
|
||||||
scope.type = type;
|
|
||||||
const el = this.$compile("<password-wizard type='type'></password-wizard>")(scope);
|
|
||||||
angular.element(document.body).append(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
promptForChallenge(challenge, orchestrator) {
|
|
||||||
const scope = this.$rootScope.$new(true);
|
|
||||||
scope.challenge = challenge;
|
|
||||||
scope.orchestrator = orchestrator;
|
|
||||||
const el = this.$compile(
|
|
||||||
"<challenge-modal " +
|
|
||||||
"class='sk-modal' challenge='challenge' orchestrator='orchestrator'>" +
|
|
||||||
"</challenge-modal>"
|
|
||||||
)(scope);
|
|
||||||
angular.element(document.body).append(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
async performProtocolUpgrade() {
|
|
||||||
const errors = await this.application.upgradeProtocolVersion();
|
|
||||||
if (errors.length === 0) {
|
|
||||||
this.application.alertService.alert({
|
|
||||||
text: "Success! Your encryption version has been upgraded." +
|
|
||||||
" You'll be asked to enter your credentials again on other devices you're signed into."
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.application.alertService.alert({
|
|
||||||
text: "Unable to upgrade encryption version. Please try again."
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async presentPrivilegesModal(action, onSuccess, onCancel) {
|
|
||||||
if (this.authenticationInProgress()) {
|
|
||||||
onCancel && onCancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const customSuccess = async () => {
|
|
||||||
onSuccess && await onSuccess();
|
|
||||||
this.currentAuthenticationElement = null;
|
|
||||||
};
|
|
||||||
const customCancel = async () => {
|
|
||||||
onCancel && await onCancel();
|
|
||||||
this.currentAuthenticationElement = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const scope = this.$rootScope.$new(true);
|
|
||||||
scope.action = action;
|
|
||||||
scope.onSuccess = customSuccess;
|
|
||||||
scope.onCancel = customCancel;
|
|
||||||
const el = this.$compile(`
|
|
||||||
<privileges-auth-modal action='action' on-success='onSuccess'
|
|
||||||
on-cancel='onCancel' class='sk-modal'></privileges-auth-modal>
|
|
||||||
`)(scope);
|
|
||||||
angular.element(document.body).append(el);
|
|
||||||
|
|
||||||
this.currentAuthenticationElement = el;
|
|
||||||
}
|
|
||||||
|
|
||||||
presentPrivilegesManagementModal() {
|
|
||||||
var scope = this.$rootScope.$new(true);
|
|
||||||
var el = this.$compile("<privileges-management-modal class='sk-modal'></privileges-management-modal>")(scope);
|
|
||||||
angular.element(document.body).append(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
authenticationInProgress() {
|
|
||||||
return this.currentAuthenticationElement != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
presentPasswordModal(callback) {
|
|
||||||
const scope = this.$rootScope.$new(true);
|
|
||||||
scope.type = "password";
|
|
||||||
scope.title = "Decryption Assistance";
|
|
||||||
scope.message = `Unable to decrypt this item with your current keys.
|
|
||||||
Please enter your account password at the time of this revision.`;
|
|
||||||
scope.callback = callback;
|
|
||||||
const el = this.$compile(
|
|
||||||
`<input-modal type='type' message='message'
|
|
||||||
title='title' callback='callback'></input-modal>`
|
|
||||||
)(scope);
|
|
||||||
angular.element(document.body).append(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
presentRevisionPreviewModal(uuid, content) {
|
|
||||||
const scope = this.$rootScope.$new(true);
|
|
||||||
scope.uuid = uuid;
|
|
||||||
scope.content = content;
|
|
||||||
const el = this.$compile(
|
|
||||||
`<revision-preview-modal uuid='uuid' content='content'
|
|
||||||
class='sk-modal'></revision-preview-modal>`
|
|
||||||
)(scope);
|
|
||||||
angular.element(document.body).append(el);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
export { AlertService } from './alertService';
|
export { AlertService } from './alertService';
|
||||||
export { ArchiveManager } from './archiveManager';
|
export { ArchiveManager } from './archiveManager';
|
||||||
export { DesktopManager } from './desktopManager';
|
export { DesktopManager } from './desktopManager';
|
||||||
export { GodService } from './godService';
|
|
||||||
export { KeyboardManager } from './keyboardManager';
|
export { KeyboardManager } from './keyboardManager';
|
||||||
export { LockManager } from './lockManager';
|
export { LockManager } from './lockManager';
|
||||||
export { NativeExtManager } from './nativeExtManager';
|
export { NativeExtManager } from './nativeExtManager';
|
||||||
export { PreferencesManager } from './preferencesManager';
|
export { PreferencesManager } from './preferencesManager';
|
||||||
export { StatusManager } from './statusManager';
|
export { StatusManager } from './statusManager';
|
||||||
export { ThemeManager } from './themeManager';
|
export { ThemeManager } from './themeManager';
|
||||||
|
export { AppState } from './state';
|
||||||
|
|||||||
@@ -22,8 +22,19 @@ const KeyboardKeyEvents = {
|
|||||||
export class KeyboardManager {
|
export class KeyboardManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.observers = [];
|
this.observers = [];
|
||||||
window.addEventListener('keydown', this.handleKeyDown.bind(this));
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||||
window.addEventListener('keyup', this.handleKeyUp.bind(this));
|
this.handleKeyUp = this.handleKeyUp.bind(this);
|
||||||
|
window.addEventListener('keydown', this.handleKeyDown);
|
||||||
|
window.addEventListener('keyup', this.handleKeyUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @access public */
|
||||||
|
deinit() {
|
||||||
|
this.observers.length = 0;
|
||||||
|
window.removeEventListener('keydown', this.handleKeyDown);
|
||||||
|
window.removeEventListener('keyup', this.handleKeyUp);
|
||||||
|
this.handleKeyDown = null;
|
||||||
|
this.handleKeyUp = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifiersForEvent(event) {
|
modifiersForEvent(event) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import { AppStateEvents } from '../state';
|
import { AppStateEvents } from '@/services/state';
|
||||||
|
|
||||||
const MILLISECONDS_PER_SECOND = 1000;
|
const MILLISECONDS_PER_SECOND = 1000;
|
||||||
const FOCUS_POLL_INTERVAL = 1 * MILLISECONDS_PER_SECOND;
|
const FOCUS_POLL_INTERVAL = 1 * MILLISECONDS_PER_SECOND;
|
||||||
@@ -12,16 +12,15 @@ const LOCK_INTERVAL_ONE_HOUR= 3600 * MILLISECONDS_PER_SECOND;
|
|||||||
const STORAGE_KEY_AUTOLOCK_INTERVAL = "AutoLockIntervalKey";
|
const STORAGE_KEY_AUTOLOCK_INTERVAL = "AutoLockIntervalKey";
|
||||||
|
|
||||||
export class LockManager {
|
export class LockManager {
|
||||||
/* @ngInject */
|
constructor(application) {
|
||||||
constructor($rootScope, application, appState) {
|
|
||||||
this.$rootScope = $rootScope;
|
|
||||||
this.application = application;
|
this.application = application;
|
||||||
this.appState = appState;
|
setImmediate(() => {
|
||||||
this.observeVisibility();
|
this.observeVisibility();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
observeVisibility() {
|
observeVisibility() {
|
||||||
this.appState.addObserver((eventName, data) => {
|
this.unsubState = this.application.getAppState().addObserver((eventName) => {
|
||||||
if(eventName === AppStateEvents.WindowDidBlur) {
|
if(eventName === AppStateEvents.WindowDidBlur) {
|
||||||
this.documentVisibilityChanged(false);
|
this.documentVisibilityChanged(false);
|
||||||
} else if(eventName === AppStateEvents.WindowDidFocus) {
|
} else if(eventName === AppStateEvents.WindowDidFocus) {
|
||||||
@@ -33,6 +32,13 @@ export class LockManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.unsubState();
|
||||||
|
if (this.pollFocusInterval) {
|
||||||
|
clearInterval(this.pollFocusInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async setAutoLockInterval(interval) {
|
async setAutoLockInterval(interval) {
|
||||||
return this.application.setValue(STORAGE_KEY_AUTOLOCK_INTERVAL, interval);
|
return this.application.setValue(STORAGE_KEY_AUTOLOCK_INTERVAL, interval);
|
||||||
}
|
}
|
||||||
@@ -53,7 +59,7 @@ export class LockManager {
|
|||||||
* not triggered on a typical window blur event but rather on tab changes.
|
* not triggered on a typical window blur event but rather on tab changes.
|
||||||
*/
|
*/
|
||||||
beginWebFocusPolling() {
|
beginWebFocusPolling() {
|
||||||
this.pollFocusTimeout = setInterval(() => {
|
this.pollFocusInterval = setInterval(() => {
|
||||||
const hasFocus = document.hasFocus();
|
const hasFocus = document.hasFocus();
|
||||||
if(hasFocus && this.lastFocusState === 'hidden') {
|
if(hasFocus && this.lastFocusState === 'hidden') {
|
||||||
this.documentVisibilityChanged(true);
|
this.documentVisibilityChanged(true);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ export class NativeExtManager extends ApplicationService {
|
|||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(application) {
|
constructor(application) {
|
||||||
super(application);
|
super(application);
|
||||||
this.application = application;
|
|
||||||
this.extManagerId = 'org.standardnotes.extensions-manager';
|
this.extManagerId = 'org.standardnotes.extensions-manager';
|
||||||
this.batchManagerId = 'org.standardnotes.batch-manager';
|
this.batchManagerId = 'org.standardnotes.batch-manager';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
ApplicationEvents,
|
|
||||||
SNPredicate,
|
SNPredicate,
|
||||||
ContentTypes,
|
ContentTypes,
|
||||||
CreateMaxPayloadFromAnyObject,
|
CreateMaxPayloadFromAnyObject,
|
||||||
@@ -24,15 +23,7 @@ export const PrefKeys = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class PreferencesManager extends ApplicationService {
|
export class PreferencesManager extends ApplicationService {
|
||||||
/* @ngInject */
|
|
||||||
constructor(
|
|
||||||
appState,
|
|
||||||
application
|
|
||||||
) {
|
|
||||||
super(application);
|
|
||||||
this.appState = appState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
onAppLaunch() {
|
onAppLaunch() {
|
||||||
super.onAppLaunch();
|
super.onAppLaunch();
|
||||||
@@ -65,7 +56,7 @@ export class PreferencesManager extends ApplicationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
preferencesDidChange() {
|
preferencesDidChange() {
|
||||||
this.appState.setUserPreferences(this.userPreferences);
|
this.application.getAppState().setUserPreferences(this.userPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
syncUserPreferences() {
|
syncUserPreferences() {
|
||||||
|
|||||||
@@ -23,21 +23,33 @@ export const EventSources = {
|
|||||||
export class AppState {
|
export class AppState {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$timeout,
|
|
||||||
$rootScope,
|
$rootScope,
|
||||||
application,
|
$timeout,
|
||||||
godService
|
application
|
||||||
) {
|
) {
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.$rootScope = $rootScope;
|
this.$rootScope = $rootScope;
|
||||||
this.application = application;
|
this.application = application;
|
||||||
this.godService = godService;
|
|
||||||
this.observers = [];
|
this.observers = [];
|
||||||
this.locked = true;
|
this.locked = true;
|
||||||
this.registerVisibilityObservers();
|
this.registerVisibilityObservers();
|
||||||
this.addAppEventObserver();
|
this.addAppEventObserver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.unsubApp();
|
||||||
|
this.unsubApp = null;
|
||||||
|
this.observers.length = 0;
|
||||||
|
if(this.rootScopeCleanup1) {
|
||||||
|
this.rootScopeCleanup1();
|
||||||
|
this.rootScopeCleanup2();
|
||||||
|
this.rootScopeCleanup1 = null;
|
||||||
|
this.rootScopeCleanup2 = null;
|
||||||
|
}
|
||||||
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
||||||
|
this.onVisibilityChange = null;
|
||||||
|
}
|
||||||
|
|
||||||
addAppEventObserver() {
|
addAppEventObserver() {
|
||||||
this.unsubApp = this.application.addEventObserver(async (eventName) => {
|
this.unsubApp = this.application.addEventObserver(async (eventName) => {
|
||||||
if (eventName === ApplicationEvents.Started) {
|
if (eventName === ApplicationEvents.Started) {
|
||||||
@@ -54,23 +66,26 @@ export class AppState {
|
|||||||
|
|
||||||
registerVisibilityObservers() {
|
registerVisibilityObservers() {
|
||||||
if (isDesktopApplication()) {
|
if (isDesktopApplication()) {
|
||||||
this.$rootScope.$on('window-lost-focus', () => {
|
this.rootScopeCleanup1 = this.$rootScope.$on('window-lost-focus', () => {
|
||||||
this.notifyEvent(AppStateEvents.WindowDidBlur);
|
this.notifyEvent(AppStateEvents.WindowDidBlur);
|
||||||
});
|
});
|
||||||
this.$rootScope.$on('window-gained-focus', () => {
|
this.rootScopeCleanup2 = this.$rootScope.$on('window-gained-focus', () => {
|
||||||
this.notifyEvent(AppStateEvents.WindowDidFocus);
|
this.notifyEvent(AppStateEvents.WindowDidFocus);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
/* Tab visibility listener, web only */
|
/* Tab visibility listener, web only */
|
||||||
document.addEventListener('visibilitychange', (e) => {
|
this.onVisibilityChange = this.onVisibilityChange.bind(this);
|
||||||
const visible = document.visibilityState === "visible";
|
document.addEventListener('visibilitychange', this.onVisibilityChange);
|
||||||
const event = visible
|
|
||||||
? AppStateEvents.WindowDidFocus
|
|
||||||
: AppStateEvents.WindowDidBlur;
|
|
||||||
this.notifyEvent(event);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onVisibilityChange() {
|
||||||
|
const visible = document.visibilityState === "visible";
|
||||||
|
const event = visible
|
||||||
|
? AppStateEvents.WindowDidFocus
|
||||||
|
: AppStateEvents.WindowDidBlur;
|
||||||
|
this.notifyEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
/** @returns A function that unregisters this observer */
|
/** @returns A function that unregisters this observer */
|
||||||
addObserver(callback) {
|
addObserver(callback) {
|
||||||
@@ -120,10 +135,10 @@ export class AppState {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
if (note && note.content.protected &&
|
if (note && note.content.protected &&
|
||||||
await this.application.privilegesService.actionRequiresPrivilege(
|
await this.application.application.privilegesService.actionRequiresPrivilege(
|
||||||
ProtectedActions.ViewProtectedNotes
|
ProtectedActions.ViewProtectedNotes
|
||||||
)) {
|
)) {
|
||||||
this.godService.presentPrivilegesModal(
|
this.application.presentPrivilegesModal(
|
||||||
ProtectedActions.ViewProtectedNotes,
|
ProtectedActions.ViewProtectedNotes,
|
||||||
run
|
run
|
||||||
);
|
);
|
||||||
@@ -5,33 +5,35 @@ import {
|
|||||||
EncryptionIntents,
|
EncryptionIntents,
|
||||||
ApplicationService,
|
ApplicationService,
|
||||||
} from 'snjs';
|
} from 'snjs';
|
||||||
import { AppStateEvents } from '@/state';
|
import { AppStateEvents } from '@/services/state';
|
||||||
|
|
||||||
const CACHED_THEMES_KEY = 'cachedThemes';
|
const CACHED_THEMES_KEY = 'cachedThemes';
|
||||||
|
|
||||||
export class ThemeManager extends ApplicationService {
|
export class ThemeManager extends ApplicationService {
|
||||||
/* @ngInject */
|
constructor(application) {
|
||||||
constructor(
|
|
||||||
application,
|
|
||||||
appState,
|
|
||||||
desktopManager,
|
|
||||||
) {
|
|
||||||
super(application);
|
super(application);
|
||||||
this.appState = appState;
|
|
||||||
this.desktopManager = desktopManager;
|
|
||||||
this.activeThemes = [];
|
this.activeThemes = [];
|
||||||
this.unsubState = appState.addObserver((eventName, data) => {
|
setImmediate(() => {
|
||||||
if (eventName === AppStateEvents.DesktopExtsReady) {
|
this.unsubState = this.application.getAppState().addObserver((eventName, data) => {
|
||||||
this.activateCachedThemes();
|
if (eventName === AppStateEvents.DesktopExtsReady) {
|
||||||
}
|
this.activateCachedThemes();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.unsubState();
|
||||||
|
this.unsubState = null;
|
||||||
|
this.activeThemes.length = 0;
|
||||||
|
super.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
onAppStart() {
|
onAppStart() {
|
||||||
super.onAppStart();
|
super.onAppStart();
|
||||||
this.registerObservers();
|
this.registerObservers();
|
||||||
if (!this.desktopManager.isDesktop) {
|
if (!this.application.getDesktopService().isDesktop) {
|
||||||
this.activateCachedThemes();
|
this.activateCachedThemes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,7 +54,7 @@ export class ThemeManager extends ApplicationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerObservers() {
|
registerObservers() {
|
||||||
this.desktopManager.registerUpdateObserver((component) => {
|
this.application.getDesktopService().registerUpdateObserver((component) => {
|
||||||
if (component.active && component.isTheme()) {
|
if (component.active && component.isTheme()) {
|
||||||
this.deactivateTheme(component);
|
this.deactivateTheme(component);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export const STRING_E2E_ENABLED = "End-to-end encryption is enabled. Your data i
|
|||||||
export const STRING_LOCAL_ENC_ENABLED = "Encryption is enabled. Your data is encrypted using your passcode before it is saved to your device storage.";
|
export const STRING_LOCAL_ENC_ENABLED = "Encryption is enabled. Your data is encrypted using your passcode before it is saved to your device storage.";
|
||||||
export const STRING_ENC_NOT_ENABLED = "Encryption is not enabled. Sign in, register, or add a passcode lock to enable encryption.";
|
export const STRING_ENC_NOT_ENABLED = "Encryption is not enabled. Sign in, register, or add a passcode lock to enable encryption.";
|
||||||
export const STRING_IMPORT_SUCCESS = "Your data has been successfully imported.";
|
export const STRING_IMPORT_SUCCESS = "Your data has been successfully imported.";
|
||||||
export const STRING_REMOVE_PASSCODE_CONFIRMATION = "Are you sure you want to remove your local passcode?";
|
export const STRING_REMOVE_PASSCODE_CONFIRMATION = "Are you sure you want to remove your application passcode?";
|
||||||
export const STRING_REMOVE_PASSCODE_OFFLINE_ADDENDUM = " This will remove encryption from your local data.";
|
export const STRING_REMOVE_PASSCODE_OFFLINE_ADDENDUM = " This will remove encryption from your local data.";
|
||||||
export const STRING_NON_MATCHING_PASSCODES = "The two passcodes you entered do not match. Please try again.";
|
export const STRING_NON_MATCHING_PASSCODES = "The two passcodes you entered do not match. Please try again.";
|
||||||
export const STRING_NON_MATCHING_PASSWORDS = "The two passwords you entered do not match. Please try again.";
|
export const STRING_NON_MATCHING_PASSWORDS = "The two passwords you entered do not match. Please try again.";
|
||||||
|
|||||||
15
app/assets/templates/application-view.pug
Normal file
15
app/assets/templates/application-view.pug
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
.main-ui-view(
|
||||||
|
ng-class='self.platformString'
|
||||||
|
)
|
||||||
|
#app.app(
|
||||||
|
ng-class='self.state.appClass',
|
||||||
|
ng-if='!self.state.needsUnlock && self.state.ready'
|
||||||
|
)
|
||||||
|
tags-panel(application='self.application')
|
||||||
|
notes-panel(application='self.application')
|
||||||
|
editor-panel(application='self.application')
|
||||||
|
|
||||||
|
footer(
|
||||||
|
ng-if='!self.state.needsUnlock && self.state.ready'
|
||||||
|
application='self.application'
|
||||||
|
)
|
||||||
@@ -11,5 +11,6 @@
|
|||||||
| {{ctrl.component.name}}
|
| {{ctrl.component.name}}
|
||||||
a.sk-a.info.close-button(ng-click="ctrl.dismiss()") Close
|
a.sk-a.info.close-button(ng-click="ctrl.dismiss()") Close
|
||||||
component-view.component-view(
|
component-view.component-view(
|
||||||
component="ctrl.component"
|
component="ctrl.component",
|
||||||
|
application='self.application'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -46,6 +46,6 @@
|
|||||||
| an unlocked application, but do not affect data encryption state.
|
| an unlocked application, but do not affect data encryption state.
|
||||||
p.sk-p
|
p.sk-p
|
||||||
| Privileges sync across your other devices; however, note that if you
|
| Privileges sync across your other devices; however, note that if you
|
||||||
| require a "Local Passcode" privilege, and another device does not have
|
| require an "Application Passcode" privilege, and another device does not have
|
||||||
| a local passcode set up, the local passcode requirement will be ignored
|
| an application passcode set up, the application passcode requirement will be ignored
|
||||||
| on that device.
|
| on that device.
|
||||||
|
|||||||
@@ -23,5 +23,6 @@
|
|||||||
) {{ctrl.content.text}}
|
) {{ctrl.content.text}}
|
||||||
component-view.component-view(
|
component-view.component-view(
|
||||||
component="ctrl.editor"
|
component="ctrl.editor"
|
||||||
ng-if="ctrl.editor"
|
ng-if="ctrl.editor",
|
||||||
|
application='self.application'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -165,7 +165,8 @@
|
|||||||
callback='self.editorMenuOnSelect',
|
callback='self.editorMenuOnSelect',
|
||||||
current-item='self.state.note',
|
current-item='self.state.note',
|
||||||
ng-if='self.state.showEditorMenu',
|
ng-if='self.state.showEditorMenu',
|
||||||
selected-editor='self.state.selectedEditor'
|
selected-editor='self.state.selectedEditor',
|
||||||
|
application='self.application'
|
||||||
)
|
)
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
click-outside=`self.setMenuState('showExtensions', false)`,
|
click-outside=`self.setMenuState('showExtensions', false)`,
|
||||||
@@ -176,7 +177,8 @@
|
|||||||
.sk-label Actions
|
.sk-label Actions
|
||||||
actions-menu(
|
actions-menu(
|
||||||
item='self.state.note',
|
item='self.state.note',
|
||||||
ng-if='self.state.showExtensions'
|
ng-if='self.state.showExtensions',
|
||||||
|
application='self.application'
|
||||||
)
|
)
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
click-outside=`self.setMenuState('showSessionHistory', false)`,
|
click-outside=`self.setMenuState('showSessionHistory', false)`,
|
||||||
@@ -186,7 +188,8 @@
|
|||||||
.sk-label Session History
|
.sk-label Session History
|
||||||
session-history-menu(
|
session-history-menu(
|
||||||
item='self.state.note',
|
item='self.state.note',
|
||||||
ng-if='self.state.showSessionHistory'
|
ng-if='self.state.showSessionHistory',
|
||||||
|
application='self.application'
|
||||||
)
|
)
|
||||||
#editor-content.editor-content(
|
#editor-content.editor-content(
|
||||||
ng-if='self.state.noteReady && !self.state.note.errorDecrypting'
|
ng-if='self.state.noteReady && !self.state.note.errorDecrypting'
|
||||||
@@ -196,14 +199,15 @@
|
|||||||
hoverable='true',
|
hoverable='true',
|
||||||
min-width='300',
|
min-width='300',
|
||||||
ng-if='self.state.marginResizersEnabled',
|
ng-if='self.state.marginResizersEnabled',
|
||||||
on-resize-finish='self.onPanelResizeFinish',
|
on-resize-finish='self.onPanelResizeFinish()',
|
||||||
panel-id="'editor-content'",
|
panel-id="'editor-content'",
|
||||||
property="'left'"
|
property="'left'"
|
||||||
)
|
)
|
||||||
component-view.component-view(
|
component-view.component-view(
|
||||||
component='self.state.selectedEditor',
|
component='self.state.selectedEditor',
|
||||||
ng-if='self.state.selectedEditor',
|
ng-if='self.state.selectedEditor',
|
||||||
on-load='self.onEditorLoad'
|
on-load='self.onEditorLoad',
|
||||||
|
application='self.application'
|
||||||
)
|
)
|
||||||
textarea#note-text-editor.editable(
|
textarea#note-text-editor.editable(
|
||||||
dir='auto',
|
dir='auto',
|
||||||
@@ -222,7 +226,7 @@
|
|||||||
control='self.rightPanelPuppet',
|
control='self.rightPanelPuppet',
|
||||||
hoverable='true', min-width='300',
|
hoverable='true', min-width='300',
|
||||||
ng-if='self.state.marginResizersEnabled',
|
ng-if='self.state.marginResizersEnabled',
|
||||||
on-resize-finish='self.onPanelResizeFinish',
|
on-resize-finish='self.onPanelResizeFinish()',
|
||||||
panel-id="'editor-content'",
|
panel-id="'editor-content'",
|
||||||
property="'right'"
|
property="'right'"
|
||||||
)
|
)
|
||||||
@@ -249,5 +253,6 @@
|
|||||||
manual-dealloc='true',
|
manual-dealloc='true',
|
||||||
ng-if='component.active',
|
ng-if='component.active',
|
||||||
ng-repeat='component in self.state.componentStack',
|
ng-repeat='component in self.state.componentStack',
|
||||||
ng-show='!component.hidden'
|
ng-show='!component.hidden',
|
||||||
|
application='self.application'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#footer-bar.sk-app-bar.no-edges.no-bottom-edge
|
#footer-bar.sk-app-bar.no-edges.no-bottom-edge
|
||||||
.left
|
.left
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
click-outside='ctrl.clickOutsideAccountMenu()',
|
click-outside='ctrl.clickOutsideAccountMenu()',
|
||||||
is-open='ctrl.showAccountMenu',
|
is-open='ctrl.showAccountMenu',
|
||||||
ng-click='ctrl.accountMenuPressed()'
|
ng-click='ctrl.accountMenuPressed()'
|
||||||
)
|
)
|
||||||
@@ -13,9 +13,10 @@
|
|||||||
.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.error}') Account
|
||||||
account-menu(
|
account-menu(
|
||||||
close-function='ctrl.closeAccountMenu',
|
close-function='ctrl.closeAccountMenu()',
|
||||||
ng-click='$event.stopPropagation()',
|
ng-click='$event.stopPropagation()',
|
||||||
ng-if='ctrl.showAccountMenu',
|
ng-if='ctrl.showAccountMenu',
|
||||||
|
application='ctrl.application'
|
||||||
)
|
)
|
||||||
.sk-app-bar-item
|
.sk-app-bar-item
|
||||||
a.no-decoration.sk-label.title(
|
a.no-decoration.sk-label.title(
|
||||||
@@ -31,21 +32,22 @@
|
|||||||
component-modal(
|
component-modal(
|
||||||
component='room',
|
component='room',
|
||||||
ng-if='room.showRoom',
|
ng-if='room.showRoom',
|
||||||
on-dismiss='ctrl.onRoomDismiss'
|
on-dismiss='ctrl.onRoomDismiss()',
|
||||||
|
application='self.application'
|
||||||
)
|
)
|
||||||
.center
|
.center
|
||||||
.sk-app-bar-item(ng-show='ctrl.arbitraryStatusMessage')
|
.sk-app-bar-item(ng-if='ctrl.arbitraryStatusMessage')
|
||||||
.sk-app-bar-item-column
|
.sk-app-bar-item-column
|
||||||
span.neutral.sk-label {{ctrl.arbitraryStatusMessage}}
|
span.neutral.sk-label {{ctrl.arbitraryStatusMessage}}
|
||||||
.right
|
.right
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
ng-click='ctrl.openSecurityUpdate()',
|
ng-click='ctrl.openSecurityUpdate()',
|
||||||
ng-show='ctrl.state.dataUpgradeAvailable'
|
ng-if='ctrl.state.dataUpgradeAvailable'
|
||||||
)
|
)
|
||||||
span.success.sk-label Encryption upgrade available.
|
span.success.sk-label Encryption upgrade available.
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
ng-click='ctrl.clickedNewUpdateAnnouncement()',
|
ng-click='ctrl.clickedNewUpdateAnnouncement()',
|
||||||
ng-show='ctrl.newUpdateAvailable == true'
|
ng-if='ctrl.newUpdateAvailable == true'
|
||||||
)
|
)
|
||||||
span.info.sk-label New update available.
|
span.info.sk-label New update available.
|
||||||
.sk-app-bar-item.no-pointer(
|
.sk-app-bar-item.no-pointer(
|
||||||
@@ -59,9 +61,10 @@
|
|||||||
)
|
)
|
||||||
.sk-label.warning(ng-if='ctrl.state.outOfSync') Potentially Out of Sync
|
.sk-label.warning(ng-if='ctrl.state.outOfSync') Potentially Out of Sync
|
||||||
sync-resolution-menu(
|
sync-resolution-menu(
|
||||||
close-function='ctrl.toggleSyncResolutionMenu',
|
close-function='ctrl.toggleSyncResolutionMenu()',
|
||||||
ng-click='$event.stopPropagation();',
|
ng-click='$event.stopPropagation();',
|
||||||
ng-if='ctrl.showSyncResolution'
|
ng-if='ctrl.showSyncResolution',
|
||||||
|
application='self.application'
|
||||||
)
|
)
|
||||||
.sk-app-bar-item(ng-if='ctrl.lastSyncDate && ctrl.isRefreshing')
|
.sk-app-bar-item(ng-if='ctrl.lastSyncDate && ctrl.isRefreshing')
|
||||||
.sk-spinner.small
|
.sk-spinner.small
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
) Forgot?
|
) Forgot?
|
||||||
div(ng-if='ctrl.formData.showRecovery')
|
div(ng-if='ctrl.formData.showRecovery')
|
||||||
.sk-p
|
.sk-p
|
||||||
| If you forgot your local passcode, your only option is to clear
|
| If you forgot your application passcode, your only option is to clear
|
||||||
| your local data from this device and sign back in to your account.
|
| your local data from this device and sign back in to your account.
|
||||||
.sk-panel-row
|
.sk-panel-row
|
||||||
a.sk-a.danger.center-text(
|
a.sk-a.danger.center-text(
|
||||||
|
|||||||
@@ -145,6 +145,6 @@
|
|||||||
control="self.panelPuppet"
|
control="self.panelPuppet"
|
||||||
default-width="300"
|
default-width="300"
|
||||||
hoverable="true"
|
hoverable="true"
|
||||||
on-resize-finish="self.onPanelResize"
|
on-resize-finish="self.onPanelResize()"
|
||||||
panel-id="'notes-column'"
|
panel-id="'notes-column'"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,14 +1,4 @@
|
|||||||
.main-ui-view(
|
application-view(
|
||||||
ng-class='self.platformString'
|
ng-repeat='application in self.applications',
|
||||||
)
|
application='application'
|
||||||
#app.app(
|
)
|
||||||
ng-class='self.state.appClass',
|
|
||||||
ng-if='!self.state.needsUnlock && self.state.ready'
|
|
||||||
)
|
|
||||||
tags-panel
|
|
||||||
notes-panel
|
|
||||||
editor-panel
|
|
||||||
|
|
||||||
footer(
|
|
||||||
ng-if='!self.state.needsUnlock && self.state.ready'
|
|
||||||
)
|
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
#tags-column.sn-component.section.tags(aria-label='Tags')
|
#tags-column.sn-component.section.tags(aria-label='Tags')
|
||||||
.component-view-container(ng-if='self.component.active')
|
.component-view-container(ng-if='self.component.active')
|
||||||
component-view.component-view(component='self.component')
|
component-view.component-view(
|
||||||
|
component='self.component',
|
||||||
|
application='self.application'
|
||||||
|
)
|
||||||
#tags-content.content(ng-if='!(self.component && self.component.active)')
|
#tags-content.content(ng-if='!(self.component && self.component.active)')
|
||||||
.tags-title-section.section-title-bar
|
.tags-title-section.section-title-bar
|
||||||
.section-title-bar-header
|
.section-title-bar-header
|
||||||
@@ -60,6 +63,6 @@
|
|||||||
control='self.panelPuppet',
|
control='self.panelPuppet',
|
||||||
default-width='150',
|
default-width='150',
|
||||||
hoverable='true',
|
hoverable='true',
|
||||||
on-resize-finish='self.onPanelResize',
|
on-resize-finish='self.onPanelResize()',
|
||||||
panel-id="'tags-column'"
|
panel-id="'tags-column'"
|
||||||
)
|
)
|
||||||
|
|||||||
6944
dist/javascripts/app.js
vendored
6944
dist/javascripts/app.js
vendored
File diff suppressed because one or more lines are too long
2
dist/javascripts/app.js.map
vendored
2
dist/javascripts/app.js.map
vendored
File diff suppressed because one or more lines are too long
85
public/dist/libsodium.bundle.js
vendored
85
public/dist/libsodium.bundle.js
vendored
@@ -1,2 +1,85 @@
|
|||||||
(window.webpackJsonpSNCrypto=window.webpackJsonpSNCrypto||[]).push([[0],{125:function(t,c){},126:function(t,c){},168:function(t,c,n){"use strict";n.r(c);var o=n(21);n.d(c,"ready",(function(){return o.ready})),n.d(c,"crypto_pwhash",(function(){return o.crypto_pwhash})),n.d(c,"crypto_pwhash_ALG_DEFAULT",(function(){return o.crypto_pwhash_ALG_DEFAULT})),n.d(c,"crypto_aead_xchacha20poly1305_ietf_encrypt",(function(){return o.crypto_aead_xchacha20poly1305_ietf_encrypt})),n.d(c,"crypto_aead_xchacha20poly1305_ietf_decrypt",(function(){return o.crypto_aead_xchacha20poly1305_ietf_decrypt}))},51:function(t,c){},91:function(t,c){},93:function(t,c){}}]);
|
(window["webpackJsonpSNCrypto"] = window["webpackJsonpSNCrypto"] || []).push([["libsodium"],{
|
||||||
|
|
||||||
|
/***/ "./lib/libsodium.js":
|
||||||
|
/*!**************************!*\
|
||||||
|
!*** ./lib/libsodium.js ***!
|
||||||
|
\**************************/
|
||||||
|
/*! exports provided: ready, crypto_pwhash, crypto_pwhash_ALG_DEFAULT, crypto_aead_xchacha20poly1305_ietf_encrypt, crypto_aead_xchacha20poly1305_ietf_decrypt */
|
||||||
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
__webpack_require__.r(__webpack_exports__);
|
||||||
|
/* harmony import */ var libsodium_wrappers__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! libsodium-wrappers */ "./node_modules/libsodium-wrappers/dist/modules/libsodium-wrappers.js");
|
||||||
|
/* harmony import */ var libsodium_wrappers__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(libsodium_wrappers__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
|
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ready", function() { return libsodium_wrappers__WEBPACK_IMPORTED_MODULE_0__["ready"]; });
|
||||||
|
|
||||||
|
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "crypto_pwhash", function() { return libsodium_wrappers__WEBPACK_IMPORTED_MODULE_0__["crypto_pwhash"]; });
|
||||||
|
|
||||||
|
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "crypto_pwhash_ALG_DEFAULT", function() { return libsodium_wrappers__WEBPACK_IMPORTED_MODULE_0__["crypto_pwhash_ALG_DEFAULT"]; });
|
||||||
|
|
||||||
|
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "crypto_aead_xchacha20poly1305_ietf_encrypt", function() { return libsodium_wrappers__WEBPACK_IMPORTED_MODULE_0__["crypto_aead_xchacha20poly1305_ietf_encrypt"]; });
|
||||||
|
|
||||||
|
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "crypto_aead_xchacha20poly1305_ietf_decrypt", function() { return libsodium_wrappers__WEBPACK_IMPORTED_MODULE_0__["crypto_aead_xchacha20poly1305_ietf_decrypt"]; });
|
||||||
|
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 0:
|
||||||
|
/*!********************!*\
|
||||||
|
!*** fs (ignored) ***!
|
||||||
|
\********************/
|
||||||
|
/*! no static exports found */
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
/* (ignored) */
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 1:
|
||||||
|
/*!**********************!*\
|
||||||
|
!*** util (ignored) ***!
|
||||||
|
\**********************/
|
||||||
|
/*! no static exports found */
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
/* (ignored) */
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 2:
|
||||||
|
/*!**********************!*\
|
||||||
|
!*** util (ignored) ***!
|
||||||
|
\**********************/
|
||||||
|
/*! no static exports found */
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
/* (ignored) */
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 3:
|
||||||
|
/*!************************!*\
|
||||||
|
!*** buffer (ignored) ***!
|
||||||
|
\************************/
|
||||||
|
/*! no static exports found */
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
/* (ignored) */
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 4:
|
||||||
|
/*!************************!*\
|
||||||
|
!*** crypto (ignored) ***!
|
||||||
|
\************************/
|
||||||
|
/*! no static exports found */
|
||||||
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
|
/* (ignored) */
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
}]);
|
||||||
//# sourceMappingURL=libsodium.bundle.js.map
|
//# sourceMappingURL=libsodium.bundle.js.map
|
||||||
30596
public/dist/vendors~libsodium.bundle.js
vendored
30596
public/dist/vendors~libsodium.bundle.js
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user