WIP
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { isDesktopApplication, isNullOrUndefined } from '@/utils';
|
||||
import { PrivilegesManager } from '@/services/privilegesManager';
|
||||
import template from '%/directives/account-menu.pug';
|
||||
import { protocolManager } from 'snjs';
|
||||
import { ProtectedActions } from 'snjs';
|
||||
import { PureCtrl } from '@Controllers';
|
||||
import {
|
||||
STRING_ACCOUNT_MENU_UNCHECK_MERGE,
|
||||
@@ -33,56 +32,38 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
$scope,
|
||||
$rootScope,
|
||||
$timeout,
|
||||
alertManager,
|
||||
archiveManager,
|
||||
appVersion,
|
||||
authManager,
|
||||
modelManager,
|
||||
passcodeManager,
|
||||
privilegesManager,
|
||||
storageManager,
|
||||
syncManager,
|
||||
godService,
|
||||
lockManager,
|
||||
application
|
||||
) {
|
||||
super($timeout);
|
||||
this.$scope = $scope;
|
||||
this.$rootScope = $rootScope;
|
||||
this.$timeout = $timeout;
|
||||
this.alertManager = alertManager;
|
||||
this.archiveManager = archiveManager;
|
||||
this.authManager = authManager;
|
||||
this.modelManager = modelManager;
|
||||
this.passcodeManager = passcodeManager;
|
||||
this.privilegesManager = privilegesManager;
|
||||
this.storageManager = storageManager;
|
||||
this.syncManager = syncManager;
|
||||
this.godService = godService;
|
||||
this.lockManager = lockManager;
|
||||
this.application = application;
|
||||
|
||||
this.state = {
|
||||
appVersion: 'v' + (window.electronAppVersion || appVersion),
|
||||
user: this.authManager.user,
|
||||
canAddPasscode: !this.authManager.isEphemeralSession(),
|
||||
passcodeAutoLockOptions: this.passcodeManager.getAutoLockIntervalOptions(),
|
||||
user: this.application.getUser(),
|
||||
canAddPasscode: !this.application.isEphemeralSession(),
|
||||
passcodeAutoLockOptions: this.lockManager.getAutoLockIntervalOptions(),
|
||||
formData: {
|
||||
mergeLocal: true,
|
||||
ephemeral: false
|
||||
},
|
||||
mutable: {
|
||||
backupEncrypted: this.encryptedBackupsAvailable()
|
||||
}
|
||||
mutable: {}
|
||||
};
|
||||
|
||||
this.syncStatus = this.syncManager.syncStatus;
|
||||
this.syncManager.getServerURL().then((url) => {
|
||||
this.setState({
|
||||
server: url,
|
||||
formData: { ...this.state.formData, url: url }
|
||||
});
|
||||
});
|
||||
this.authManager.checkForSecurityUpdate().then((available) => {
|
||||
this.setState({
|
||||
securityUpdateAvailable: available
|
||||
});
|
||||
});
|
||||
this.syncStatus = this.application.getSyncStatus();
|
||||
this.loadHost();
|
||||
this.checkForSecurityUpdate();
|
||||
this.reloadAutoLockInterval();
|
||||
this.loadBackupsAvailability();
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
@@ -97,15 +78,51 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
});
|
||||
}
|
||||
|
||||
encryptedBackupsAvailable() {
|
||||
return !isNullOrUndefined(this.authManager.user) || this.passcodeManager.hasPasscode();
|
||||
async loadHost() {
|
||||
const host = await this.application.getHost();
|
||||
this.setState({
|
||||
server: host,
|
||||
formData: {
|
||||
...this.state.formData,
|
||||
url: host
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async checkForSecurityUpdate() {
|
||||
const available = await this.godService.checkForSecurityUpdate();
|
||||
this.setState({
|
||||
securityUpdateAvailable: available
|
||||
});
|
||||
}
|
||||
|
||||
async loadBackupsAvailability() {
|
||||
const hasUser = !isNullOrUndefined(await this.application.getUser());
|
||||
const hasPasscode = await this.application.hasPasscode();
|
||||
const encryptedAvailable = hasUser || hasPasscode;
|
||||
|
||||
function encryptionStatusString() {
|
||||
if (hasUser) {
|
||||
return STRING_E2E_ENABLED;
|
||||
} else if (hasPasscode) {
|
||||
return STRING_LOCAL_ENC_ENABLED;
|
||||
} else {
|
||||
return STRING_ENC_NOT_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
encryptionStatusString: encryptionStatusString(),
|
||||
encryptionEnabled: encryptedAvailable,
|
||||
mutable: {
|
||||
...this.state.mutable,
|
||||
backupEncrypted: encryptedAvailable
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
submitMfaForm() {
|
||||
const params = {
|
||||
[this.state.formData.mfa.payload.mfa_key]: this.state.formData.userMfaCode
|
||||
};
|
||||
this.login(params);
|
||||
this.login();
|
||||
}
|
||||
|
||||
blurAuthFields() {
|
||||
@@ -114,9 +131,9 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
ELEMENT_NAME_AUTH_PASSWORD,
|
||||
ELEMENT_NAME_AUTH_PASSWORD_CONF
|
||||
];
|
||||
for(const name of names) {
|
||||
for (const name of names) {
|
||||
const element = document.getElementsByName(name)[0];
|
||||
if(element) {
|
||||
if (element) {
|
||||
element.blur();
|
||||
}
|
||||
}
|
||||
@@ -143,29 +160,25 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
});
|
||||
}
|
||||
|
||||
async login(extraParams) {
|
||||
/** Prevent a timed sync from occuring while signing in. */
|
||||
this.syncManager.lockSyncing();
|
||||
async login() {
|
||||
await this.setFormDataState({
|
||||
status: STRING_GENERATING_LOGIN_KEYS,
|
||||
authenticating: true
|
||||
});
|
||||
const response = await this.authManager.login(
|
||||
this.state.formData.url,
|
||||
this.state.formData.email,
|
||||
this.state.formData.user_password,
|
||||
this.state.formData.ephemeral,
|
||||
this.state.formData.strictSignin,
|
||||
extraParams
|
||||
);
|
||||
const response = await this.application.signIn({
|
||||
email: this.state.formData.email,
|
||||
password: this.state.formData.user_password,
|
||||
strict: this.state.formData.strictSignin,
|
||||
ephemeral: this.state.formData.ephemeral,
|
||||
mfaKeyPath: this.state.formData.mfa.payload.mfa_key,
|
||||
mfaCode: this.state.formData.userMfaCode,
|
||||
mergeLocal: this.state.formData.mergeLocal
|
||||
});
|
||||
const hasError = !response || response.error;
|
||||
if (!hasError) {
|
||||
await this.onAuthSuccess();
|
||||
this.syncManager.unlockSyncing();
|
||||
this.syncManager.sync({ performIntegrityCheck: true });
|
||||
return;
|
||||
}
|
||||
this.syncManager.unlockSyncing();
|
||||
await this.setFormDataState({
|
||||
status: null,
|
||||
});
|
||||
@@ -174,7 +187,7 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
: { message: "An unknown error occured." };
|
||||
|
||||
if (error.tag === 'mfa-required' || error.tag === 'mfa-invalid') {
|
||||
await this.setFormDataState({
|
||||
await this.setFormDataState({
|
||||
showLogin: false,
|
||||
mfa: error
|
||||
});
|
||||
@@ -184,7 +197,7 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
mfa: null
|
||||
});
|
||||
if (error.message) {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: error.message
|
||||
});
|
||||
}
|
||||
@@ -197,22 +210,22 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
async register() {
|
||||
const confirmation = this.state.formData.password_conf;
|
||||
if (confirmation !== this.state.formData.user_password) {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: STRING_NON_MATCHING_PASSWORDS
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
await this.setFormDataState({
|
||||
confirmPassword: false,
|
||||
status: STRING_GENERATING_REGISTER_KEYS,
|
||||
authenticating: true
|
||||
});
|
||||
const response = await this.authManager.register(
|
||||
this.state.formData.url,
|
||||
this.state.formData.email,
|
||||
this.state.formData.user_password,
|
||||
this.state.formData.ephemeral
|
||||
);
|
||||
const response = await this.application.register({
|
||||
email: this.state.formData.email,
|
||||
password: this.state.formData.user_password,
|
||||
ephemeral: this.state.formData.ephemeral,
|
||||
mergeLocal: this.state.formData.mergeLocal
|
||||
});
|
||||
if (!response || response.error) {
|
||||
await this.setFormDataState({
|
||||
status: null
|
||||
@@ -223,18 +236,18 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
await this.setFormDataState({
|
||||
authenticating: false
|
||||
});
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: error.message
|
||||
});
|
||||
} else {
|
||||
await this.onAuthSuccess();
|
||||
this.syncManager.sync();
|
||||
this.application.sync();
|
||||
}
|
||||
}
|
||||
|
||||
mergeLocalChanged() {
|
||||
if (!this.state.formData.mergeLocal) {
|
||||
this.alertManager.confirm({
|
||||
this.application.alertManager.confirm({
|
||||
text: STRING_ACCOUNT_MENU_UNCHECK_MERGE,
|
||||
destructive: true,
|
||||
onCancel: () => {
|
||||
@@ -249,34 +262,30 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
async onAuthSuccess() {
|
||||
if (this.state.formData.mergeLocal) {
|
||||
this.$rootScope.$broadcast('major-data-change');
|
||||
await this.clearDatabaseAndRewriteAllItems({ alternateUuids: true });
|
||||
} else {
|
||||
this.modelManager.removeAllItemsFromMemory();
|
||||
await this.storageManager.clearAllModels();
|
||||
await this.rewriteDatabase({ alternateUuids: true });
|
||||
}
|
||||
await this.setFormDataState({
|
||||
authenticating: false
|
||||
});
|
||||
this.syncManager.refreshErroredItems();
|
||||
this.close();
|
||||
}
|
||||
|
||||
openPasswordWizard(type) {
|
||||
this.close();
|
||||
this.authManager.presentPasswordWizard(type);
|
||||
this.godService.presentPasswordWizard(type);
|
||||
}
|
||||
|
||||
async openPrivilegesModal() {
|
||||
this.close();
|
||||
const run = () => {
|
||||
this.privilegesManager.presentPrivilegesManagementModal();
|
||||
this.godService.presentPrivilegesManagementModal();
|
||||
};
|
||||
const needsPrivilege = await this.privilegesManager.actionRequiresPrivilege(
|
||||
PrivilegesManager.ActionManagePrivileges
|
||||
const needsPrivilege = await this.application.privilegesManager.actionRequiresPrivilege(
|
||||
ProtectedActions.ManagePrivileges
|
||||
);
|
||||
if (needsPrivilege) {
|
||||
this.privilegesManager.presentPrivilegesModal(
|
||||
PrivilegesManager.ActionManagePrivileges,
|
||||
this.godService.presentPrivilegesModal(
|
||||
ProtectedActions.ManagePrivileges,
|
||||
() => {
|
||||
run();
|
||||
}
|
||||
@@ -288,21 +297,21 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
|
||||
/**
|
||||
* Allows IndexedDB unencrypted logs to be deleted
|
||||
* `clearAllModels` will remove data from backing store,
|
||||
* `clearAllPayloads` will remove data from backing store,
|
||||
* but not from working memory See:
|
||||
* https://github.com/standardnotes/desktop/issues/131
|
||||
*/
|
||||
async clearDatabaseAndRewriteAllItems({ alternateUuids } = {}) {
|
||||
await this.storageManager.clearAllModels();
|
||||
await this.syncManager.markAllItemsDirtyAndSaveOffline(alternateUuids);
|
||||
async rewriteDatabase({ alternateUuids } = {}) {
|
||||
await this.application.destroyDatabase();
|
||||
await this.application.markAllItemsAsNeedingSync({ alternateUuids });
|
||||
}
|
||||
|
||||
destroyLocalData() {
|
||||
this.alertManager.confirm({
|
||||
this.application.alertManager.confirm({
|
||||
text: STRING_SIGN_OUT_CONFIRMATION,
|
||||
destructive: true,
|
||||
onConfirm: async () => {
|
||||
await this.authManager.signout(true);
|
||||
await this.application.signOut();
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
@@ -323,7 +332,7 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
const data = JSON.parse(e.target.result);
|
||||
resolve(data);
|
||||
} catch (e) {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: STRING_INVALID_IMPORT_FILE
|
||||
});
|
||||
}
|
||||
@@ -360,12 +369,12 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
await this.performImport(data, null);
|
||||
}
|
||||
};
|
||||
const needsPrivilege = await this.privilegesManager.actionRequiresPrivilege(
|
||||
PrivilegesManager.ActionManageBackups
|
||||
const needsPrivilege = await this.application.privilegesManager.actionRequiresPrivilege(
|
||||
ProtectedActions.ManageBackups
|
||||
);
|
||||
if (needsPrivilege) {
|
||||
this.privilegesManager.presentPrivilegesModal(
|
||||
PrivilegesManager.ActionManageBackups,
|
||||
this.godService.presentPrivilegesModal(
|
||||
ProtectedActions.ManageBackups,
|
||||
run
|
||||
);
|
||||
} else {
|
||||
@@ -386,47 +395,22 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
});
|
||||
if (errorCount > 0) {
|
||||
const message = StringImportError({ errorCount: errorCount });
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: message
|
||||
});
|
||||
} else {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: STRING_IMPORT_SUCCESS
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async importJSONData(data, password) {
|
||||
let errorCount = 0;
|
||||
if (data.auth_params) {
|
||||
const keys = await protocolManager.computeEncryptionKeysForUser(
|
||||
password,
|
||||
data.auth_params
|
||||
);
|
||||
try {
|
||||
const throws = false;
|
||||
await protocolManager.decryptMultipleItems(data.items, keys, throws);
|
||||
const items = [];
|
||||
for (const item of data.items) {
|
||||
item.enc_item_key = null;
|
||||
item.auth_hash = null;
|
||||
if (item.errorDecrypting) {
|
||||
errorCount++;
|
||||
} else {
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
data.items = items;
|
||||
} catch (e) {
|
||||
this.alertManager.alert({
|
||||
text: STRING_ERROR_DECRYPTING_IMPORT
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const items = await this.modelManager.importItems(data.items);
|
||||
for (const item of items) {
|
||||
const { affectedItems, errorCount } = await this.application.importData({
|
||||
data: data.items,
|
||||
password: password
|
||||
});
|
||||
for (const item of affectedItems) {
|
||||
/**
|
||||
* Don't want to activate any components during import process in
|
||||
* case of exceptions breaking up the import proccess
|
||||
@@ -435,8 +419,6 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
item.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
this.syncManager.sync();
|
||||
return errorCount;
|
||||
}
|
||||
|
||||
@@ -445,10 +427,12 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
}
|
||||
|
||||
notesAndTagsCount() {
|
||||
return this.modelManager.allItemsMatchingTypes([
|
||||
'Note',
|
||||
'Tag'
|
||||
]).length;
|
||||
return this.application.getItems({
|
||||
contentType: [
|
||||
'Note',
|
||||
'Tag'
|
||||
]
|
||||
}).length;
|
||||
}
|
||||
|
||||
encryptionStatusForNotes() {
|
||||
@@ -456,32 +440,8 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
return length + "/" + length + " notes and tags encrypted";
|
||||
}
|
||||
|
||||
encryptionEnabled() {
|
||||
return this.passcodeManager.hasPasscode() || !this.authManager.offline();
|
||||
}
|
||||
|
||||
encryptionSource() {
|
||||
if (!this.authManager.offline()) {
|
||||
return "Account keys";
|
||||
} else if (this.passcodeManager.hasPasscode()) {
|
||||
return "Local Passcode";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
encryptionStatusString() {
|
||||
if (!this.authManager.offline()) {
|
||||
return STRING_E2E_ENABLED;
|
||||
} else if (this.passcodeManager.hasPasscode()) {
|
||||
return STRING_LOCAL_ENC_ENABLED;
|
||||
} else {
|
||||
return STRING_ENC_NOT_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
async reloadAutoLockInterval() {
|
||||
const interval = await this.passcodeManager.getAutoLockInterval();
|
||||
const interval = await this.lockManager.getAutoLockInterval();
|
||||
this.setState({
|
||||
selectedAutoLockInterval: interval
|
||||
});
|
||||
@@ -489,15 +449,15 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
|
||||
async selectAutoLockInterval(interval) {
|
||||
const run = async () => {
|
||||
await this.passcodeManager.setAutoLockInterval(interval);
|
||||
await this.lockManager.setAutoLockInterval(interval);
|
||||
this.reloadAutoLockInterval();
|
||||
};
|
||||
const needsPrivilege = await this.privilegesManager.actionRequiresPrivilege(
|
||||
PrivilegesManager.ActionManagePasscode
|
||||
const needsPrivilege = await this.application.privilegesManager.actionRequiresPrivilege(
|
||||
ProtectedActions.ManagePasscode
|
||||
);
|
||||
if (needsPrivilege) {
|
||||
this.privilegesManager.presentPrivilegesModal(
|
||||
PrivilegesManager.ActionManagePasscode,
|
||||
this.godService.presentPrivilegesModal(
|
||||
ProtectedActions.ManagePasscode,
|
||||
() => {
|
||||
run();
|
||||
}
|
||||
@@ -508,7 +468,7 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
}
|
||||
|
||||
hasPasscode() {
|
||||
return this.passcodeManager.hasPasscode();
|
||||
return this.application.hasPasscode();
|
||||
}
|
||||
|
||||
addPasscodeClicked() {
|
||||
@@ -520,23 +480,23 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
submitPasscodeForm() {
|
||||
const passcode = this.state.formData.passcode;
|
||||
if (passcode !== this.state.formData.confirmPasscode) {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: STRING_NON_MATCHING_PASSCODES
|
||||
});
|
||||
return;
|
||||
}
|
||||
const func = this.state.formData.changingPasscode
|
||||
? this.passcodeManager.changePasscode.bind(this.passcodeManager)
|
||||
: this.passcodeManager.setPasscode.bind(this.passcodeManager);
|
||||
? this.application.changePasscode.bind(this.application)
|
||||
: this.application.setPasscode.bind(this.application);
|
||||
func(passcode, async () => {
|
||||
await this.setFormDataState({
|
||||
passcode: null,
|
||||
confirmPasscode: null,
|
||||
showPasscodeForm: false
|
||||
});
|
||||
if (await this.authManager.offline()) {
|
||||
if (isNullOrUndefined(await this.application.getUser())) {
|
||||
this.$rootScope.$broadcast('major-data-change');
|
||||
this.clearDatabaseAndRewriteAllItems();
|
||||
this.rewriteDatabase();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -546,12 +506,12 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
this.state.formData.changingPasscode = true;
|
||||
this.addPasscodeClicked();
|
||||
};
|
||||
const needsPrivilege = await this.privilegesManager.actionRequiresPrivilege(
|
||||
PrivilegesManager.ActionManagePasscode
|
||||
const needsPrivilege = await this.application.privilegesManager.actionRequiresPrivilege(
|
||||
ProtectedActions.ManagePasscode
|
||||
);
|
||||
if (needsPrivilege) {
|
||||
this.privilegesManager.presentPrivilegesModal(
|
||||
PrivilegesManager.ActionManagePasscode,
|
||||
this.godService.presentPrivilegesModal(
|
||||
ProtectedActions.ManagePasscode,
|
||||
run
|
||||
);
|
||||
} else {
|
||||
@@ -560,34 +520,24 @@ class AccountMenuCtrl extends PureCtrl {
|
||||
}
|
||||
|
||||
async removePasscodePressed() {
|
||||
const run = () => {
|
||||
const signedIn = !this.authManager.offline();
|
||||
const run = async () => {
|
||||
const signedIn = !isNullOrUndefined(await this.application.getUser());
|
||||
let message = STRING_REMOVE_PASSCODE_CONFIRMATION;
|
||||
if (!signedIn) {
|
||||
message += STRING_REMOVE_PASSCODE_OFFLINE_ADDENDUM;
|
||||
}
|
||||
this.alertManager.confirm({
|
||||
this.application.alertManager.confirm({
|
||||
text: message,
|
||||
destructive: true,
|
||||
onConfirm: () => {
|
||||
this.passcodeManager.clearPasscode();
|
||||
if (this.authManager.offline()) {
|
||||
this.syncManager.markAllItemsDirtyAndSaveOffline();
|
||||
}
|
||||
this.application.removePasscode();
|
||||
}
|
||||
});
|
||||
};
|
||||
const needsPrivilege = await this.privilegesManager.actionRequiresPrivilege(
|
||||
PrivilegesManager.ActionManagePasscode
|
||||
this.godService.presentPrivilegesModal(
|
||||
ProtectedActions.ManagePasscode,
|
||||
run
|
||||
);
|
||||
if (needsPrivilege) {
|
||||
this.privilegesManager.presentPrivilegesModal(
|
||||
PrivilegesManager.ActionManagePasscode,
|
||||
run
|
||||
);
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
}
|
||||
|
||||
isDesktopApplication() {
|
||||
|
||||
@@ -14,15 +14,15 @@ class ComponentViewCtrl {
|
||||
$scope,
|
||||
$rootScope,
|
||||
$timeout,
|
||||
componentManager,
|
||||
application,
|
||||
desktopManager,
|
||||
themeManager
|
||||
) {
|
||||
this.$rootScope = $rootScope;
|
||||
this.$timeout = $timeout;
|
||||
this.application = application;
|
||||
this.themeManager = themeManager;
|
||||
this.desktopManager = desktopManager;
|
||||
this.componentManager = componentManager;
|
||||
this.componentValid = true;
|
||||
|
||||
$scope.$watch('ctrl.component', (component, prevComponent) => {
|
||||
@@ -52,7 +52,7 @@ class ComponentViewCtrl {
|
||||
|
||||
registerComponentHandlers() {
|
||||
this.themeHandlerIdentifier = 'component-view-' + Math.random();
|
||||
this.componentManager.registerHandler({
|
||||
this.application.componentManager.registerHandler({
|
||||
identifier: this.themeHandlerIdentifier,
|
||||
areas: ['themes'],
|
||||
activationHandler: (component) => {
|
||||
@@ -61,7 +61,7 @@ class ComponentViewCtrl {
|
||||
});
|
||||
|
||||
this.identifier = 'component-view-' + Math.random();
|
||||
this.componentManager.registerHandler({
|
||||
this.application.componentManager.registerHandler({
|
||||
identifier: this.identifier,
|
||||
areas: [this.component.area],
|
||||
activationHandler: (component) => {
|
||||
@@ -74,7 +74,7 @@ class ComponentViewCtrl {
|
||||
},
|
||||
actionHandler: (component, action, data) => {
|
||||
if(action === 'set-size') {
|
||||
this.componentManager.handleSetSizeEvent(component, data);
|
||||
this.application.componentManager.handleSetSizeEvent(component, data);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -91,7 +91,7 @@ class ComponentViewCtrl {
|
||||
|
||||
async reloadComponent() {
|
||||
this.componentValid = false;
|
||||
await this.componentManager.reloadComponent(this.component);
|
||||
await this.application.componentManager.reloadComponent(this.component);
|
||||
this.reloadStatus();
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ class ComponentViewCtrl {
|
||||
}
|
||||
if(this.componentValid !== previouslyValid) {
|
||||
if(this.componentValid) {
|
||||
this.componentManager.reloadComponent(component, true);
|
||||
this.application.componentManager.reloadComponent(component, true);
|
||||
}
|
||||
}
|
||||
if(this.expired && doManualReload) {
|
||||
@@ -140,7 +140,7 @@ class ComponentViewCtrl {
|
||||
if(!this.component.active) {
|
||||
return;
|
||||
}
|
||||
const iframe = this.componentManager.iframeForComponent(
|
||||
const iframe = this.application.componentManager.iframeForComponent(
|
||||
this.component
|
||||
);
|
||||
if(!iframe) {
|
||||
@@ -186,7 +186,7 @@ class ComponentViewCtrl {
|
||||
} catch (e) {}
|
||||
}
|
||||
this.$timeout.cancel(this.loadTimeout);
|
||||
await this.componentManager.registerComponentWindow(
|
||||
await this.application.componentManager.registerComponentWindow(
|
||||
this.component,
|
||||
iframe.contentWindow
|
||||
);
|
||||
@@ -201,13 +201,13 @@ class ComponentViewCtrl {
|
||||
componentValueDidSet(component, prevComponent) {
|
||||
const dontSync = true;
|
||||
if(prevComponent && component !== prevComponent) {
|
||||
this.componentManager.deactivateComponent(
|
||||
this.application.componentManager.deactivateComponent(
|
||||
prevComponent,
|
||||
dontSync
|
||||
);
|
||||
}
|
||||
if(component) {
|
||||
this.componentManager.activateComponent(
|
||||
this.application.componentManager.activateComponent(
|
||||
component,
|
||||
dontSync
|
||||
);
|
||||
@@ -239,17 +239,17 @@ class ComponentViewCtrl {
|
||||
}
|
||||
|
||||
getUrl() {
|
||||
const url = this.componentManager.urlForComponent(this.component);
|
||||
const url = this.application.componentManager.urlForComponent(this.component);
|
||||
this.component.runningLocally = (url === this.component.local_url);
|
||||
return url;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.componentManager.deregisterHandler(this.themeHandlerIdentifier);
|
||||
this.componentManager.deregisterHandler(this.identifier);
|
||||
this.application.componentManager.deregisterHandler(this.themeHandlerIdentifier);
|
||||
this.application.componentManager.deregisterHandler(this.identifier);
|
||||
if(this.component && !this.manualDealloc) {
|
||||
const dontSync = true;
|
||||
this.componentManager.deactivateComponent(this.component, dontSync);
|
||||
this.application.componentManager.deactivateComponent(this.component, dontSync);
|
||||
}
|
||||
|
||||
this.desktopManager.deregisterUpdateObserver(this.updateObserver);
|
||||
|
||||
@@ -4,16 +4,12 @@ class ConflictResolutionCtrl {
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
$element,
|
||||
alertManager,
|
||||
archiveManager,
|
||||
modelManager,
|
||||
syncManager
|
||||
application
|
||||
) {
|
||||
this.$element = $element;
|
||||
this.alertManager = alertManager;
|
||||
this.application = application;
|
||||
this.archiveManager = archiveManager;
|
||||
this.modelManager = modelManager;
|
||||
this.syncManager = syncManager;
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
@@ -31,35 +27,31 @@ class ConflictResolutionCtrl {
|
||||
}
|
||||
|
||||
keepItem1() {
|
||||
this.alertManager.confirm({
|
||||
this.application.alertManager.confirm({
|
||||
text: `Are you sure you want to delete the item on the right?`,
|
||||
destructive: true,
|
||||
onConfirm: () => {
|
||||
this.modelManager.setItemToBeDeleted(this.item2);
|
||||
this.syncManager.sync().then(() => {
|
||||
this.applyCallback();
|
||||
});
|
||||
this.application.deleteItem({item: this.item2});
|
||||
this.triggerCallback();
|
||||
this.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
keepItem2() {
|
||||
this.alertManager.confirm({
|
||||
this.application.alertManager.confirm({
|
||||
text: `Are you sure you want to delete the item on the left?`,
|
||||
destructive: true,
|
||||
onConfirm: () => {
|
||||
this.modelManager.setItemToBeDeleted(this.item1);
|
||||
this.syncManager.sync().then(() => {
|
||||
this.applyCallback();
|
||||
});
|
||||
this.application.deleteItem({item: this.item1});
|
||||
this.triggerCallback();
|
||||
this.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
keepBoth() {
|
||||
this.applyCallback();
|
||||
this.triggerCallback();
|
||||
this.dismiss();
|
||||
}
|
||||
|
||||
@@ -70,7 +62,7 @@ class ConflictResolutionCtrl {
|
||||
);
|
||||
}
|
||||
|
||||
applyCallback() {
|
||||
triggerCallback() {
|
||||
this.callback && this.callback();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,22 +6,17 @@ class EditorMenuCtrl extends PureCtrl {
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
$timeout,
|
||||
componentManager,
|
||||
modelManager,
|
||||
syncManager,
|
||||
application
|
||||
) {
|
||||
super($timeout);
|
||||
this.$timeout = $timeout;
|
||||
this.componentManager = componentManager;
|
||||
this.modelManager = modelManager;
|
||||
this.syncManager = syncManager;
|
||||
this.application = application;
|
||||
this.state = {
|
||||
isDesktop: isDesktopApplication()
|
||||
};
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
const editors = this.componentManager.componentsForArea('editor-editor')
|
||||
const editors = this.application.componentManager.componentsForArea('editor-editor')
|
||||
.sort((a, b) => {
|
||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||
});
|
||||
@@ -36,8 +31,7 @@ class EditorMenuCtrl extends PureCtrl {
|
||||
if(component) {
|
||||
if(component.content.conflict_of) {
|
||||
component.content.conflict_of = null;
|
||||
this.modelManager.setItemDirty(component, true);
|
||||
this.syncManager.sync();
|
||||
this.application.saveItem({item: component});
|
||||
}
|
||||
}
|
||||
this.$timeout(() => {
|
||||
@@ -58,16 +52,15 @@ class EditorMenuCtrl extends PureCtrl {
|
||||
}
|
||||
|
||||
makeEditorDefault(component) {
|
||||
const currentDefault = this.componentManager
|
||||
const currentDefault = this.application.componentManager
|
||||
.componentsForArea('editor-editor')
|
||||
.filter((e) => e.isDefaultEditor())[0];
|
||||
if(currentDefault) {
|
||||
currentDefault.setAppDataItem('defaultEditor', false);
|
||||
this.modelManager.setItemDirty(currentDefault);
|
||||
this.application.setItemsNeedsSync({item: currentDefault});
|
||||
}
|
||||
component.setAppDataItem('defaultEditor', true);
|
||||
this.modelManager.setItemDirty(component);
|
||||
this.syncManager.sync();
|
||||
this.application.saveItem({ item: component });
|
||||
this.setState({
|
||||
defaultEditor: component
|
||||
});
|
||||
@@ -75,8 +68,7 @@ class EditorMenuCtrl extends PureCtrl {
|
||||
|
||||
removeEditorDefault(component) {
|
||||
component.setAppDataItem('defaultEditor', false);
|
||||
this.modelManager.setItemDirty(component);
|
||||
this.syncManager.sync();
|
||||
this.application.saveItem({ item: component });
|
||||
this.setState({
|
||||
defaultEditor: null
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { protocolManager } from 'snjs';
|
||||
import template from '%/directives/password-wizard.pug';
|
||||
import { STRING_FAILED_PASSWORD_CHANGE } from '@/strings';
|
||||
import { isNullOrUndefined } from '../../utils';
|
||||
|
||||
const DEFAULT_CONTINUE_TITLE = "Continue";
|
||||
const Steps = {
|
||||
@@ -18,25 +18,17 @@ class PasswordWizardCtrl {
|
||||
$element,
|
||||
$scope,
|
||||
$timeout,
|
||||
alertManager,
|
||||
archiveManager,
|
||||
authManager,
|
||||
modelManager,
|
||||
syncManager,
|
||||
archiveManager
|
||||
) {
|
||||
this.$element = $element;
|
||||
this.$timeout = $timeout;
|
||||
this.$scope = $scope;
|
||||
this.alertManager = alertManager;
|
||||
this.archiveManager = archiveManager;
|
||||
this.authManager = authManager;
|
||||
this.modelManager = modelManager;
|
||||
this.syncManager = syncManager;
|
||||
this.registerWindowUnloadStopper();
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.syncStatus = this.syncManager.syncStatus;
|
||||
this.syncStatus = this.application.getSyncStatus();
|
||||
this.formData = {};
|
||||
this.configureDefaults();
|
||||
}
|
||||
@@ -139,20 +131,11 @@ class PasswordWizardCtrl {
|
||||
this.formData.status = "Unable to process your password. Please try again.";
|
||||
return;
|
||||
}
|
||||
this.formData.status = "Encrypting and syncing data with new keys...";
|
||||
|
||||
const syncSuccess = await this.resyncData();
|
||||
this.formData.statusError = !syncSuccess;
|
||||
this.formData.processing = !syncSuccess;
|
||||
if (syncSuccess) {
|
||||
this.lockContinue = false;
|
||||
if (this.changePassword) {
|
||||
this.formData.status = "Successfully changed password and synced all items.";
|
||||
} else if (this.securityUpdate) {
|
||||
this.formData.status = "Successfully performed security update and synced all items.";
|
||||
}
|
||||
} else {
|
||||
this.formData.status = STRING_FAILED_PASSWORD_CHANGE;
|
||||
this.lockContinue = false;
|
||||
if (this.changePassword) {
|
||||
this.formData.status = "Successfully changed password.";
|
||||
} else if (this.securityUpdate) {
|
||||
this.formData.status = "Successfully performed security update.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,28 +143,28 @@ class PasswordWizardCtrl {
|
||||
const currentPassword = this.formData.currentPassword;
|
||||
const newPass = this.securityUpdate ? currentPassword : this.formData.newPassword;
|
||||
if (!currentPassword || currentPassword.length === 0) {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: "Please enter your current password."
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (this.changePassword) {
|
||||
if (!newPass || newPass.length === 0) {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: "Please enter a new password."
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (newPass !== this.formData.newPasswordConfirmation) {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: "Your new password does not match its confirmation."
|
||||
});
|
||||
this.formData.status = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!this.authManager.user.email) {
|
||||
this.alertManager.alert({
|
||||
if (!this.application.getUser().email) {
|
||||
this.application.alertManager.alert({
|
||||
text: "We don't have your email stored. Please log out then log back in to fix this issue."
|
||||
});
|
||||
this.formData.status = null;
|
||||
@@ -189,61 +172,31 @@ class PasswordWizardCtrl {
|
||||
}
|
||||
|
||||
/** Validate current password */
|
||||
const authParams = await this.authManager.getAuthParams();
|
||||
const password = this.formData.currentPassword;
|
||||
const keys = await protocolManager.computeEncryptionKeysForUser(
|
||||
password,
|
||||
authParams
|
||||
);
|
||||
const success = keys.mk === (await this.authManager.keys()).mk;
|
||||
if (success) {
|
||||
this.currentServerPw = keys.pw;
|
||||
const key = await this.application.validateAccountPassword({
|
||||
password: this.formData.currentPassword
|
||||
});
|
||||
if (key) {
|
||||
this.currentServerPassword = key.serverPassword;
|
||||
} else {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: "The current password you entered is not correct. Please try again."
|
||||
});
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
async resyncData() {
|
||||
await this.modelManager.setAllItemsDirty();
|
||||
const response = await this.syncManager.sync();
|
||||
if (!response || response.error) {
|
||||
this.alertManager.alert({
|
||||
text: STRING_FAILED_PASSWORD_CHANGE
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return !isNullOrUndefined(key);
|
||||
}
|
||||
|
||||
async processPasswordChange() {
|
||||
const newUserPassword = this.securityUpdate
|
||||
const newPassword = this.securityUpdate
|
||||
? this.formData.currentPassword
|
||||
: this.formData.newPassword;
|
||||
const currentServerPw = this.currentServerPw;
|
||||
const results = await protocolManager.generateInitialKeysAndAuthParamsForUser(
|
||||
this.authManager.user.email,
|
||||
newUserPassword
|
||||
);
|
||||
const newKeys = results.keys;
|
||||
const newAuthParams = results.authParams;
|
||||
/**
|
||||
* Perform a sync beforehand to pull in any last minutes changes before we change
|
||||
* the encryption key (and thus cant decrypt new changes).
|
||||
*/
|
||||
await this.syncManager.sync();
|
||||
const response = await this.authManager.changePassword(
|
||||
await this.syncManager.getServerURL(),
|
||||
this.authManager.user.email,
|
||||
currentServerPw,
|
||||
newKeys,
|
||||
newAuthParams
|
||||
);
|
||||
|
||||
const response = await this.application.changePassword({
|
||||
email: this.application.getUser().email,
|
||||
currentPassword: this.formData.currentPassword,
|
||||
newPassword: newPassword
|
||||
});
|
||||
if (response.error) {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: response.error.message
|
||||
? response.error.message
|
||||
: "There was an error changing your password. Please try again."
|
||||
@@ -260,7 +213,7 @@ class PasswordWizardCtrl {
|
||||
|
||||
dismiss() {
|
||||
if (this.lockContinue) {
|
||||
this.alertManager.alert({
|
||||
this.application.alertManager.alert({
|
||||
text: "Cannot close window until pending tasks are complete."
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -5,22 +5,24 @@ class PrivilegesAuthModalCtrl {
|
||||
constructor(
|
||||
$element,
|
||||
$timeout,
|
||||
privilegesManager,
|
||||
application
|
||||
) {
|
||||
this.$element = $element;
|
||||
this.$timeout = $timeout;
|
||||
this.privilegesManager = privilegesManager;
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.authParameters = {};
|
||||
this.sessionLengthOptions = this.privilegesManager.getSessionLengthOptions();
|
||||
this.privilegesManager.getSelectedSessionLength().then((length) => {
|
||||
this.sessionLengthOptions = this.application.privilegesManager.getSessionLengthOptions();
|
||||
this.application.privilegesManager.getSelectedSessionLength()
|
||||
.then((length) => {
|
||||
this.$timeout(() => {
|
||||
this.selectedSessionLength = length;
|
||||
});
|
||||
});
|
||||
this.privilegesManager.netCredentialsForAction(this.action).then((credentials) => {
|
||||
this.application.privilegesManager.netCredentialsForAction(this.action)
|
||||
.then((credentials) => {
|
||||
this.$timeout(() => {
|
||||
this.requiredCredentials = credentials.sort();
|
||||
});
|
||||
@@ -32,7 +34,7 @@ class PrivilegesAuthModalCtrl {
|
||||
}
|
||||
|
||||
promptForCredential(credential) {
|
||||
return this.privilegesManager.displayInfoForCredential(credential).prompt;
|
||||
return this.application.privilegesManager.displayInfoForCredential(credential).prompt;
|
||||
}
|
||||
|
||||
cancel() {
|
||||
@@ -65,13 +67,13 @@ class PrivilegesAuthModalCtrl {
|
||||
if (!this.validate()) {
|
||||
return;
|
||||
}
|
||||
const result = await this.privilegesManager.authenticateAction(
|
||||
const result = await this.application.privilegesManager.authenticateAction(
|
||||
this.action,
|
||||
this.authParameters
|
||||
);
|
||||
this.$timeout(() => {
|
||||
if (result.success) {
|
||||
this.privilegesManager.setSessionLength(this.selectedSessionLength);
|
||||
this.application.privilegesManager.setSessionLength(this.selectedSessionLength);
|
||||
this.onSuccess();
|
||||
this.dismiss();
|
||||
} else {
|
||||
|
||||
@@ -6,20 +6,18 @@ class PrivilegesManagementModalCtrl {
|
||||
constructor(
|
||||
$timeout,
|
||||
$element,
|
||||
privilegesManager,
|
||||
authManager,
|
||||
passcodeManager,
|
||||
application
|
||||
) {
|
||||
this.$element = $element;
|
||||
this.$timeout = $timeout;
|
||||
this.privilegesManager = privilegesManager;
|
||||
this.hasPasscode = passcodeManager.hasPasscode();
|
||||
this.hasAccount = !authManager.offline();
|
||||
this.application = application;
|
||||
this.hasPasscode = application.hasPasscode();
|
||||
this.hasAccount = !application.noUser();
|
||||
this.reloadPrivileges();
|
||||
}
|
||||
|
||||
displayInfoForCredential(credential) {
|
||||
const info = this.privilegesManager.displayInfoForCredential(credential);
|
||||
const info = this.application.privilegesManager.displayInfoForCredential(credential);
|
||||
if (credential === PrivilegesManager.CredentialLocalPasscode) {
|
||||
info.availability = this.hasPasscode;
|
||||
} else if (credential === PrivilegesManager.CredentialAccountPassword) {
|
||||
@@ -31,7 +29,7 @@ class PrivilegesManagementModalCtrl {
|
||||
}
|
||||
|
||||
displayInfoForAction(action) {
|
||||
return this.privilegesManager.displayInfoForAction(action).label;
|
||||
return this.application.privilegesManager.displayInfoForAction(action).label;
|
||||
}
|
||||
|
||||
isCredentialRequiredForAction(action, credential) {
|
||||
@@ -42,21 +40,21 @@ class PrivilegesManagementModalCtrl {
|
||||
}
|
||||
|
||||
async clearSession() {
|
||||
await this.privilegesManager.clearSession();
|
||||
await this.application.privilegesManager.clearSession();
|
||||
this.reloadPrivileges();
|
||||
}
|
||||
|
||||
async reloadPrivileges() {
|
||||
this.availableActions = this.privilegesManager.getAvailableActions();
|
||||
this.availableCredentials = this.privilegesManager.getAvailableCredentials();
|
||||
const sessionEndDate = await this.privilegesManager.getSessionExpirey();
|
||||
this.availableActions = this.application.privilegesManager.getAvailableActions();
|
||||
this.availableCredentials = this.application.privilegesManager.getAvailableCredentials();
|
||||
const sessionEndDate = await this.application.privilegesManager.getSessionExpirey();
|
||||
this.sessionExpirey = sessionEndDate.toLocaleString();
|
||||
this.sessionExpired = new Date() >= sessionEndDate;
|
||||
this.credentialDisplayInfo = {};
|
||||
for (const cred of this.availableCredentials) {
|
||||
this.credentialDisplayInfo[cred] = this.displayInfoForCredential(cred);
|
||||
}
|
||||
const privs = await this.privilegesManager.getPrivileges();
|
||||
const privs = await this.application.privilegesManager.getPrivileges();
|
||||
this.$timeout(() => {
|
||||
this.privileges = privs;
|
||||
});
|
||||
@@ -64,7 +62,7 @@ class PrivilegesManagementModalCtrl {
|
||||
|
||||
checkboxValueChanged(action, credential) {
|
||||
this.privileges.toggleCredentialForAction(action, credential);
|
||||
this.privilegesManager.savePrivileges();
|
||||
this.application.privilegesManager.savePrivileges();
|
||||
}
|
||||
|
||||
cancel() {
|
||||
|
||||
@@ -7,23 +7,17 @@ class RevisionPreviewModalCtrl {
|
||||
$element,
|
||||
$scope,
|
||||
$timeout,
|
||||
alertManager,
|
||||
componentManager,
|
||||
modelManager,
|
||||
syncManager,
|
||||
) {
|
||||
this.$element = $element;
|
||||
this.$scope = $scope;
|
||||
this.$timeout = $timeout;
|
||||
this.alertManager = alertManager;
|
||||
this.componentManager = componentManager;
|
||||
this.modelManager = modelManager;
|
||||
this.syncManager = syncManager;
|
||||
this.createNote();
|
||||
this.configureEditor();
|
||||
$scope.$on('$destroy', () => {
|
||||
if (this.identifier) {
|
||||
this.componentManager.deregisterHandler(this.identifier);
|
||||
this.application.componentManager.deregisterHandler(this.identifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -41,7 +35,7 @@ class RevisionPreviewModalCtrl {
|
||||
* for note as not to save changes to original, if editor makes changes.
|
||||
*/
|
||||
this.note.uuid = this.uuid;
|
||||
const editorForNote = this.componentManager.editorForNote(this.note);
|
||||
const editorForNote = this.application.componentManager.editorForNote(this.note);
|
||||
this.note.uuid = protocolManager.crypto.generateUUIDSync();
|
||||
if (editorForNote) {
|
||||
/**
|
||||
@@ -55,7 +49,7 @@ class RevisionPreviewModalCtrl {
|
||||
editorCopy.readonly = true;
|
||||
editorCopy.lockReadonly = true;
|
||||
this.identifier = editorCopy.uuid;
|
||||
this.componentManager.registerHandler({
|
||||
this.application.componentManager.registerHandler({
|
||||
identifier: this.identifier,
|
||||
areas: ['editor-editor'],
|
||||
contextRequestHandler: (component) => {
|
||||
@@ -75,21 +69,21 @@ class RevisionPreviewModalCtrl {
|
||||
}
|
||||
|
||||
restore(asCopy) {
|
||||
const run = () => {
|
||||
const run = async () => {
|
||||
let item;
|
||||
if (asCopy) {
|
||||
const contentCopy = Object.assign({}, this.content);
|
||||
if (contentCopy.title) {
|
||||
contentCopy.title += " (copy)";
|
||||
}
|
||||
item = this.modelManager.createItem({
|
||||
content_type: 'Note',
|
||||
content: contentCopy
|
||||
item = await this.application.createItem({
|
||||
contentType: 'Note',
|
||||
content: contentCopy,
|
||||
needsSync: true
|
||||
});
|
||||
this.modelManager.addItem(item);
|
||||
} else {
|
||||
const uuid = this.uuid;
|
||||
item = this.modelManager.findItem(uuid);
|
||||
item = this.application.findItem({uuid: uuid});
|
||||
item.content = Object.assign({}, this.content);
|
||||
this.modelManager.mapResponseItemsToLocalModels(
|
||||
[item],
|
||||
@@ -102,7 +96,7 @@ class RevisionPreviewModalCtrl {
|
||||
};
|
||||
|
||||
if (!asCopy) {
|
||||
this.alertManager.confirm({
|
||||
this.application.alertManager.confirm({
|
||||
text: "Are you sure you want to replace the current note's contents with what you see in this preview?",
|
||||
destructive: true,
|
||||
onConfirm: run
|
||||
|
||||
Reference in New Issue
Block a user