refactor: update SNJS + eslint

This commit is contained in:
Baptiste Grob
2021-01-18 13:06:01 +01:00
parent f7f3b062fb
commit 27a68accdd
12 changed files with 272 additions and 384 deletions

View File

@@ -1,7 +1,6 @@
import { WebDirective } from './../../types';
import { isDesktopApplication, preventRefreshing } from '@/utils';
import template from '%/directives/account-menu.pug';
import { ProtectedAction, ContentType } from '@standardnotes/snjs';
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
import {
STRING_ACCOUNT_MENU_UNCHECK_MERGE,
@@ -10,8 +9,6 @@ import {
STRING_LOCAL_ENC_ENABLED,
STRING_ENC_NOT_ENABLED,
STRING_IMPORT_SUCCESS,
STRING_REMOVE_PASSCODE_CONFIRMATION,
STRING_REMOVE_PASSCODE_OFFLINE_ADDENDUM,
STRING_NON_MATCHING_PASSCODES,
STRING_NON_MATCHING_PASSWORDS,
STRING_INVALID_IMPORT_FILE,
@@ -23,7 +20,7 @@ import {
STRING_UNSUPPORTED_BACKUP_FILE_VERSION
} from '@/strings';
import { PasswordWizardType } from '@/types';
import { BackupFile } from '@standardnotes/snjs';
import { BackupFile, ContentType } from '@standardnotes/snjs';
import { confirmDialog, alertDialog } from '@/services/alertService';
import { autorun, IReactionDisposer } from 'mobx';
import { storage, StorageKey } from '@/services/localStorage';
@@ -35,22 +32,22 @@ const ELEMENT_NAME_AUTH_PASSWORD = 'password';
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
mergeLocal?: boolean
url: string
authenticating: boolean
status: string
passcode: string
confirmPasscode: string
changingPasscode: boolean
email: string;
user_password: string;
password_conf: string;
confirmPassword: boolean;
showLogin: boolean;
showRegister: boolean;
showPasscodeForm: boolean;
strictSignin?: boolean;
ephemeral: boolean;
mergeLocal?: boolean;
url: string;
authenticating: boolean;
status: string;
passcode: string;
confirmPasscode: string;
changingPasscode: boolean;
}
type AccountMenuState = {
@@ -72,7 +69,7 @@ type AccountMenuState = {
showSessions: boolean;
}
class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> {
class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
public appVersion: string
/** @template */
@@ -331,26 +328,6 @@ class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> {
this.appState.openSessionsModal();
}
async openPrivilegesModal() {
const run = () => {
this.application!.presentPrivilegesManagementModal();
this.close();
};
const needsPrivilege = await this.application!.privilegesService!.actionRequiresPrivilege(
ProtectedAction.ManagePrivileges
);
if (needsPrivilege) {
this.application!.presentPrivilegesModal(
ProtectedAction.ManagePrivileges,
() => {
run();
}
);
} else {
run();
}
}
async destroyLocalData() {
if (await confirmDialog({
text: STRING_SIGN_OUT_CONFIRMATION,
@@ -394,56 +371,46 @@ class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> {
* @template
*/
async importFileSelected(files: File[]) {
const run = async () => {
const file = files[0];
const data = await this.readFile(file);
if (!data) {
const file = files[0];
const data = await this.readFile(file);
if (!data) {
return;
}
if (data.version || data.auth_params || data.keyParams) {
const version = data.version || data.keyParams?.version || data.auth_params?.version;
if (
!this.application!.protocolService!.supportedVersions().includes(version)
) {
await this.setState({ importData: null });
alertDialog({ text: STRING_UNSUPPORTED_BACKUP_FILE_VERSION });
return;
}
if (data.version || data.auth_params || data.keyParams) {
const version = data.version || data.keyParams?.version || data.auth_params?.version;
if (
!this.application!.protocolService!.supportedVersions().includes(version)
) {
await this.setState({ importData: null });
alertDialog({ text: STRING_UNSUPPORTED_BACKUP_FILE_VERSION });
return;
}
if (data.keyParams || data.auth_params) {
await this.setState({
importData: {
...this.getState().importData,
requestPassword: true,
data,
}
});
const element = document.getElementById(
ELEMENT_ID_IMPORT_PASSWORD_INPUT
);
if (element) {
element.scrollIntoView(false);
if (data.keyParams || data.auth_params) {
await this.setState({
importData: {
...this.getState().importData,
requestPassword: true,
data,
}
} else {
await this.performImport(data, undefined);
});
const element = document.getElementById(
ELEMENT_ID_IMPORT_PASSWORD_INPUT
);
if (element) {
element.scrollIntoView(false);
}
} else {
await this.performImport(data, undefined);
}
};
const needsPrivilege = await this.application!.privilegesService!.actionRequiresPrivilege(
ProtectedAction.ManageBackups
);
if (needsPrivilege) {
this.application!.presentPrivilegesModal(
ProtectedAction.ManageBackups,
run
);
} else {
run();
await this.performImport(data, undefined);
}
}
async performImport(data: BackupFile, password?: string) {
if (!(await this.application.authorizeFileImport())) {
return;
}
await this.setState({
importData: {
...this.getState().importData,
@@ -499,23 +466,11 @@ class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> {
}
async selectAutoLockInterval(interval: number) {
const run = async () => {
await this.application!.getAutolockService().setAutoLockInterval(interval);
this.reloadAutoLockInterval();
};
const needsPrivilege = await this.application!.privilegesService!.actionRequiresPrivilege(
ProtectedAction.ManagePasscode
);
if (needsPrivilege) {
this.application!.presentPrivilegesModal(
ProtectedAction.ManagePasscode,
() => {
run();
}
);
} else {
run();
if (!(await this.application.authorizeAutolockIntervalChange())) {
return;
}
await this.application!.getAutolockService().setAutoLockInterval(interval);
this.reloadAutoLockInterval();
}
hidePasswordForm() {
@@ -562,53 +517,18 @@ class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> {
}
async changePasscodePressed() {
const run = () => {
this.getState().formData.changingPasscode = true;
this.addPasscodeClicked();
};
const needsPrivilege = await this.application!.privilegesService!.actionRequiresPrivilege(
ProtectedAction.ManagePasscode
);
if (needsPrivilege) {
this.application!.presentPrivilegesModal(
ProtectedAction.ManagePasscode,
run
);
} else {
run();
}
this.getState().formData.changingPasscode = true;
this.addPasscodeClicked();
}
async removePasscodePressed() {
const run = async () => {
const signedIn = this.application!.hasAccount();
let message = STRING_REMOVE_PASSCODE_CONFIRMATION;
if (!signedIn) {
message += STRING_REMOVE_PASSCODE_OFFLINE_ADDENDUM;
}
if (await confirmDialog({
text: message,
confirmButtonStyle: 'danger'
})) {
await preventRefreshing(STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL, async () => {
await this.application.getAutolockService().deleteAutolockPreference();
await this.application!.removePasscode();
await this.reloadAutoLockInterval();
});
await preventRefreshing(STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL, async () => {
if (await this.application!.removePasscode()) {
await this.application.getAutolockService().deleteAutolockPreference();
await this.reloadAutoLockInterval();
this.refreshEncryptionStatus();
}
};
const needsPrivilege = await this.application!.privilegesService!.actionRequiresPrivilege(
ProtectedAction.ManagePasscode
);
if (needsPrivilege) {
this.application!.presentPrivilegesModal(
ProtectedAction.ManagePasscode,
run
);
} else {
run();
}
});
}
openErrorReportingDialog() {

View File

@@ -1,9 +1,17 @@
import { SNComponent, PurePayload, ComponentMutator, AppDataField, ContentType } from '@standardnotes/snjs';
import {
SNComponent,
PurePayload,
ComponentMutator,
AppDataField,
EncryptionIntent,
ApplicationService,
ApplicationEvent,
removeFromArray,
} from '@standardnotes/snjs';
/* eslint-disable camelcase */
import { WebApplication } from '@/ui_models/application';
// An interface used by the Desktop app to interact with SN
import { isDesktopApplication } from '@/utils';
import { EncryptionIntent, ApplicationService, ApplicationEvent, removeFromArray } from '@standardnotes/snjs';
import { Bridge } from './bridge';
type UpdateObserverCallback = (component: SNComponent) => void
@@ -20,7 +28,8 @@ export class DesktopManager extends ApplicationService {
componentActivationObservers: ComponentActivationObserver[] = []
updateObservers: {
callback: UpdateObserverCallback
}[] = []
}[] = [];
isDesktop = isDesktopApplication();
dataLoaded = false

View File

@@ -1,13 +1,10 @@
import { isDesktopApplication, isDev } from '@/utils';
import pull from 'lodash/pull';
import {
ProtectedAction,
ApplicationEvent,
SNTag,
SNNote,
SNUserPrefs,
ContentType,
SNSmartTag,
PayloadSource,
DeinitSource,
UuidString,
@@ -231,8 +228,7 @@ export class AppState {
return;
};
const approved = this.application.authorizeNoteAccess(note);
if (approved === true || await approved) {
if (await this.application.authorizeNoteAccess(note)) {
const activeEditor = this.getActiveEditor();
if (!activeEditor) {
this.application.editorGroup.createEditor(noteUuid);

View File

@@ -1,4 +1,3 @@
import { PermissionDialog } from '@standardnotes/snjs';
import { ComponentModalScope } from './../directives/views/componentModal';
import { AccountSwitcherScope, PermissionsModalScope } from './../types';
import { ComponentGroup } from './component_group';
@@ -9,7 +8,9 @@ import {
SNApplication,
platformFromString,
Challenge,
ProtectedAction, SNComponent
SNComponent,
PermissionDialog,
DeinitSource,
} from '@standardnotes/snjs';
import angular from 'angular';
import { getPlatformString } from '@/utils';
@@ -27,17 +28,16 @@ import {
import { AppState } from '@/ui_models/app_state';
import { SNWebCrypto } from '@standardnotes/sncrypto-web';
import { Bridge } from '@/services/bridge';
import { DeinitSource } from '@standardnotes/snjs';
type WebServices = {
appState: AppState
desktopService: DesktopManager
autolockService: AutolockService
archiveService: ArchiveManager
nativeExtService: NativeExtManager
statusManager: StatusManager
themeService: ThemeManager
keyboardService: KeyboardManager
appState: AppState;
desktopService: DesktopManager;
autolockService: AutolockService;
archiveService: ArchiveManager;
nativeExtService: NativeExtManager;
statusManager: StatusManager;
themeService: ThemeManager;
keyboardService: KeyboardManager;
}
export class WebApplication extends SNApplication {
@@ -78,7 +78,7 @@ export class WebApplication extends SNApplication {
}
/** @override */
deinit(source: DeinitSource) {
deinit(source: DeinitSource): void {
for (const service of Object.values(this.webServices)) {
if ('deinit' in service) {
service.deinit?.(source);
@@ -107,15 +107,15 @@ export class WebApplication extends SNApplication {
this.componentManager!.presentPermissionsDialog = this.presentPermissionsDialog;
}
setWebServices(services: WebServices) {
setWebServices(services: WebServices): void {
this.webServices = services;
}
public getAppState() {
public getAppState(): AppState {
return this.webServices.appState;
}
public getDesktopService() {
public getDesktopService(): DesktopManager {
return this.webServices.desktopService;
}
@@ -170,46 +170,6 @@ export class WebApplication extends SNApplication {
this.applicationElement.append(el);
}
async presentPrivilegesModal(
action: ProtectedAction,
onSuccess?: any,
onCancel?: any
) {
if (this.authenticationInProgress()) {
onCancel && onCancel();
return;
}
const customSuccess = async () => {
onSuccess && await onSuccess();
this.currentAuthenticationElement = undefined;
};
const customCancel = async () => {
onCancel && await onCancel();
this.currentAuthenticationElement = undefined;
};
const scope: any = this.scope!.$new(true);
scope.action = action;
scope.onSuccess = customSuccess;
scope.onCancel = customCancel;
scope.application = this;
const el = this.$compile!(`
<privileges-auth-modal application='application' action='action' on-success='onSuccess'
on-cancel='onCancel' class='sk-modal'></privileges-auth-modal>
`)(scope);
this.applicationElement.append(el);
this.currentAuthenticationElement = el;
}
presentPrivilegesManagementModal() {
const scope: any = this.scope!.$new(true);
scope.application = this;
const el = this.$compile!("<privileges-management-modal application='application' class='sk-modal'></privileges-management-modal>")(scope);
this.applicationElement.append(el);
}
authenticationInProgress() {
return this.currentAuthenticationElement != null;
}

View File

@@ -12,7 +12,9 @@
| {{ctrl.challenge.subheading}}
.sk-panel-section
div(ng-repeat="prompt in ctrl.state.prompts track by prompt.id")
.sk-panel-row
.sk-panel-row(
ng-if="prompt.validation != ctrl.protectionsSessionValidation"
)
input.sk-input.contrast(
ng-model="ctrl.state.values[prompt.id].value"
should-focus="$index == 0"
@@ -21,7 +23,17 @@
ng-change="ctrl.onTextValueChange(prompt)"
ng-attr-type="{{prompt.secureTextEntry ? 'password' : 'text'}}",
ng-attr-placeholder="{{prompt.title}}"
)
)
.sk-horizontal-group(
ng-if="prompt.validation == ctrl.protectionsSessionValidation"
)
.sk-p.sk-bold Remember For
a.sk-a.info(
ng-repeat="option in ctrl.protectionsSessionDurations"
ng-class="{'boxed' : option.valueInSeconds == ctrl.state.values[prompt.id].value}"
ng-click="ctrl.onValueChange(prompt, option.valueInSeconds);"
)
| {{option.label}}
.sk-panel-row.centered
label.sk-label.danger(
ng-if="ctrl.state.values[prompt.id].invalid"

View File

@@ -5,45 +5,46 @@ import {
removeFromArray,
Challenge,
ChallengeReason,
ChallengePrompt
ChallengePrompt,
ChallengeValidation,
ProtectionSessionDurations,
} from '@standardnotes/snjs';
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
import { WebDirective } from '@/types';
import { confirmDialog } from '@/services/alertService';
import {
STRING_SIGN_OUT_CONFIRMATION,
} from '@/strings';
import { STRING_SIGN_OUT_CONFIRMATION } from '@/strings';
type InputValue = {
prompt: ChallengePrompt
value: string
invalid: boolean
}
prompt: ChallengePrompt;
value: string | number | boolean;
invalid: boolean;
};
type Values = Record<number, InputValue>
type Values = Record<number, InputValue>;
type ChallengeModalState = {
prompts: ChallengePrompt[]
values: Partial<Values>
processing: boolean,
forgotPasscode: boolean,
showForgotPasscodeLink: boolean,
processingPrompts: ChallengePrompt[],
hasAccount: boolean,
}
prompts: ChallengePrompt[];
values: Partial<Values>;
processing: boolean;
forgotPasscode: boolean;
showForgotPasscodeLink: boolean;
processingPrompts: ChallengePrompt[];
hasAccount: boolean;
protectedNoteAccessDuration: number;
};
class ChallengeModalCtrl extends PureViewCtrl<{}, ChallengeModalState> {
private $element: JQLite
application!: WebApplication
challenge!: Challenge
class ChallengeModalCtrl extends PureViewCtrl<unknown, ChallengeModalState> {
application!: WebApplication;
challenge!: Challenge;
/** @template */
protectionsSessionDurations = ProtectionSessionDurations;
protectionsSessionValidation =
ChallengeValidation.ProtectionSessionDuration;
/* @ngInject */
constructor(
$element: JQLite,
$timeout: ng.ITimeoutService
) {
constructor(private $element: JQLite, $timeout: ng.ITimeoutService) {
super($timeout);
this.$element = $element;
}
getState() {
@@ -57,13 +58,13 @@ class ChallengeModalCtrl extends PureViewCtrl<{}, ChallengeModalState> {
for (const prompt of prompts) {
values[prompt.id] = {
prompt,
value: '',
invalid: false
value: prompt.initialValue ?? '',
invalid: false,
};
}
const showForgotPasscodeLink = [
ChallengeReason.ApplicationUnlock,
ChallengeReason.Migration
ChallengeReason.Migration,
].includes(this.challenge.reason);
this.setState({
prompts,
@@ -72,34 +73,32 @@ class ChallengeModalCtrl extends PureViewCtrl<{}, ChallengeModalState> {
forgotPasscode: false,
showForgotPasscodeLink,
hasAccount: this.application.hasAccount(),
processingPrompts: []
processingPrompts: [],
protectedNoteAccessDuration: ProtectionSessionDurations[0].valueInSeconds,
});
this.application.addChallengeObserver(
this.challenge,
{
onValidValue: (value) => {
this.getState().values[value.prompt.id]!.invalid = false;
this.application.addChallengeObserver(this.challenge, {
onValidValue: (value) => {
this.getState().values[value.prompt.id]!.invalid = false;
removeFromArray(this.state.processingPrompts, value.prompt);
this.reloadProcessingStatus();
},
onInvalidValue: (value) => {
this.getState().values[value.prompt.id]!.invalid = true;
/** If custom validation, treat all values together and not individually */
if (!value.prompt.validates) {
this.setState({ processingPrompts: [], processing: false });
} else {
removeFromArray(this.state.processingPrompts, value.prompt);
this.reloadProcessingStatus();
},
onInvalidValue: (value) => {
this.getState().values[value.prompt.id]!.invalid = true;
/** If custom validation, treat all values together and not individually */
if (!value.prompt.validates) {
this.setState({ processingPrompts: [], processing: false });
} else {
removeFromArray(this.state.processingPrompts, value.prompt);
this.reloadProcessingStatus();
}
},
onComplete: () => {
this.dismiss();
},
onCancel: () => {
this.dismiss();
},
}
);
}
},
onComplete: () => {
this.dismiss();
},
onCancel: () => {
this.dismiss();
},
});
}
deinit() {
@@ -110,18 +109,20 @@ class ChallengeModalCtrl extends PureViewCtrl<{}, ChallengeModalState> {
reloadProcessingStatus() {
return this.setState({
processing: this.state.processingPrompts.length > 0
processing: this.state.processingPrompts.length > 0,
});
}
async destroyLocalData() {
if (await confirmDialog({
text: STRING_SIGN_OUT_CONFIRMATION,
confirmButtonStyle: "danger"
})) {
if (
await confirmDialog({
text: STRING_SIGN_OUT_CONFIRMATION,
confirmButtonStyle: 'danger',
})
) {
await this.application.signOut();
this.dismiss();
};
}
}
/** @template */
@@ -133,7 +134,7 @@ class ChallengeModalCtrl extends PureViewCtrl<{}, ChallengeModalState> {
onForgotPasscodeClick() {
this.setState({
forgotPasscode: true
forgotPasscode: true,
});
}
@@ -143,15 +144,22 @@ class ChallengeModalCtrl extends PureViewCtrl<{}, ChallengeModalState> {
this.setState({ values });
}
onValueChange(prompt: ChallengePrompt, value: number) {
const values = this.state.values;
values[prompt.id]!.invalid = false;
values[prompt.id]!.value = value;
}
validate() {
const failed = [];
for (const prompt of this.getState().prompts) {
const value = this.getState().values[prompt.id];
if (!value || value.value.length === 0) {
this.getState().values[prompt.id]!.invalid = true;
let failed = 0;
for (const prompt of this.state.prompts) {
const value = this.state.values[prompt.id]!;
if (typeof value.value === 'string' && value.value.length === 0) {
this.state.values[prompt.id]!.invalid = true;
failed++;
}
}
return failed.length === 0;
return failed === 0;
}
async submit() {
@@ -161,15 +169,15 @@ class ChallengeModalCtrl extends PureViewCtrl<{}, ChallengeModalState> {
await this.setState({ processing: true });
const values: ChallengeValue[] = [];
for (const inputValue of Object.values(this.getState().values)) {
const rawValue = inputValue!!.value;
const rawValue = inputValue!.value;
const value = new ChallengeValue(inputValue!.prompt, rawValue);
values.push(value);
}
const processingPrompts = values.map((v) => v.prompt);
await this.setState({
processingPrompts: processingPrompts,
processing: processingPrompts.length > 0
})
processing: processingPrompts.length > 0,
});
/**
* Unfortunately neccessary to wait 50ms so that the above setState call completely
* updates the UI to change processing state, before we enter into UI blocking operation
@@ -181,7 +189,7 @@ class ChallengeModalCtrl extends PureViewCtrl<{}, ChallengeModalState> {
} else {
this.setState({ processing: false });
}
}, 50)
}, 50);
}
dismiss() {
@@ -202,7 +210,7 @@ export class ChallengeModal extends WebDirective {
this.bindToController = true;
this.scope = {
challenge: '=',
application: '='
application: '=',
};
}
}

View File

@@ -8,7 +8,6 @@ import {
isPayloadSourceRetrieved,
isPayloadSourceInternalChange,
ContentType,
ProtectedAction,
SNComponent,
SNNote,
SNTag,
@@ -24,7 +23,7 @@ import { isDesktopApplication } from '@/utils';
import { KeyboardModifier, KeyboardKey } from '@/services/keyboardManager';
import template from './editor-view.pug';
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
import { AppStateEvent, EventSource } from '@/ui_models/app_state';
import { EventSource } from '@/ui_models/app_state';
import {
STRING_DELETED_NOTE,
STRING_INVALID_NOTE,
@@ -85,7 +84,7 @@ type EditorState = {
* then re-initialized. Used when reloading spellcheck status. */
textareaUnloading: boolean
/** Fields that can be directly mutated by the template */
mutable: {}
mutable: any
}
type EditorValues = {
@@ -98,7 +97,7 @@ function sortAlphabetically(array: SNComponent[]): SNComponent[] {
return array.sort((a, b) => a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1);
}
class EditorViewCtrl extends PureViewCtrl<{}, EditorState> {
class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
/** Passed through template */
readonly application!: WebApplication
readonly editor!: Editor
@@ -248,7 +247,7 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> {
case ApplicationEvent.HighLatencySync:
this.setState({ syncTakingTooLong: true });
break;
case ApplicationEvent.CompletedFullSync:
case ApplicationEvent.CompletedFullSync: {
this.setState({ syncTakingTooLong: false });
const isInErrorState = this.state.saveError;
/** if we're still dirty, don't change status, a sync is likely upcoming. */
@@ -256,6 +255,7 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> {
this.showAllChangesSavedStatus();
}
break;
}
case ApplicationEvent.FailedSync:
/**
* Only show error status in editor if the note is dirty.
@@ -601,10 +601,12 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> {
this.setMenuState('showOptionsMenu', false);
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onTitleFocus() {
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onTitleBlur() {
}
@@ -627,50 +629,35 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> {
);
return;
}
const run = async () => {
if (this.note.locked) {
this.application.alertService!.alert(
STRING_DELETE_LOCKED_ATTEMPT
);
return;
}
const title = this.note.safeTitle().length
? `'${this.note.title}'`
: "this note";
const text = StringDeleteNote(
title,
permanently
if (this.note.locked) {
this.application.alertService!.alert(
STRING_DELETE_LOCKED_ATTEMPT
);
if (await confirmDialog({
text,
confirmButtonStyle: 'danger'
})) {
if (permanently) {
this.performNoteDeletion(this.note);
} else {
this.saveNote(
true,
false,
true,
(mutator) => {
mutator.trashed = true;
}
);
}
};
};
const requiresPrivilege = await this.application.privilegesService!.actionRequiresPrivilege(
ProtectedAction.DeleteNote
return;
}
const title = this.note.safeTitle().length
? `'${this.note.title}'`
: "this note";
const text = StringDeleteNote(
title,
permanently
);
if (requiresPrivilege) {
this.application.presentPrivilegesModal(
ProtectedAction.DeleteNote,
() => {
run();
}
);
} else {
run();
if (await confirmDialog({
text,
confirmButtonStyle: 'danger'
})) {
if (permanently) {
this.performNoteDeletion(this.note);
} else {
this.saveNote(
true,
false,
true,
(mutator) => {
mutator.trashed = true;
}
);
}
}
}

View File

@@ -5,7 +5,6 @@ import { dateToLocalizedString, preventRefreshing } from '@/utils';
import {
ApplicationEvent,
SyncQueueStrategy,
ProtectedAction,
ContentType,
SNComponent,
SNTheme,
@@ -44,7 +43,7 @@ type DockShortcut = {
}
}
class FooterViewCtrl extends PureViewCtrl<{}, {
class FooterViewCtrl extends PureViewCtrl<unknown, {
outOfSync: boolean;
hasPasscode: boolean;
dataUpgradeAvailable: boolean;
@@ -207,7 +206,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
case AppStateEvent.BeganBackupDownload:
statusService.setMessage("Saving local backup…");
break;
case AppStateEvent.EndedBackupDownload:
case AppStateEvent.EndedBackupDownload: {
const successMessage = "Successfully saved backup.";
const errorMessage = "Unable to save local backup."
statusService.setMessage(data.success ? successMessage : errorMessage);
@@ -222,6 +221,7 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
}
}, twoSeconds);
break;
}
}
}
@@ -544,28 +544,9 @@ class FooterViewCtrl extends PureViewCtrl<{}, {
}
async selectRoom(room: SNComponent) {
const run = () => {
this.$timeout(() => {
this.roomShowState[room.uuid] = !this.roomShowState[room.uuid];
});
};
if (!this.roomShowState[room.uuid]) {
const requiresPrivilege = await this.application.privilegesService!
.actionRequiresPrivilege(
ProtectedAction.ManageExtensions
);
if (requiresPrivilege) {
this.application.presentPrivilegesModal(
ProtectedAction.ManageExtensions,
run
);
} else {
run();
}
} else {
run();
}
this.$timeout(() => {
this.roomShowState[room.uuid] = !this.roomShowState[room.uuid];
});
}
displayBetaDialog() {