Account menu TS
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
|
import { WebDirective } from './../../types';
|
||||||
import { isDesktopApplication, isNullOrUndefined } from '@/utils';
|
import { isDesktopApplication, isNullOrUndefined } from '@/utils';
|
||||||
import template from '%/directives/account-menu.pug';
|
import template from '%/directives/account-menu.pug';
|
||||||
import { ProtectedAction } from 'snjs';
|
import { ProtectedAction, ContentType, SNComponent } from 'snjs';
|
||||||
import { PureCtrl } from '@Controllers';
|
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
||||||
import {
|
import {
|
||||||
STRING_ACCOUNT_MENU_UNCHECK_MERGE,
|
STRING_ACCOUNT_MENU_UNCHECK_MERGE,
|
||||||
STRING_SIGN_OUT_CONFIRMATION,
|
STRING_SIGN_OUT_CONFIRMATION,
|
||||||
@@ -18,6 +19,9 @@ import {
|
|||||||
STRING_GENERATING_REGISTER_KEYS,
|
STRING_GENERATING_REGISTER_KEYS,
|
||||||
StringImportError
|
StringImportError
|
||||||
} from '@/strings';
|
} from '@/strings';
|
||||||
|
import { SyncOpStatus } from '@/../../../../snjs/dist/@types/services/sync/sync_op_status';
|
||||||
|
import { PasswordWizardType } from '@/types';
|
||||||
|
import { BackupFile } from '@/../../../../snjs/dist/@types/services/protocol_service';
|
||||||
|
|
||||||
const ELEMENT_ID_IMPORT_PASSWORD_INPUT = 'import-password-request';
|
const ELEMENT_ID_IMPORT_PASSWORD_INPUT = 'import-password-request';
|
||||||
|
|
||||||
@@ -25,11 +29,46 @@ const ELEMENT_NAME_AUTH_EMAIL = 'email';
|
|||||||
const ELEMENT_NAME_AUTH_PASSWORD = 'password';
|
const ELEMENT_NAME_AUTH_PASSWORD = 'password';
|
||||||
const ELEMENT_NAME_AUTH_PASSWORD_CONF = 'password_conf';
|
const ELEMENT_NAME_AUTH_PASSWORD_CONF = 'password_conf';
|
||||||
|
|
||||||
|
type FormData = {
|
||||||
|
email: string
|
||||||
|
user_password: string
|
||||||
|
password_conf: string
|
||||||
|
confirmPassword: boolean
|
||||||
|
showLogin: boolean
|
||||||
|
showRegister: boolean
|
||||||
|
showPasscodeForm: boolean
|
||||||
|
strictSignin?: boolean
|
||||||
|
ephemeral: boolean
|
||||||
|
mfa: { payload: any }
|
||||||
|
userMfaCode?: string
|
||||||
|
mergeLocal?: boolean
|
||||||
|
url: string
|
||||||
|
authenticating: boolean
|
||||||
|
status: string
|
||||||
|
passcode: string
|
||||||
|
confirmPasscode: string
|
||||||
|
changingPasscode: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
type AccountMenuState = {
|
||||||
|
formData: Partial<FormData>
|
||||||
|
appVersion: string
|
||||||
|
passcodeAutoLockOptions: any
|
||||||
|
user: any
|
||||||
|
mutable: any
|
||||||
|
importData: any
|
||||||
|
}
|
||||||
|
|
||||||
class AccountMenuCtrl extends PureCtrl {
|
class AccountMenuCtrl extends PureCtrl {
|
||||||
|
|
||||||
|
public appVersion: string
|
||||||
|
private syncStatus?: SyncOpStatus
|
||||||
|
private closeFunction?: () => void
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$timeout,
|
$timeout: ng.ITimeoutService,
|
||||||
appVersion,
|
appVersion: string,
|
||||||
) {
|
) {
|
||||||
super($timeout);
|
super($timeout);
|
||||||
this.appVersion = appVersion;
|
this.appVersion = appVersion;
|
||||||
@@ -38,15 +77,19 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
/** @override */
|
/** @override */
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return {
|
return {
|
||||||
appVersion: 'v' + (window.electronAppVersion || this.appVersion),
|
appVersion: 'v' + ((window as any).electronAppVersion || this.appVersion),
|
||||||
passcodeAutoLockOptions: this.application.getLockService().getAutoLockIntervalOptions(),
|
passcodeAutoLockOptions: this.application!.getLockService().getAutoLockIntervalOptions(),
|
||||||
user: this.application.getUser(),
|
user: this.application!.getUser(),
|
||||||
formData: {
|
formData: {
|
||||||
mergeLocal: true,
|
mergeLocal: true,
|
||||||
ephemeral: false
|
ephemeral: false
|
||||||
},
|
},
|
||||||
mutable: {}
|
mutable: {}
|
||||||
};
|
} as AccountMenuState;
|
||||||
|
}
|
||||||
|
|
||||||
|
getState() {
|
||||||
|
return this.state as AccountMenuState;
|
||||||
}
|
}
|
||||||
|
|
||||||
async onAppKeyChange() {
|
async onAppKeyChange() {
|
||||||
@@ -64,9 +107,9 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
|
|
||||||
refreshedCredentialState() {
|
refreshedCredentialState() {
|
||||||
return {
|
return {
|
||||||
user: this.application.getUser(),
|
user: this.application!.getUser(),
|
||||||
canAddPasscode: !this.application.isEphemeralSession(),
|
canAddPasscode: !this.application!.isEphemeralSession(),
|
||||||
hasPasscode: this.application.hasPasscode(),
|
hasPasscode: this.application!.hasPasscode(),
|
||||||
showPasscodeForm: false
|
showPasscodeForm: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -76,7 +119,7 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
this.initProps({
|
this.initProps({
|
||||||
closeFunction: this.closeFunction
|
closeFunction: this.closeFunction
|
||||||
});
|
});
|
||||||
this.syncStatus = this.application.getSyncStatus();
|
this.syncStatus = this.application!.getSyncStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
@@ -86,24 +129,24 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadHost() {
|
async loadHost() {
|
||||||
const host = await this.application.getHost();
|
const host = await this.application!.getHost();
|
||||||
this.setState({
|
this.setState({
|
||||||
server: host,
|
server: host,
|
||||||
formData: {
|
formData: {
|
||||||
...this.state.formData,
|
...this.getState().formData,
|
||||||
url: host
|
url: host
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onHostInputChange() {
|
onHostInputChange() {
|
||||||
const url = this.state.formData.url;
|
const url = this.getState().formData.url!;
|
||||||
this.application.setHost(url);
|
this.application!.setHost(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadBackupsAvailability() {
|
async loadBackupsAvailability() {
|
||||||
const hasUser = !isNullOrUndefined(this.application.getUser());
|
const hasUser = !isNullOrUndefined(this.application!.getUser());
|
||||||
const hasPasscode = this.application.hasPasscode();
|
const hasPasscode = this.application!.hasPasscode();
|
||||||
const encryptedAvailable = hasUser || hasPasscode;
|
const encryptedAvailable = hasUser || hasPasscode;
|
||||||
|
|
||||||
function encryptionStatusString() {
|
function encryptionStatusString() {
|
||||||
@@ -120,7 +163,7 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
encryptionStatusString: encryptionStatusString(),
|
encryptionStatusString: encryptionStatusString(),
|
||||||
encryptionEnabled: encryptedAvailable,
|
encryptionEnabled: encryptedAvailable,
|
||||||
mutable: {
|
mutable: {
|
||||||
...this.state.mutable,
|
...this.getState().mutable,
|
||||||
backupEncrypted: encryptedAvailable
|
backupEncrypted: encryptedAvailable
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -145,21 +188,21 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
submitAuthForm() {
|
submitAuthForm() {
|
||||||
if (!this.state.formData.email || !this.state.formData.user_password) {
|
if (!this.getState().formData.email || !this.getState().formData.user_password) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.blurAuthFields();
|
this.blurAuthFields();
|
||||||
if (this.state.formData.showLogin) {
|
if (this.getState().formData.showLogin) {
|
||||||
this.login();
|
this.login();
|
||||||
} else {
|
} else {
|
||||||
this.register();
|
this.register();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async setFormDataState(formData) {
|
async setFormDataState(formData: Partial<FormData>) {
|
||||||
return this.setState({
|
return this.setState({
|
||||||
formData: {
|
formData: {
|
||||||
...this.state.formData,
|
...this.getState().formData,
|
||||||
...formData
|
...formData
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -170,20 +213,21 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
status: STRING_GENERATING_LOGIN_KEYS,
|
status: STRING_GENERATING_LOGIN_KEYS,
|
||||||
authenticating: true
|
authenticating: true
|
||||||
});
|
});
|
||||||
const response = await this.application.signIn({
|
const formData = this.getState().formData;
|
||||||
email: this.state.formData.email,
|
const response = await this.application!.signIn(
|
||||||
password: this.state.formData.user_password,
|
formData.email!,
|
||||||
strict: this.state.formData.strictSignin,
|
formData.user_password!,
|
||||||
ephemeral: this.state.formData.ephemeral,
|
formData.strictSignin,
|
||||||
mfaKeyPath: this.state.formData.mfa && this.state.formData.mfa.payload.mfa_key,
|
formData.ephemeral,
|
||||||
mfaCode: this.state.formData.userMfaCode,
|
formData.mfa && formData.mfa.payload.mfa_key,
|
||||||
mergeLocal: this.state.formData.mergeLocal
|
formData.userMfaCode,
|
||||||
});
|
formData.mergeLocal
|
||||||
|
);
|
||||||
const hasError = !response || response.error;
|
const hasError = !response || response.error;
|
||||||
if (!hasError) {
|
if (!hasError) {
|
||||||
await this.setFormDataState({
|
await this.setFormDataState({
|
||||||
authenticating: false,
|
authenticating: false,
|
||||||
user_password: null
|
user_password: undefined
|
||||||
});
|
});
|
||||||
this.close();
|
this.close();
|
||||||
return;
|
return;
|
||||||
@@ -195,19 +239,17 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
await this.setFormDataState({
|
await this.setFormDataState({
|
||||||
showLogin: false,
|
showLogin: false,
|
||||||
mfa: error,
|
mfa: error,
|
||||||
status: null
|
status: undefined
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await this.setFormDataState({
|
await this.setFormDataState({
|
||||||
showLogin: true,
|
showLogin: true,
|
||||||
mfa: null,
|
mfa: undefined,
|
||||||
status: null,
|
status: undefined,
|
||||||
user_password: null
|
user_password: undefined
|
||||||
});
|
});
|
||||||
if (error.message) {
|
if (error.message) {
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(error.message);
|
||||||
text: error.message
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.setFormDataState({
|
await this.setFormDataState({
|
||||||
@@ -216,11 +258,11 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async register() {
|
async register() {
|
||||||
const confirmation = this.state.formData.password_conf;
|
const confirmation = this.getState().formData.password_conf;
|
||||||
if (confirmation !== this.state.formData.user_password) {
|
if (confirmation !== this.getState().formData.user_password) {
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: STRING_NON_MATCHING_PASSWORDS
|
STRING_NON_MATCHING_PASSWORDS
|
||||||
});
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.setFormDataState({
|
await this.setFormDataState({
|
||||||
@@ -228,15 +270,15 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
status: STRING_GENERATING_REGISTER_KEYS,
|
status: STRING_GENERATING_REGISTER_KEYS,
|
||||||
authenticating: true
|
authenticating: true
|
||||||
});
|
});
|
||||||
const response = await this.application.register({
|
const response = await this.application!.register(
|
||||||
email: this.state.formData.email,
|
this.getState().formData.email!,
|
||||||
password: this.state.formData.user_password,
|
this.getState().formData.user_password!,
|
||||||
ephemeral: this.state.formData.ephemeral,
|
this.getState().formData.ephemeral,
|
||||||
mergeLocal: this.state.formData.mergeLocal
|
this.getState().formData.mergeLocal
|
||||||
});
|
);
|
||||||
if (!response || response.error) {
|
if (!response || response.error) {
|
||||||
await this.setFormDataState({
|
await this.setFormDataState({
|
||||||
status: null
|
status: undefined
|
||||||
});
|
});
|
||||||
const error = response
|
const error = response
|
||||||
? response.error
|
? response.error
|
||||||
@@ -244,9 +286,9 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
await this.setFormDataState({
|
await this.setFormDataState({
|
||||||
authenticating: false
|
authenticating: false
|
||||||
});
|
});
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: error.message
|
error.message
|
||||||
});
|
);
|
||||||
} else {
|
} else {
|
||||||
await this.setFormDataState({ authenticating: false });
|
await this.setFormDataState({ authenticating: false });
|
||||||
this.close();
|
this.close();
|
||||||
@@ -254,34 +296,38 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mergeLocalChanged() {
|
mergeLocalChanged() {
|
||||||
if (!this.state.formData.mergeLocal) {
|
if (!this.getState().formData.mergeLocal) {
|
||||||
this.application.alertService.confirm({
|
this.application!.alertService!.confirm(
|
||||||
text: STRING_ACCOUNT_MENU_UNCHECK_MERGE,
|
STRING_ACCOUNT_MENU_UNCHECK_MERGE,
|
||||||
destructive: true,
|
undefined,
|
||||||
onCancel: () => {
|
undefined,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
() => {
|
||||||
this.setFormDataState({
|
this.setFormDataState({
|
||||||
mergeLocal: true
|
mergeLocal: true
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
});
|
true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openPasswordWizard() {
|
openPasswordWizard() {
|
||||||
this.close();
|
this.close();
|
||||||
this.application.presentPasswordWizard();
|
this.application!.presentPasswordWizard(PasswordWizardType.ChangePassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
async openPrivilegesModal() {
|
async openPrivilegesModal() {
|
||||||
this.close();
|
this.close();
|
||||||
const run = () => {
|
const run = () => {
|
||||||
this.application.presentPrivilegesManagementModal();
|
this.application!.presentPrivilegesManagementModal();
|
||||||
};
|
};
|
||||||
const needsPrivilege = await this.application.privilegesService.actionRequiresPrivilege(
|
const needsPrivilege = await this.application!.privilegesService!.actionRequiresPrivilege(
|
||||||
ProtectedAction.ManagePrivileges
|
ProtectedAction.ManagePrivileges
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.application.presentPrivilegesModal(
|
this.application!.presentPrivilegesModal(
|
||||||
ProtectedAction.ManagePrivileges,
|
ProtectedAction.ManagePrivileges,
|
||||||
() => {
|
() => {
|
||||||
run();
|
run();
|
||||||
@@ -293,33 +339,37 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroyLocalData() {
|
destroyLocalData() {
|
||||||
this.application.alertService.confirm({
|
this.application!.alertService!.confirm(
|
||||||
text: STRING_SIGN_OUT_CONFIRMATION,
|
STRING_SIGN_OUT_CONFIRMATION,
|
||||||
destructive: true,
|
undefined,
|
||||||
onConfirm: async () => {
|
undefined,
|
||||||
await this.application.signOut();
|
undefined,
|
||||||
}
|
async () => {
|
||||||
});
|
await this.application!.signOut();
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async submitImportPassword() {
|
async submitImportPassword() {
|
||||||
await this.performImport(
|
await this.performImport(
|
||||||
this.state.importData.data,
|
this.getState().importData.data,
|
||||||
this.state.importData.password
|
this.getState().importData.password
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async readFile(file) {
|
async readFile(file: File): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = function (e) {
|
reader.onload = (e) => {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(e.target.result);
|
const data = JSON.parse(e.target!.result as string);
|
||||||
resolve(data);
|
resolve(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: STRING_INVALID_IMPORT_FILE
|
STRING_INVALID_IMPORT_FILE
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
@@ -329,7 +379,7 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
/**
|
/**
|
||||||
* @template
|
* @template
|
||||||
*/
|
*/
|
||||||
async importFileSelected(files) {
|
async importFileSelected(files: File[]) {
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
const data = await this.readFile(file);
|
const data = await this.readFile(file);
|
||||||
@@ -339,7 +389,7 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
if (data.auth_params) {
|
if (data.auth_params) {
|
||||||
await this.setState({
|
await this.setState({
|
||||||
importData: {
|
importData: {
|
||||||
...this.state.importData,
|
...this.getState().importData,
|
||||||
requestPassword: true,
|
requestPassword: true,
|
||||||
data: data
|
data: data
|
||||||
}
|
}
|
||||||
@@ -351,14 +401,14 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
element.scrollIntoView(false);
|
element.scrollIntoView(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await this.performImport(data, null);
|
await this.performImport(data, undefined);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const needsPrivilege = await this.application.privilegesService.actionRequiresPrivilege(
|
const needsPrivilege = await this.application!.privilegesService!.actionRequiresPrivilege(
|
||||||
ProtectedAction.ManageBackups
|
ProtectedAction.ManageBackups
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.application.presentPrivilegesModal(
|
this.application!.presentPrivilegesModal(
|
||||||
ProtectedAction.ManageBackups,
|
ProtectedAction.ManageBackups,
|
||||||
run
|
run
|
||||||
);
|
);
|
||||||
@@ -367,10 +417,10 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async performImport(data, password) {
|
async performImport(data: any, password?: string) {
|
||||||
await this.setState({
|
await this.setState({
|
||||||
importData: {
|
importData: {
|
||||||
...this.state.importData,
|
...this.getState().importData,
|
||||||
loading: true
|
loading: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -380,44 +430,35 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
});
|
});
|
||||||
if (errorCount > 0) {
|
if (errorCount > 0) {
|
||||||
const message = StringImportError(errorCount);
|
const message = StringImportError(errorCount);
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: message
|
message
|
||||||
});
|
);
|
||||||
} else {
|
} else {
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: STRING_IMPORT_SUCCESS
|
STRING_IMPORT_SUCCESS
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async importJSONData(data, password) {
|
async importJSONData(data: BackupFile, password?: string) {
|
||||||
const { affectedItems, errorCount } = await this.application.importData({
|
const { errorCount } = await this.application!.importData(
|
||||||
data: data.items,
|
data,
|
||||||
password: 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
|
|
||||||
*/
|
|
||||||
if (item.content_type === 'SN|Component') {
|
|
||||||
item.active = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errorCount;
|
return errorCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadDataArchive() {
|
async downloadDataArchive() {
|
||||||
this.application.getArchiveService().downloadBackup(this.state.mutable.backupEncrypted);
|
this.application!.getArchiveService().downloadBackup(this.getState().mutable.backupEncrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
notesAndTagsCount() {
|
notesAndTagsCount() {
|
||||||
return this.application.getItems({
|
return this.application!.getItems(
|
||||||
contentType: [
|
[
|
||||||
'Note',
|
ContentType.Note,
|
||||||
'Tag'
|
ContentType.Tag
|
||||||
]
|
]
|
||||||
}).length;
|
).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptionStatusForNotes() {
|
encryptionStatusForNotes() {
|
||||||
@@ -426,22 +467,22 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async reloadAutoLockInterval() {
|
async reloadAutoLockInterval() {
|
||||||
const interval = await this.application.getLockService().getAutoLockInterval();
|
const interval = await this.application!.getLockService().getAutoLockInterval();
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedAutoLockInterval: interval
|
selectedAutoLockInterval: interval
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectAutoLockInterval(interval) {
|
async selectAutoLockInterval(interval: number) {
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
await this.application.getLockService().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(
|
||||||
ProtectedAction.ManagePasscode
|
ProtectedAction.ManagePasscode
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.application.presentPrivilegesModal(
|
this.application!.presentPrivilegesModal(
|
||||||
ProtectedAction.ManagePasscode,
|
ProtectedAction.ManagePasscode,
|
||||||
() => {
|
() => {
|
||||||
run();
|
run();
|
||||||
@@ -456,13 +497,13 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
this.setFormDataState({
|
this.setFormDataState({
|
||||||
showLogin: false,
|
showLogin: false,
|
||||||
showRegister: false,
|
showRegister: false,
|
||||||
user_password: null,
|
user_password: undefined,
|
||||||
password_conf: null
|
password_conf: undefined
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPasscode() {
|
hasPasscode() {
|
||||||
return this.passcodeManager.hasPasscode();
|
return this.application!.hasPasscode();
|
||||||
}
|
}
|
||||||
|
|
||||||
addPasscodeClicked() {
|
addPasscodeClicked() {
|
||||||
@@ -472,20 +513,20 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
submitPasscodeForm() {
|
submitPasscodeForm() {
|
||||||
const passcode = this.state.formData.passcode;
|
const passcode = this.getState().formData.passcode!;
|
||||||
if (passcode !== this.state.formData.confirmPasscode) {
|
if (passcode !== this.getState().formData.confirmPasscode!) {
|
||||||
this.application.alertService.alert({
|
this.application!.alertService!.alert(
|
||||||
text: STRING_NON_MATCHING_PASSCODES
|
STRING_NON_MATCHING_PASSCODES
|
||||||
});
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(this.state.formData.changingPasscode
|
(this.getState().formData.changingPasscode
|
||||||
? this.application.changePasscode(passcode)
|
? this.application!.changePasscode(passcode)
|
||||||
: this.application.setPasscode(passcode)
|
: this.application!.setPasscode(passcode)
|
||||||
).then(() => {
|
).then(() => {
|
||||||
this.setFormDataState({
|
this.setFormDataState({
|
||||||
passcode: null,
|
passcode: undefined,
|
||||||
confirmPasscode: null,
|
confirmPasscode: undefined,
|
||||||
showPasscodeForm: false
|
showPasscodeForm: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -493,14 +534,14 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
|
|
||||||
async changePasscodePressed() {
|
async changePasscodePressed() {
|
||||||
const run = () => {
|
const run = () => {
|
||||||
this.state.formData.changingPasscode = true;
|
this.getState().formData.changingPasscode = true;
|
||||||
this.addPasscodeClicked();
|
this.addPasscodeClicked();
|
||||||
};
|
};
|
||||||
const needsPrivilege = await this.application.privilegesService.actionRequiresPrivilege(
|
const needsPrivilege = await this.application!.privilegesService!.actionRequiresPrivilege(
|
||||||
ProtectedAction.ManagePasscode
|
ProtectedAction.ManagePasscode
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.application.presentPrivilegesModal(
|
this.application!.presentPrivilegesModal(
|
||||||
ProtectedAction.ManagePasscode,
|
ProtectedAction.ManagePasscode,
|
||||||
run
|
run
|
||||||
);
|
);
|
||||||
@@ -511,24 +552,28 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
|
|
||||||
async removePasscodePressed() {
|
async removePasscodePressed() {
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
const signedIn = !isNullOrUndefined(await this.application.getUser());
|
const signedIn = !isNullOrUndefined(await this.application!.getUser());
|
||||||
let message = STRING_REMOVE_PASSCODE_CONFIRMATION;
|
let message = STRING_REMOVE_PASSCODE_CONFIRMATION;
|
||||||
if (!signedIn) {
|
if (!signedIn) {
|
||||||
message += STRING_REMOVE_PASSCODE_OFFLINE_ADDENDUM;
|
message += STRING_REMOVE_PASSCODE_OFFLINE_ADDENDUM;
|
||||||
}
|
}
|
||||||
this.application.alertService.confirm({
|
this.application!.alertService!.confirm(
|
||||||
text: message,
|
message,
|
||||||
destructive: true,
|
undefined,
|
||||||
onConfirm: () => {
|
undefined,
|
||||||
this.application.removePasscode();
|
undefined,
|
||||||
}
|
() => {
|
||||||
});
|
this.application!.removePasscode();
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
const needsPrivilege = await this.application.privilegesService.actionRequiresPrivilege(
|
const needsPrivilege = await this.application!.privilegesService!.actionRequiresPrivilege(
|
||||||
ProtectedAction.ManagePasscode
|
ProtectedAction.ManagePasscode
|
||||||
);
|
);
|
||||||
if (needsPrivilege) {
|
if (needsPrivilege) {
|
||||||
this.application.presentPrivilegesModal(
|
this.application!.presentPrivilegesModal(
|
||||||
ProtectedAction.ManagePasscode,
|
ProtectedAction.ManagePasscode,
|
||||||
run
|
run
|
||||||
);
|
);
|
||||||
@@ -542,8 +587,9 @@ class AccountMenuCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AccountMenu {
|
export class AccountMenu extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
super();
|
||||||
this.restrict = 'E';
|
this.restrict = 'E';
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.controller = AccountMenuCtrl;
|
this.controller = AccountMenuCtrl;
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { WebApplication } from './../application';
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import { AppStateEvent } from '@/services/state';
|
import { AppStateEvent } from '@/services/state';
|
||||||
|
|
||||||
@@ -7,12 +8,20 @@ const LOCK_INTERVAL_NONE = 0;
|
|||||||
const LOCK_INTERVAL_IMMEDIATE = 1;
|
const LOCK_INTERVAL_IMMEDIATE = 1;
|
||||||
const LOCK_INTERVAL_ONE_MINUTE = 60 * MILLISECONDS_PER_SECOND;
|
const LOCK_INTERVAL_ONE_MINUTE = 60 * MILLISECONDS_PER_SECOND;
|
||||||
const LOCK_INTERVAL_FIVE_MINUTES = 300 * MILLISECONDS_PER_SECOND;
|
const LOCK_INTERVAL_FIVE_MINUTES = 300 * MILLISECONDS_PER_SECOND;
|
||||||
const LOCK_INTERVAL_ONE_HOUR= 3600 * MILLISECONDS_PER_SECOND;
|
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 {
|
||||||
constructor(application) {
|
|
||||||
|
private application: WebApplication
|
||||||
|
private unsubState: any
|
||||||
|
private pollFocusInterval: any
|
||||||
|
private lastFocusState?: 'hidden' | 'visible'
|
||||||
|
private lockAfterDate?: Date
|
||||||
|
private lockTimeout?: any
|
||||||
|
|
||||||
|
constructor(application: WebApplication) {
|
||||||
this.application = application;
|
this.application = application;
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this.observeVisibility();
|
this.observeVisibility();
|
||||||
@@ -20,13 +29,15 @@ export class LockManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
observeVisibility() {
|
observeVisibility() {
|
||||||
this.unsubState = this.application.getAppState().addObserver((eventName) => {
|
this.unsubState = this.application.getAppState().addObserver(
|
||||||
if(eventName === AppStateEvent.WindowDidBlur) {
|
async (eventName) => {
|
||||||
this.documentVisibilityChanged(false);
|
if (eventName === AppStateEvent.WindowDidBlur) {
|
||||||
} else if(eventName === AppStateEvent.WindowDidFocus) {
|
this.documentVisibilityChanged(false);
|
||||||
this.documentVisibilityChanged(true);
|
} else if (eventName === AppStateEvent.WindowDidFocus) {
|
||||||
|
this.documentVisibilityChanged(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
if (!isDesktopApplication()) {
|
if (!isDesktopApplication()) {
|
||||||
this.beginWebFocusPolling();
|
this.beginWebFocusPolling();
|
||||||
}
|
}
|
||||||
@@ -39,15 +50,18 @@ export class LockManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async setAutoLockInterval(interval) {
|
async setAutoLockInterval(interval: number) {
|
||||||
return this.application.setValue(STORAGE_KEY_AUTOLOCK_INTERVAL, interval);
|
return this.application!.setValue(
|
||||||
|
STORAGE_KEY_AUTOLOCK_INTERVAL,
|
||||||
|
interval
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAutoLockInterval() {
|
async getAutoLockInterval() {
|
||||||
const interval = await this.application.getValue(
|
const interval = await this.application!.getValue(
|
||||||
STORAGE_KEY_AUTOLOCK_INTERVAL,
|
STORAGE_KEY_AUTOLOCK_INTERVAL
|
||||||
);
|
);
|
||||||
if(interval) {
|
if (interval) {
|
||||||
return interval;
|
return interval;
|
||||||
} else {
|
} else {
|
||||||
return LOCK_INTERVAL_NONE;
|
return LOCK_INTERVAL_NONE;
|
||||||
@@ -61,9 +75,9 @@ export class LockManager {
|
|||||||
beginWebFocusPolling() {
|
beginWebFocusPolling() {
|
||||||
this.pollFocusInterval = 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);
|
||||||
} else if(!hasFocus && this.lastFocusState === 'visible') {
|
} else if (!hasFocus && this.lastFocusState === 'visible') {
|
||||||
this.documentVisibilityChanged(false);
|
this.documentVisibilityChanged(false);
|
||||||
}
|
}
|
||||||
/* Save this to compare against next time around */
|
/* Save this to compare against next time around */
|
||||||
@@ -96,10 +110,10 @@ export class LockManager {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
async documentVisibilityChanged(visible) {
|
async documentVisibilityChanged(visible: boolean) {
|
||||||
if(visible) {
|
if (visible) {
|
||||||
const locked = await this.application.isLocked();
|
const locked = await this.application.isLocked();
|
||||||
if(
|
if (
|
||||||
!locked &&
|
!locked &&
|
||||||
this.lockAfterDate &&
|
this.lockAfterDate &&
|
||||||
new Date() > this.lockAfterDate
|
new Date() > this.lockAfterDate
|
||||||
@@ -114,7 +128,7 @@ export class LockManager {
|
|||||||
|
|
||||||
async beginAutoLockTimer() {
|
async beginAutoLockTimer() {
|
||||||
var interval = await this.getAutoLockInterval();
|
var interval = await this.getAutoLockInterval();
|
||||||
if(interval === LOCK_INTERVAL_NONE) {
|
if (interval === LOCK_INTERVAL_NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -123,7 +137,7 @@ export class LockManager {
|
|||||||
* persisted, as living in memory is sufficient. If memory is cleared, then the
|
* persisted, as living in memory is sufficient. If memory is cleared, then the
|
||||||
* application will lock anyway.
|
* application will lock anyway.
|
||||||
*/
|
*/
|
||||||
const addToNow = (seconds) => {
|
const addToNow = (seconds: number) => {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
date.setSeconds(date.getSeconds() + seconds);
|
date.setSeconds(date.getSeconds() + seconds);
|
||||||
return date;
|
return date;
|
||||||
@@ -132,12 +146,12 @@ export class LockManager {
|
|||||||
this.lockTimeout = setTimeout(() => {
|
this.lockTimeout = setTimeout(() => {
|
||||||
this.cancelAutoLockTimer();
|
this.cancelAutoLockTimer();
|
||||||
this.application.lock();
|
this.application.lock();
|
||||||
this.lockAfterDate = null;
|
this.lockAfterDate = undefined;
|
||||||
}, interval);
|
}, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelAutoLockTimer() {
|
cancelAutoLockTimer() {
|
||||||
clearTimeout(this.lockTimeout);
|
clearTimeout(this.lockTimeout);
|
||||||
this.lockAfterDate = null;
|
this.lockAfterDate = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user