feat: clear protection session
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { WebDirective } from './../../types';
|
||||
import { isDesktopApplication, preventRefreshing } from '@/utils';
|
||||
import { isDesktopApplication, isSameDay, preventRefreshing } from '@/utils';
|
||||
import template from '%/directives/account-menu.pug';
|
||||
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||
import {
|
||||
@@ -18,17 +18,22 @@ import {
|
||||
STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_CHANGE,
|
||||
STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL,
|
||||
STRING_UNSUPPORTED_BACKUP_FILE_VERSION,
|
||||
Strings
|
||||
Strings,
|
||||
} from '@/strings';
|
||||
import { PasswordWizardType } from '@/types';
|
||||
import { BackupFile, ContentType, Platform } from '@standardnotes/snjs';
|
||||
import {
|
||||
ApplicationEvent,
|
||||
BackupFile,
|
||||
ContentType,
|
||||
Platform,
|
||||
} from '@standardnotes/snjs';
|
||||
import { confirmDialog, alertDialog } from '@/services/alertService';
|
||||
import { autorun, IReactionDisposer } from 'mobx';
|
||||
import { storage, StorageKey } from '@/services/localStorage';
|
||||
import {
|
||||
disableErrorReporting,
|
||||
enableErrorReporting,
|
||||
errorReportingId
|
||||
errorReportingId,
|
||||
} from '@/services/errorReporting';
|
||||
|
||||
const ELEMENT_NAME_AUTH_EMAIL = 'email';
|
||||
@@ -52,7 +57,7 @@ type FormData = {
|
||||
passcode: string;
|
||||
confirmPasscode: string;
|
||||
changingPasscode: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
type AccountMenuState = {
|
||||
formData: Partial<FormData>;
|
||||
@@ -72,21 +77,19 @@ type AccountMenuState = {
|
||||
showSessions: boolean;
|
||||
errorReportingId: string | null;
|
||||
keyStorageInfo: string | null;
|
||||
}
|
||||
protectionsDisabledUntil: string | null;
|
||||
};
|
||||
|
||||
class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
|
||||
public appVersion: string
|
||||
public appVersion: string;
|
||||
/** @template */
|
||||
private closeFunction?: () => void
|
||||
private removeBetaWarningListener?: IReactionDisposer
|
||||
private removeSyncObserver?: IReactionDisposer
|
||||
private closeFunction?: () => void;
|
||||
private removeBetaWarningListener?: IReactionDisposer;
|
||||
private removeSyncObserver?: IReactionDisposer;
|
||||
private removeProtectionLengthObserver?: () => void;
|
||||
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
$timeout: ng.ITimeoutService,
|
||||
appVersion: string,
|
||||
) {
|
||||
constructor($timeout: ng.ITimeoutService, appVersion: string) {
|
||||
super($timeout);
|
||||
this.appVersion = appVersion;
|
||||
}
|
||||
@@ -95,7 +98,9 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
getInitialState() {
|
||||
return {
|
||||
appVersion: 'v' + ((window as any).electronAppVersion || this.appVersion),
|
||||
passcodeAutoLockOptions: this.application.getAutolockService().getAutoLockIntervalOptions(),
|
||||
passcodeAutoLockOptions: this.application
|
||||
.getAutolockService()
|
||||
.getAutoLockIntervalOptions(),
|
||||
user: this.application.getUser(),
|
||||
formData: {
|
||||
mergeLocal: true,
|
||||
@@ -103,12 +108,14 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
},
|
||||
mutable: {},
|
||||
showBetaWarning: false,
|
||||
errorReportingEnabled: storage.get(StorageKey.DisableErrorReporting) === false,
|
||||
errorReportingEnabled:
|
||||
storage.get(StorageKey.DisableErrorReporting) === false,
|
||||
showSessions: false,
|
||||
errorReportingId: errorReportingId(),
|
||||
keyStorageInfo: Strings.keyStorageInfo(this.application),
|
||||
importData: null,
|
||||
syncInProgress: false,
|
||||
protectionsDisabledUntil: this.getProtectionsDisabledUntil(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -134,14 +141,16 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
user: this.application.getUser(),
|
||||
canAddPasscode: !this.application.isEphemeralSession(),
|
||||
hasPasscode: this.application.hasPasscode(),
|
||||
showPasscodeForm: false
|
||||
showPasscodeForm: false,
|
||||
};
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
super.$onInit();
|
||||
this.setState({
|
||||
showSessions: this.appState.enableUnfinishedFeatures && await this.application.userCanManageSessions()
|
||||
showSessions:
|
||||
this.appState.enableUnfinishedFeatures &&
|
||||
(await this.application.userCanManageSessions()),
|
||||
});
|
||||
|
||||
const sync = this.appState.sync;
|
||||
@@ -153,14 +162,24 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
});
|
||||
this.removeBetaWarningListener = autorun(() => {
|
||||
this.setState({
|
||||
showBetaWarning: this.appState.showBetaWarning
|
||||
showBetaWarning: this.appState.showBetaWarning,
|
||||
});
|
||||
});
|
||||
|
||||
this.removeProtectionLengthObserver = this.application.addEventObserver(
|
||||
async () => {
|
||||
this.setState({
|
||||
protectionsDisabledUntil: this.getProtectionsDisabledUntil(),
|
||||
});
|
||||
},
|
||||
ApplicationEvent.ProtectionSessionExpiryDateChanged
|
||||
);
|
||||
}
|
||||
|
||||
deinit() {
|
||||
this.removeSyncObserver?.();
|
||||
this.removeBetaWarningListener?.();
|
||||
this.removeProtectionLengthObserver?.();
|
||||
super.deinit();
|
||||
}
|
||||
|
||||
@@ -170,17 +189,46 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
});
|
||||
}
|
||||
|
||||
private getProtectionsDisabledUntil(): string | null {
|
||||
const protectionExpiry = this.application.getProtectionSessionExpiryDate();
|
||||
const now = new Date();
|
||||
if (protectionExpiry > now) {
|
||||
let f: Intl.DateTimeFormat;
|
||||
if (isSameDay(protectionExpiry, now)) {
|
||||
f = new Intl.DateTimeFormat(undefined, {
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
});
|
||||
} else {
|
||||
f = new Intl.DateTimeFormat(undefined, {
|
||||
weekday: 'long',
|
||||
day: 'numeric',
|
||||
month: 'short',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
});
|
||||
}
|
||||
|
||||
return f.format(protectionExpiry);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async loadHost() {
|
||||
const host = await this.application!.getHost();
|
||||
const host = await this.application.getHost();
|
||||
this.setState({
|
||||
server: host,
|
||||
formData: {
|
||||
...this.getState().formData,
|
||||
url: host
|
||||
}
|
||||
url: host,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
enableProtections() {
|
||||
this.application.clearProtectionSession();
|
||||
}
|
||||
|
||||
onHostInputChange() {
|
||||
const url = this.getState().formData.url!;
|
||||
this.application!.setHost(url);
|
||||
@@ -200,8 +248,8 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
encryptionEnabled,
|
||||
mutable: {
|
||||
...this.getState().mutable,
|
||||
backupEncrypted: encryptionEnabled
|
||||
}
|
||||
backupEncrypted: encryptionEnabled,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -213,7 +261,7 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
const names = [
|
||||
ELEMENT_NAME_AUTH_EMAIL,
|
||||
ELEMENT_NAME_AUTH_PASSWORD,
|
||||
ELEMENT_NAME_AUTH_PASSWORD_CONF
|
||||
ELEMENT_NAME_AUTH_PASSWORD_CONF,
|
||||
];
|
||||
for (const name of names) {
|
||||
const element = document.getElementsByName(name)[0];
|
||||
@@ -224,7 +272,10 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
}
|
||||
|
||||
submitAuthForm() {
|
||||
if (!this.getState().formData.email || !this.getState().formData.user_password) {
|
||||
if (
|
||||
!this.getState().formData.email ||
|
||||
!this.getState().formData.user_password
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.blurAuthFields();
|
||||
@@ -239,15 +290,15 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
return this.setState({
|
||||
formData: {
|
||||
...this.getState().formData,
|
||||
...formData
|
||||
}
|
||||
...formData,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async login() {
|
||||
await this.setFormDataState({
|
||||
status: STRING_GENERATING_LOGIN_KEYS,
|
||||
authenticating: true
|
||||
authenticating: true,
|
||||
});
|
||||
const formData = this.getState().formData;
|
||||
const response = await this.application!.signIn(
|
||||
@@ -261,7 +312,7 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
if (!error) {
|
||||
await this.setFormDataState({
|
||||
authenticating: false,
|
||||
user_password: undefined
|
||||
user_password: undefined,
|
||||
});
|
||||
this.close();
|
||||
return;
|
||||
@@ -269,28 +320,26 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
await this.setFormDataState({
|
||||
showLogin: true,
|
||||
status: undefined,
|
||||
user_password: undefined
|
||||
user_password: undefined,
|
||||
});
|
||||
if (error.message) {
|
||||
this.application!.alertService!.alert(error.message);
|
||||
}
|
||||
await this.setFormDataState({
|
||||
authenticating: false
|
||||
authenticating: false,
|
||||
});
|
||||
}
|
||||
|
||||
async register() {
|
||||
const confirmation = this.getState().formData.password_conf;
|
||||
if (confirmation !== this.getState().formData.user_password) {
|
||||
this.application!.alertService!.alert(
|
||||
STRING_NON_MATCHING_PASSWORDS
|
||||
);
|
||||
this.application!.alertService!.alert(STRING_NON_MATCHING_PASSWORDS);
|
||||
return;
|
||||
}
|
||||
await this.setFormDataState({
|
||||
confirmPassword: false,
|
||||
status: STRING_GENERATING_REGISTER_KEYS,
|
||||
authenticating: true
|
||||
authenticating: true,
|
||||
});
|
||||
const response = await this.application!.register(
|
||||
this.getState().formData.email!,
|
||||
@@ -301,14 +350,12 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
const error = response.error;
|
||||
if (error) {
|
||||
await this.setFormDataState({
|
||||
status: undefined
|
||||
status: undefined,
|
||||
});
|
||||
await this.setFormDataState({
|
||||
authenticating: false
|
||||
authenticating: false,
|
||||
});
|
||||
this.application!.alertService!.alert(
|
||||
error.message
|
||||
);
|
||||
this.application!.alertService!.alert(error.message);
|
||||
} else {
|
||||
await this.setFormDataState({ authenticating: false });
|
||||
this.close();
|
||||
@@ -320,8 +367,8 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
this.setFormDataState({
|
||||
mergeLocal: !(await confirmDialog({
|
||||
text: STRING_ACCOUNT_MENU_UNCHECK_MERGE,
|
||||
confirmButtonStyle: 'danger'
|
||||
}))
|
||||
confirmButtonStyle: 'danger',
|
||||
})),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -337,17 +384,19 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
}
|
||||
|
||||
async destroyLocalData() {
|
||||
if (await confirmDialog({
|
||||
if (
|
||||
await confirmDialog({
|
||||
text: STRING_SIGN_OUT_CONFIRMATION,
|
||||
confirmButtonStyle: "danger"
|
||||
})) {
|
||||
confirmButtonStyle: 'danger',
|
||||
})
|
||||
) {
|
||||
this.application.signOut();
|
||||
}
|
||||
}
|
||||
|
||||
showRegister() {
|
||||
this.setFormDataState({
|
||||
showRegister: true
|
||||
showRegister: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -359,9 +408,7 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
const data = JSON.parse(e.target!.result as string);
|
||||
resolve(data);
|
||||
} catch (e) {
|
||||
this.application!.alertService!.alert(
|
||||
STRING_INVALID_IMPORT_FILE
|
||||
);
|
||||
this.application!.alertService!.alert(STRING_INVALID_IMPORT_FILE);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
@@ -378,7 +425,8 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
return;
|
||||
}
|
||||
if (data.version || data.auth_params || data.keyParams) {
|
||||
const version = data.version || data.keyParams?.version || data.auth_params?.version;
|
||||
const version =
|
||||
data.version || data.keyParams?.version || data.auth_params?.version;
|
||||
if (
|
||||
this.application.protocolService.supportedVersions().includes(version)
|
||||
) {
|
||||
@@ -396,52 +444,50 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
await this.setState({
|
||||
importData: {
|
||||
...this.getState().importData,
|
||||
loading: true
|
||||
}
|
||||
loading: true,
|
||||
},
|
||||
});
|
||||
const result = await this.application.importData(data);
|
||||
this.setState({
|
||||
importData: null
|
||||
importData: null,
|
||||
});
|
||||
if (!result) {
|
||||
return;
|
||||
} else if ('error' in result) {
|
||||
void alertDialog({
|
||||
text: result.error
|
||||
text: result.error,
|
||||
});
|
||||
} else if (result.errorCount) {
|
||||
void alertDialog({
|
||||
text: StringImportError(result.errorCount)
|
||||
text: StringImportError(result.errorCount),
|
||||
});
|
||||
} else {
|
||||
void alertDialog({
|
||||
text: STRING_IMPORT_SUCCESS
|
||||
text: STRING_IMPORT_SUCCESS,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async downloadDataArchive() {
|
||||
this.application.getArchiveService().downloadBackup(this.getState().mutable.backupEncrypted);
|
||||
this.application
|
||||
.getArchiveService()
|
||||
.downloadBackup(this.getState().mutable.backupEncrypted);
|
||||
}
|
||||
|
||||
notesAndTagsCount() {
|
||||
return this.application.getItems(
|
||||
[
|
||||
ContentType.Note,
|
||||
ContentType.Tag
|
||||
]
|
||||
).length;
|
||||
return this.application.getItems([ContentType.Note, ContentType.Tag])
|
||||
.length;
|
||||
}
|
||||
|
||||
encryptionStatusForNotes() {
|
||||
const length = this.notesAndTagsCount();
|
||||
return length + "/" + length + " notes and tags encrypted";
|
||||
return length + '/' + length + ' notes and tags encrypted';
|
||||
}
|
||||
|
||||
async reloadAutoLockInterval() {
|
||||
const interval = await this.application!.getAutolockService().getAutoLockInterval();
|
||||
this.setState({
|
||||
selectedAutoLockInterval: interval
|
||||
selectedAutoLockInterval: interval,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -458,7 +504,7 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
showLogin: false,
|
||||
showRegister: false,
|
||||
user_password: undefined,
|
||||
password_conf: undefined
|
||||
password_conf: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -468,30 +514,31 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
|
||||
addPasscodeClicked() {
|
||||
this.setFormDataState({
|
||||
showPasscodeForm: true
|
||||
showPasscodeForm: true,
|
||||
});
|
||||
}
|
||||
|
||||
async submitPasscodeForm() {
|
||||
const passcode = this.getState().formData.passcode!;
|
||||
if (passcode !== this.getState().formData.confirmPasscode!) {
|
||||
this.application!.alertService!.alert(
|
||||
STRING_NON_MATCHING_PASSCODES
|
||||
);
|
||||
this.application!.alertService!.alert(STRING_NON_MATCHING_PASSCODES);
|
||||
return;
|
||||
}
|
||||
|
||||
await preventRefreshing(STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_CHANGE, async () => {
|
||||
await preventRefreshing(
|
||||
STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_CHANGE,
|
||||
async () => {
|
||||
if (this.application!.hasPasscode()) {
|
||||
await this.application!.changePasscode(passcode);
|
||||
} else {
|
||||
await this.application!.setPasscode(passcode);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
this.setFormDataState({
|
||||
passcode: undefined,
|
||||
confirmPasscode: undefined,
|
||||
showPasscodeForm: false
|
||||
showPasscodeForm: false,
|
||||
});
|
||||
this.refreshEncryptionStatus();
|
||||
}
|
||||
@@ -502,13 +549,18 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
}
|
||||
|
||||
async removePasscodePressed() {
|
||||
await preventRefreshing(STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL, async () => {
|
||||
await preventRefreshing(
|
||||
STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL,
|
||||
async () => {
|
||||
if (await this.application!.removePasscode()) {
|
||||
await this.application.getAutolockService().deleteAutolockPreference();
|
||||
await this.application
|
||||
.getAutolockService()
|
||||
.deleteAutolockPreference();
|
||||
await this.reloadAutoLockInterval();
|
||||
this.refreshEncryptionStatus();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
openErrorReportingDialog() {
|
||||
@@ -526,7 +578,7 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
|
||||
anonymized. We use error reports to be alerted when something in our
|
||||
code is causing unexpected errors and crashes in your application
|
||||
experience.
|
||||
`
|
||||
`,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -556,7 +608,7 @@ export class AccountMenu extends WebDirective {
|
||||
this.bindToController = true;
|
||||
this.scope = {
|
||||
closeFunction: '&',
|
||||
application: '='
|
||||
application: '=',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Platform, platformFromString } from "@standardnotes/snjs";
|
||||
import { Platform, platformFromString } from '@standardnotes/snjs';
|
||||
|
||||
declare const process : {
|
||||
declare const process: {
|
||||
env: {
|
||||
NODE_ENV: string | null | undefined
|
||||
}
|
||||
NODE_ENV: string | null | undefined;
|
||||
};
|
||||
};
|
||||
|
||||
export const isDev = process.env.NODE_ENV === 'development';
|
||||
@@ -36,11 +36,10 @@ let sharedDateFormatter: Intl.DateTimeFormat;
|
||||
export function dateToLocalizedString(date: Date) {
|
||||
if (typeof Intl !== 'undefined' && Intl.DateTimeFormat) {
|
||||
if (!sharedDateFormatter) {
|
||||
const locale = (
|
||||
(navigator.languages && navigator.languages.length)
|
||||
const locale =
|
||||
navigator.languages && navigator.languages.length
|
||||
? navigator.languages[0]
|
||||
: navigator.language
|
||||
);
|
||||
: navigator.language;
|
||||
sharedDateFormatter = new Intl.DateTimeFormat(locale, {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
@@ -58,8 +57,21 @@ export function dateToLocalizedString(date: Date) {
|
||||
}
|
||||
}
|
||||
|
||||
export function isSameDay(dateA: Date, dateB: Date): boolean {
|
||||
return (
|
||||
dateA.getFullYear() === dateB.getFullYear() &&
|
||||
dateA.getMonth() === dateB.getMonth() &&
|
||||
dateA.getDate() === dateB.getDate()
|
||||
);
|
||||
}
|
||||
|
||||
/** Via https://davidwalsh.name/javascript-debounce-function */
|
||||
export function debounce(this: any, func: any, wait: number, immediate = false) {
|
||||
export function debounce(
|
||||
this: any,
|
||||
func: any,
|
||||
wait: number,
|
||||
immediate = false
|
||||
) {
|
||||
let timeout: any;
|
||||
return () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
@@ -131,7 +143,7 @@ if (!Array.prototype.includes) {
|
||||
|
||||
// 8. Return false
|
||||
return false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -153,7 +165,9 @@ declare const __WEB__: boolean;
|
||||
declare const __DESKTOP__: boolean;
|
||||
|
||||
if (!__WEB__ && !__DESKTOP__) {
|
||||
throw Error('Neither __WEB__ nor __DESKTOP__ is true. Check your configuration files.');
|
||||
throw Error(
|
||||
'Neither __WEB__ nor __DESKTOP__ is true. Check your configuration files.'
|
||||
);
|
||||
}
|
||||
|
||||
export function isDesktopApplication() {
|
||||
|
||||
@@ -164,6 +164,19 @@
|
||||
| {{self.encryptionStatusForNotes()}}
|
||||
p.sk-p
|
||||
| {{self.state.encryptionStatusString}}
|
||||
.sk-panel-section
|
||||
.sk-panel-section-title Protections
|
||||
.sk-panel-section-subtitle.info(ng-if="self.state.protectionsDisabledUntil")
|
||||
| Protections are disabled until {{self.state.protectionsDisabledUntil}}
|
||||
.sk-panel-section-subtitle.info(ng-if="!self.state.protectionsDisabledUntil")
|
||||
| Protections are enabled
|
||||
p.sk-p
|
||||
| Actions like viewing protected notes, exporting decrypted backups,
|
||||
| or revoking an active session, require additional authentication
|
||||
| like entering your account password or application passcode.
|
||||
.sk-panel-row(ng-if="self.state.protectionsDisabledUntil")
|
||||
button.sk-button.info(ng-click="self.enableProtections()")
|
||||
span.sk-label Enable protections
|
||||
.sk-panel-section
|
||||
.sk-panel-section-title Passcode Lock
|
||||
div(ng-if='!self.state.hasPasscode')
|
||||
@@ -206,8 +219,7 @@
|
||||
ng-click='self.state.formData.showPasscodeForm = false'
|
||||
) Cancel
|
||||
div(ng-if='self.state.hasPasscode && !self.state.formData.showPasscodeForm')
|
||||
.sk-p
|
||||
| Passcode lock is enabled.
|
||||
.sk-panel-section-subtitle.info Passcode lock is enabled
|
||||
.sk-notification.contrast
|
||||
.sk-notification-title Options
|
||||
.sk-notification-text
|
||||
@@ -273,7 +285,7 @@
|
||||
.sk-panel-section
|
||||
.sk-panel-section-title Error Reporting
|
||||
.sk-panel-section-subtitle.info
|
||||
| Automatic error reporting is {{ self.state.errorReportingEnabled ? 'enabled.' : 'disabled.' }}
|
||||
| Automatic error reporting is {{ self.state.errorReportingEnabled ? 'enabled' : 'disabled' }}
|
||||
p.sk-p
|
||||
| Help us improve Standard Notes by automatically submitting
|
||||
| anonymized error reports.
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
"@reach/alert-dialog": "^0.13.0",
|
||||
"@reach/dialog": "^0.13.0",
|
||||
"@standardnotes/sncrypto-web": "^1.2.10",
|
||||
"@standardnotes/snjs": "^2.0.53",
|
||||
"@standardnotes/snjs": "^2.0.54",
|
||||
"mobx": "^6.1.6",
|
||||
"preact": "^10.5.12"
|
||||
}
|
||||
|
||||
@@ -1845,10 +1845,10 @@
|
||||
"@standardnotes/sncrypto-common" "^1.2.7"
|
||||
libsodium-wrappers "^0.7.8"
|
||||
|
||||
"@standardnotes/snjs@^2.0.53":
|
||||
version "2.0.53"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.53.tgz#ec89668fef57bf154dc0e145e4bc883cbe6be241"
|
||||
integrity sha512-9mlSitWXCBnQtMwhHMIV6/BaLIUXzWuQIMKkqWn43XYojnF33avEJteu0ciffZMAW9A2S7ORerRBVBbJxlqtdg==
|
||||
"@standardnotes/snjs@^2.0.54":
|
||||
version "2.0.54"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.54.tgz#dab1dbf0405c2671aa73e4dbb944863bd434f629"
|
||||
integrity sha512-q1FErsVthiLpOarpKohoZhvXb8BGvgCBpXzbDZ64/15L2lErFUTYbXxyklBTy5DCbULwUh7wBvkm74JF10Ghlg==
|
||||
dependencies:
|
||||
"@standardnotes/sncrypto-common" "^1.2.9"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user