From 252183a7c52bbf27886f17afa5a4b80c481db0ef Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 5 Jan 2021 12:58:07 +0100 Subject: [PATCH 01/55] feat: (wip) authorize note access --- app/assets/javascripts/ui_models/app_state.ts | 31 +++++++------------ .../javascripts/views/editor/editor_view.ts | 8 ----- 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index f64d2f8c8..0fecb118f 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -222,9 +222,18 @@ export class AppState { } async openEditor(noteUuid: string) { + if (this.getActiveEditor()?.note?.uuid === noteUuid) { + return; + } + const note = this.application.findItem(noteUuid) as SNNote; - if (this.getActiveEditor()?.note?.uuid === noteUuid) return; - const run = async () => { + if (!note) { + console.warn('Tried accessing a non-existant note of UUID ' + noteUuid); + return; + }; + + const approved = this.application.authorizeNoteAccess(note); + if (approved === true || await approved) { const activeEditor = this.getActiveEditor(); if (!activeEditor || this.multiEditorEnabled) { this.application.editorGroup.createEditor(noteUuid); @@ -232,24 +241,6 @@ export class AppState { activeEditor.setNote(note); } await this.notifyEvent(AppStateEvent.ActiveEditorChanged); - }; - if ( - note && - note.safeContent.protected && - (await this.application.privilegesService!.actionRequiresPrivilege( - ProtectedAction.ViewProtectedNotes - )) - ) { - return new Promise((resolve) => { - this.application.presentPrivilegesModal( - ProtectedAction.ViewProtectedNotes, - () => { - run().then(resolve); - } - ); - }); - } else { - return run(); } } diff --git a/app/assets/javascripts/views/editor/editor_view.ts b/app/assets/javascripts/views/editor/editor_view.ts index 1379dccd2..b1c1d3c6c 100644 --- a/app/assets/javascripts/views/editor/editor_view.ts +++ b/app/assets/javascripts/views/editor/editor_view.ts @@ -740,14 +740,6 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> { mutator.protected = !this.note.protected } ); - /** Show privileges manager if protection is not yet set up */ - this.application.privilegesService!.actionHasPrivilegesConfigured( - ProtectedAction.ViewProtectedNotes - ).then((configured) => { - if (!configured) { - this.application.presentPrivilegesManagementModal(); - } - }); } toggleNotePreview() { From f7f3b062fbf59baad164ac99cc2536cc5566e252 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 5 Jan 2021 13:02:03 +0100 Subject: [PATCH 02/55] fix: remove multiEditorEnabled --- app/assets/javascripts/ui_models/app_state.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index 0fecb118f..b15105d20 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -106,7 +106,6 @@ export class AppState { rootScopeCleanup2: any; onVisibilityChange: any; selectedTag?: SNTag; - multiEditorEnabled = false; showBetaWarning = false; readonly actionsMenu = new ActionsMenuState(); readonly sync = new SyncState(); @@ -210,7 +209,7 @@ export class AppState { : this.selectedTag.uuid : undefined; - if (!activeEditor || this.multiEditorEnabled) { + if (!activeEditor) { this.application.editorGroup.createEditor( undefined, title, @@ -235,7 +234,7 @@ export class AppState { const approved = this.application.authorizeNoteAccess(note); if (approved === true || await approved) { const activeEditor = this.getActiveEditor(); - if (!activeEditor || this.multiEditorEnabled) { + if (!activeEditor) { this.application.editorGroup.createEditor(noteUuid); } else { activeEditor.setNote(note); From 27a68accdd81a226d5cc800c004ef2a3325c10eb Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 18 Jan 2021 13:06:01 +0100 Subject: [PATCH 03/55] refactor: update SNJS + eslint --- .eslintrc | 11 +- .../directives/views/accountMenu.ts | 194 +++++------------- .../javascripts/services/desktopManager.ts | 15 +- app/assets/javascripts/ui_models/app_state.ts | 6 +- .../javascripts/ui_models/application.ts | 70 ++----- .../views/challenge_modal/challenge-modal.pug | 16 +- .../views/challenge_modal/challenge_modal.ts | 152 +++++++------- .../javascripts/views/editor/editor_view.ts | 81 +++----- .../javascripts/views/footer/footer_view.ts | 31 +-- .../templates/directives/account-menu.pug | 4 - package.json | 9 +- yarn.lock | 67 +++--- 12 files changed, 272 insertions(+), 384 deletions(-) diff --git a/.eslintrc b/.eslintrc index 657cd2c81..0f893399a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,11 +1,10 @@ { - "extends": ["eslint:recommended", "semistandard", "prettier"], - "parser": "babel-eslint", + "extends": ["eslint:recommended", "prettier"], + "parser": "@typescript-eslint/parser", "rules": { - "standard/no-callback-literal": 0, // Disable this as we have too many callbacks relying on literals - "no-throw-literal": 0, - // "no-console": "error", - "semi": 1 + "standard/no-callback-literal": "off", // Disable this as we have too many callbacks relying on literals + "no-throw-literal": "off", + "camelcase": "off" }, "env": { "browser": true diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index 21ed1a884..17ddd2cf0 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -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 { 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() { diff --git a/app/assets/javascripts/services/desktopManager.ts b/app/assets/javascripts/services/desktopManager.ts index baae0aca2..057c20c3c 100644 --- a/app/assets/javascripts/services/desktopManager.ts +++ b/app/assets/javascripts/services/desktopManager.ts @@ -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 diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index b15105d20..e973f48f8 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -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); diff --git a/app/assets/javascripts/ui_models/application.ts b/app/assets/javascripts/ui_models/application.ts index 79f628799..76dadcc68 100644 --- a/app/assets/javascripts/ui_models/application.ts +++ b/app/assets/javascripts/ui_models/application.ts @@ -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!(` - - `)(scope); - this.applicationElement.append(el); - - this.currentAuthenticationElement = el; - } - - presentPrivilegesManagementModal() { - const scope: any = this.scope!.$new(true); - scope.application = this; - const el = this.$compile!("")(scope); - this.applicationElement.append(el); - } - authenticationInProgress() { return this.currentAuthenticationElement != null; } diff --git a/app/assets/javascripts/views/challenge_modal/challenge-modal.pug b/app/assets/javascripts/views/challenge_modal/challenge-modal.pug index bb44ffbf9..6277aef49 100644 --- a/app/assets/javascripts/views/challenge_modal/challenge-modal.pug +++ b/app/assets/javascripts/views/challenge_modal/challenge-modal.pug @@ -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" diff --git a/app/assets/javascripts/views/challenge_modal/challenge_modal.ts b/app/assets/javascripts/views/challenge_modal/challenge_modal.ts index a605dac9f..a69f88b33 100644 --- a/app/assets/javascripts/views/challenge_modal/challenge_modal.ts +++ b/app/assets/javascripts/views/challenge_modal/challenge_modal.ts @@ -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 +type Values = Record; type ChallengeModalState = { - prompts: ChallengePrompt[] - values: Partial - processing: boolean, - forgotPasscode: boolean, - showForgotPasscodeLink: boolean, - processingPrompts: ChallengePrompt[], - hasAccount: boolean, -} + prompts: ChallengePrompt[]; + values: Partial; + 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 { + 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: '=', }; } } diff --git a/app/assets/javascripts/views/editor/editor_view.ts b/app/assets/javascripts/views/editor/editor_view.ts index b1c1d3c6c..d6ff57ee5 100644 --- a/app/assets/javascripts/views/editor/editor_view.ts +++ b/app/assets/javascripts/views/editor/editor_view.ts @@ -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 { /** 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; + } + ); + } } } diff --git a/app/assets/javascripts/views/footer/footer_view.ts b/app/assets/javascripts/views/footer/footer_view.ts index b6491d070..1e029617a 100644 --- a/app/assets/javascripts/views/footer/footer_view.ts +++ b/app/assets/javascripts/views/footer/footer_view.ts @@ -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 { - 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() { diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index 6c3572309..1cc5892d0 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -168,10 +168,6 @@ ng-click="self.openSessionsModal()" ng-if="self.state.showSessions" ) Manage Sessions - a.sk-a.info.sk-panel-row.condensed( - ng-click="self.openPrivilegesModal('')", - ng-show='self.state.user' - ) Manage Privileges .sk-panel-section .sk-panel-section-title Encryption .sk-panel-section-subtitle.info(ng-if='self.state.encryptionEnabled') diff --git a/package.json b/package.json index 1659fd071..805665532 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,8 @@ "@types/mocha": "^7.0.2", "@types/pug": "^2.0.4", "@types/react": "^17.0.0", - "@typescript-eslint/eslint-plugin": "^2.23.0", - "@typescript-eslint/parser": "^2.23.0", + "@typescript-eslint/eslint-plugin": "^3.10.1", + "@typescript-eslint/parser": "^3.10.1", "angular": "^1.8.2", "apply-loader": "^2.0.0", "babel-eslint": "^10.1.0", @@ -71,9 +71,12 @@ "@reach/alert-dialog": "^0.12.1", "@reach/dialog": "^0.12.1", "@standardnotes/sncrypto-web": "^1.2.9", - "@standardnotes/snjs": "^2.0.35", + "@standardnotes/snjs": "^2.0.41", "babel-loader": "^8.2.2", "mobx": "^6.0.4", "preact": "^10.5.7" + }, + "peerDependencies": { + "react": "^16.8.0" } } diff --git a/yarn.lock b/yarn.lock index 556ffb807..af8099b2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1045,10 +1045,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.35": - version "2.0.35" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.35.tgz#9e9c3058ebbfc9af7a5fc3ae18497f02a9b1e71b" - integrity sha512-uA4HXorgiV8yFGN1dtO52istUudnc3ZzEQiFLgf0bkKvA0wH3Xt+R9bBviYAdIBkTBKHCyGsBdsCiKr1QS/X9g== +"@standardnotes/snjs@^2.0.41": + version "2.0.41" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.41.tgz#131f3a206b220be5359c43963c47b1929b92f037" + integrity sha512-/6hoBcb/Ib8voqwk1YLVTAM6L2ZJV/AZDXJz/oEKY9cjO0onFMbl0T+AAWEal1d6zojyjC4Wv6Pc9fkNInvBSQ== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" @@ -1188,49 +1188,66 @@ "@types/webpack-sources" "*" source-map "^0.6.0" -"@typescript-eslint/eslint-plugin@^2.23.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9" - integrity sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ== +"@typescript-eslint/eslint-plugin@^3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" + integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== dependencies: - "@typescript-eslint/experimental-utils" "2.34.0" + "@typescript-eslint/experimental-utils" "3.10.1" + debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" + semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.34.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f" - integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA== +"@typescript-eslint/experimental-utils@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" + integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.34.0" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^2.23.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.34.0.tgz#50252630ca319685420e9a39ca05fe185a256bc8" - integrity sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA== +"@typescript-eslint/parser@^3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" + integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.34.0" - "@typescript-eslint/typescript-estree" "2.34.0" + "@typescript-eslint/experimental-utils" "3.10.1" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/typescript-estree@2.34.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5" - integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg== +"@typescript-eslint/types@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" + integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== + +"@typescript-eslint/typescript-estree@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" + integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== dependencies: + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/visitor-keys" "3.10.1" debug "^4.1.1" - eslint-visitor-keys "^1.1.0" glob "^7.1.6" is-glob "^4.0.1" lodash "^4.17.15" semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/visitor-keys@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" + integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== + dependencies: + eslint-visitor-keys "^1.1.0" + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" From 42a7cb418c1ea201d56fb2d8b589f12588bf3256 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 18 Jan 2021 13:40:10 +0100 Subject: [PATCH 04/55] refactor: remove privileges in favor of SNJS protections --- app/assets/javascripts/app.ts | 7 - .../javascripts/directives/views/index.ts | 2 - .../directives/views/privilegesAuthModal.ts | 128 ------------------ .../views/privilegesManagementModal.ts | 118 ---------------- .../directives/views/sessionsModal.tsx | 5 +- .../javascripts/services/archiveManager.ts | 56 ++++---- app/assets/javascripts/ui_models/app_state.ts | 4 +- .../javascripts/views/editor/editor-view.pug | 3 +- app/assets/stylesheets/_modals.scss | 49 ------- .../templates/directives/account-menu.pug | 4 - .../directives/privileges-auth-modal.pug | 37 ----- .../privileges-management-modal.pug | 51 ------- 12 files changed, 30 insertions(+), 434 deletions(-) delete mode 100644 app/assets/javascripts/directives/views/privilegesAuthModal.ts delete mode 100644 app/assets/javascripts/directives/views/privilegesManagementModal.ts delete mode 100644 app/assets/templates/directives/privileges-auth-modal.pug delete mode 100644 app/assets/templates/directives/privileges-management-modal.pug diff --git a/app/assets/javascripts/app.ts b/app/assets/javascripts/app.ts index 4051a7883..1d414d8df 100644 --- a/app/assets/javascripts/app.ts +++ b/app/assets/javascripts/app.ts @@ -44,8 +44,6 @@ import { PanelResizer, PasswordWizard, PermissionsModal, - PrivilegesAuthModal, - PrivilegesManagementModal, RevisionPreviewModal, HistoryMenu, SyncResolutionMenu, @@ -140,11 +138,6 @@ const startApplication: StartApplication = async function startApplication( .directive('panelResizer', () => new PanelResizer()) .directive('passwordWizard', () => new PasswordWizard()) .directive('permissionsModal', () => new PermissionsModal()) - .directive('privilegesAuthModal', () => new PrivilegesAuthModal()) - .directive( - 'privilegesManagementModal', - () => new PrivilegesManagementModal() - ) .directive('revisionPreviewModal', () => new RevisionPreviewModal()) .directive('historyMenu', () => new HistoryMenu()) .directive('syncResolutionMenu', () => new SyncResolutionMenu()) diff --git a/app/assets/javascripts/directives/views/index.ts b/app/assets/javascripts/directives/views/index.ts index adee8d90c..99931e2bb 100644 --- a/app/assets/javascripts/directives/views/index.ts +++ b/app/assets/javascripts/directives/views/index.ts @@ -8,8 +8,6 @@ export { MenuRow } from './menuRow'; export { PanelResizer } from './panelResizer'; export { PasswordWizard } from './passwordWizard'; export { PermissionsModal } from './permissionsModal'; -export { PrivilegesAuthModal } from './privilegesAuthModal'; -export { PrivilegesManagementModal } from './privilegesManagementModal'; export { RevisionPreviewModal } from './revisionPreviewModal'; export { HistoryMenu } from './historyMenu'; export { SyncResolutionMenu } from './syncResolutionMenu'; diff --git a/app/assets/javascripts/directives/views/privilegesAuthModal.ts b/app/assets/javascripts/directives/views/privilegesAuthModal.ts deleted file mode 100644 index e715ee9c4..000000000 --- a/app/assets/javascripts/directives/views/privilegesAuthModal.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { WebDirective } from './../../types'; -import { WebApplication } from '@/ui_models/application'; -import { ProtectedAction, PrivilegeCredential, PrivilegeSessionLength } from '@standardnotes/snjs'; -import template from '%/directives/privileges-auth-modal.pug'; - -type PrivilegesAuthModalScope = { - application: WebApplication - action: ProtectedAction - onSuccess: () => void - onCancel: () => void -} - -class PrivilegesAuthModalCtrl implements PrivilegesAuthModalScope { - $element: JQLite - $timeout: ng.ITimeoutService - application!: WebApplication - action!: ProtectedAction - onSuccess!: () => void - onCancel!: () => void - authParameters: Partial> = {} - sessionLengthOptions!: { value: PrivilegeSessionLength, label: string }[] - selectedSessionLength!: PrivilegeSessionLength - requiredCredentials!: PrivilegeCredential[] - failedCredentials!: PrivilegeCredential[] - - /* @ngInject */ - constructor( - $element: JQLite, - $timeout: ng.ITimeoutService - ) { - this.$element = $element; - this.$timeout = $timeout; - } - - $onInit() { - this.sessionLengthOptions = this.application!.privilegesService! - .getSessionLengthOptions(); - this.application.privilegesService!.getSelectedSessionLength() - .then((length) => { - this.$timeout(() => { - this.selectedSessionLength = length; - }); - }); - this.application.privilegesService!.netCredentialsForAction(this.action) - .then((credentials) => { - this.$timeout(() => { - this.requiredCredentials = credentials.sort(); - }); - }); - } - - selectSessionLength(length: PrivilegeSessionLength) { - this.selectedSessionLength = length; - } - - promptForCredential(credential: PrivilegeCredential) { - return this.application.privilegesService!.displayInfoForCredential(credential).prompt; - } - - cancel() { - this.dismiss(); - this.onCancel && this.onCancel(); - } - - isCredentialInFailureState(credential: PrivilegeCredential) { - if (!this.failedCredentials) { - return false; - } - return this.failedCredentials.find((candidate) => { - return candidate === credential; - }) != null; - } - - validate() { - const failed = []; - for (const cred of this.requiredCredentials) { - const value = this.authParameters[cred]; - if (!value || value.length === 0) { - failed.push(cred); - } - } - this.failedCredentials = failed; - return failed.length === 0; - } - - async submit() { - if (!this.validate()) { - return; - } - const result = await this.application.privilegesService!.authenticateAction( - this.action, - this.authParameters - ); - this.$timeout(() => { - if (result.success) { - this.application.privilegesService!.setSessionLength(this.selectedSessionLength); - this.onSuccess(); - this.dismiss(); - } else { - this.failedCredentials = result.failedCredentials; - } - }); - } - - dismiss() { - const elem = this.$element; - const scope = elem.scope(); - scope.$destroy(); - elem.remove(); - } -} - -export class PrivilegesAuthModal extends WebDirective { - constructor() { - super(); - this.restrict = 'E'; - this.template = template; - this.controller = PrivilegesAuthModalCtrl; - this.controllerAs = 'ctrl'; - this.bindToController = true; - this.scope = { - action: '=', - onSuccess: '=', - onCancel: '=', - application: '=' - }; - } -} diff --git a/app/assets/javascripts/directives/views/privilegesManagementModal.ts b/app/assets/javascripts/directives/views/privilegesManagementModal.ts deleted file mode 100644 index 81403b69a..000000000 --- a/app/assets/javascripts/directives/views/privilegesManagementModal.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { WebDirective } from './../../types'; -import { WebApplication } from '@/ui_models/application'; -import template from '%/directives/privileges-management-modal.pug'; -import { PrivilegeCredential, ProtectedAction, SNPrivileges, PrivilegeSessionLength } from '@standardnotes/snjs'; -import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl'; -import { PrivilegeMutator } from '@standardnotes/snjs'; - -type DisplayInfo = { - label: string - prompt: string -} - -class PrivilegesManagementModalCtrl extends PureViewCtrl { - - hasPasscode = false - hasAccount = false - $element: JQLite - application!: WebApplication - privileges!: SNPrivileges - availableActions!: ProtectedAction[] - availableCredentials!: PrivilegeCredential[] - sessionExpirey!: string - sessionExpired = true - credentialDisplayInfo: Partial> = {} - onCancel!: () => void - - /* @ngInject */ - constructor( - $timeout: ng.ITimeoutService, - $element: JQLite - ) { - super($timeout); - this.$element = $element; - } - - async onAppLaunch() { - super.onAppLaunch(); - this.hasPasscode = this.application.hasPasscode(); - this.hasAccount = !this.application.noAccount(); - this.reloadPrivileges(); - } - - displayInfoForCredential(credential: PrivilegeCredential) { - const info: any = this.application.privilegesService!.displayInfoForCredential(credential); - if (credential === PrivilegeCredential.LocalPasscode) { - info.availability = this.hasPasscode; - } else if (credential === PrivilegeCredential.AccountPassword) { - info.availability = this.hasAccount; - } else { - info.availability = true; - } - return info; - } - - displayInfoForAction(action: ProtectedAction) { - return this.application.privilegesService!.displayInfoForAction(action).label; - } - - isCredentialRequiredForAction(action: ProtectedAction, credential: PrivilegeCredential) { - if (!this.privileges) { - return false; - } - return this.privileges.isCredentialRequiredForAction(action, credential); - } - - async clearSession() { - await this.application.privilegesService!.clearSession(); - this.reloadPrivileges(); - } - - async reloadPrivileges() { - this.availableActions = this.application.privilegesService!.getAvailableActions(); - this.availableCredentials = this.application.privilegesService!.getAvailableCredentials(); - const sessionEndDate = await this.application.privilegesService!.getSessionExpirey(); - this.sessionExpirey = sessionEndDate.toLocaleString(); - this.sessionExpired = new Date() >= sessionEndDate; - for (const cred of this.availableCredentials) { - this.credentialDisplayInfo[cred] = this.displayInfoForCredential(cred); - } - const privs = await this.application.privilegesService!.getPrivileges(); - this.$timeout(() => { - this.privileges = privs; - }); - } - - checkboxValueChanged(action: ProtectedAction, credential: PrivilegeCredential) { - this.application.changeAndSaveItem(this.privileges.uuid, (m) => { - const mutator = m as PrivilegeMutator; - mutator.toggleCredentialForAction(action, credential); - }) - } - - cancel() { - this.dismiss(); - this.onCancel && this.onCancel(); - } - - dismiss() { - const elem = this.$element; - const scope = elem.scope(); - scope.$destroy(); - elem.remove(); - } -} - -export class PrivilegesManagementModal extends WebDirective { - constructor() { - super(); - this.restrict = 'E'; - this.template = template; - this.controller = PrivilegesManagementModalCtrl; - this.controllerAs = 'ctrl'; - this.bindToController = true; - this.scope = { - application: '=' - }; - } -} diff --git a/app/assets/javascripts/directives/views/sessionsModal.tsx b/app/assets/javascripts/directives/views/sessionsModal.tsx index 08f3906e3..dd51d4e51 100644 --- a/app/assets/javascripts/directives/views/sessionsModal.tsx +++ b/app/assets/javascripts/directives/views/sessionsModal.tsx @@ -5,6 +5,7 @@ import { RemoteSession, SessionStrings, UuidString, + isNullOrUndefined, } from '@standardnotes/snjs'; import { autorun, IAutorunOptions, IReactionPublic } from 'mobx'; import { render, FunctionComponent } from 'preact'; @@ -78,7 +79,9 @@ function useSessions( setSessions(sessionsDuringRevoke); const response = await responsePromise; - if ('error' in response) { + if (isNullOrUndefined(response)) { + setSessions(sessionsBeforeRevoke); + } else if ('error' in response) { if (response.error?.message) { setErrorMessage(response.error?.message); } else { diff --git a/app/assets/javascripts/services/archiveManager.ts b/app/assets/javascripts/services/archiveManager.ts index eaa800f3e..bb2442ac9 100644 --- a/app/assets/javascripts/services/archiveManager.ts +++ b/app/assets/javascripts/services/archiveManager.ts @@ -1,5 +1,10 @@ import { WebApplication } from '@/ui_models/application'; -import { EncryptionIntent, ProtectedAction, SNItem, ContentType, SNNote, BackupFile } from '@standardnotes/snjs'; +import { + EncryptionIntent, + ContentType, + SNNote, + BackupFile +} from '@standardnotes/snjs'; function zippableTxtName(name: string, suffix = ""): string { const sanitizedName = name @@ -22,41 +27,26 @@ export class ArchiveManager { } public async downloadBackup(encrypted: boolean) { - const run = async () => { - const intent = encrypted - ? EncryptionIntent.FileEncrypted - : EncryptionIntent.FileDecrypted; + const intent = encrypted + ? EncryptionIntent.FileEncrypted + : EncryptionIntent.FileDecrypted; - const data = await this.application.createBackupFile(intent); - if (!data) { - return; - } - const blobData = new Blob( - [JSON.stringify(data, null, 2)], - { type: 'text/json' } + const data = await this.application.createBackupFile(intent); + if (!data) { + return; + } + const blobData = new Blob( + [JSON.stringify(data, null, 2)], + { type: 'text/json' } + ); + if (encrypted) { + this.downloadData( + blobData, + `Standard Notes Encrypted Backup and Import File - ${this.formattedDate()}.txt` ); - if (encrypted) { - this.downloadData( - blobData, - `Standard Notes Encrypted Backup and Import File - ${this.formattedDate()}.txt` - ); - } else { - /** download as zipped plain text files */ - this.downloadZippedDecryptedItems(data); - } - }; - - if ( - await this.application.privilegesService! - .actionRequiresPrivilege(ProtectedAction.ManageBackups) - ) { - this.application.presentPrivilegesModal( - ProtectedAction.ManageBackups, - () => { - run(); - }); } else { - run(); + /** download as zipped plain text files */ + this.downloadZippedDecryptedItems(data); } } diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index e973f48f8..1028099de 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -217,7 +217,7 @@ export class AppState { } } - async openEditor(noteUuid: string) { + async openEditor(noteUuid: string): Promise { if (this.getActiveEditor()?.note?.uuid === noteUuid) { return; } @@ -226,7 +226,7 @@ export class AppState { if (!note) { console.warn('Tried accessing a non-existant note of UUID ' + noteUuid); return; - }; + } if (await this.application.authorizeNoteAccess(note)) { const activeEditor = this.getActiveEditor(); diff --git a/app/assets/javascripts/views/editor/editor-view.pug b/app/assets/javascripts/views/editor/editor-view.pug index 89c94e83a..7e8e58c30 100644 --- a/app/assets/javascripts/views/editor/editor-view.pug +++ b/app/assets/javascripts/views/editor/editor-view.pug @@ -80,8 +80,7 @@ ) menu-row( action='self.selectedMenuItem(true); self.toggleProtectNote()' - desc=`'Protecting a note will require credentials to view - it (Manage Privileges via Account menu)'`, + desc=`'Protecting a note will require credentials to view it'`, label="self.note.protected ? 'Unprotect' : 'Protect'" ) menu-row( diff --git a/app/assets/stylesheets/_modals.scss b/app/assets/stylesheets/_modals.scss index 77494478d..966e9ef24 100644 --- a/app/assets/stylesheets/_modals.scss +++ b/app/assets/stylesheets/_modals.scss @@ -42,55 +42,6 @@ } } -#privileges-modal { - min-width: 400px; - max-width: 700px; - - .sk-panel-header { - position: relative; - } - - .close-button { - cursor: pointer; - position: absolute; - padding: 1.1rem 2rem; - right: 0; - } - - table { - margin-bottom: 12px; - width: 100%; - overflow: auto; - border-collapse: collapse; - border-spacing: 0px; - border-color: var(--sn-stylekit-contrast-border-color); - background-color: var(--sn-stylekit-background-color); - color: var(--sn-stylekit-contrast-foreground-color); - - th, - td { - padding: 6px 13px; - border: 1px solid var(--sn-stylekit-contrast-border-color); - } - - tr:nth-child(2n) { - background-color: var(--sn-stylekit-contrast-background-color); - } - } - - th { - text-align: center; - font-weight: normal; - } - - .priv-header { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - } -} - #item-preview-modal { > .sk-modal-content { width: 800px; diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index 585f1c6fb..39953a61c 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -222,10 +222,6 @@ | {{option.label}} .sk-p The autolock timer begins when the window or tab loses focus. .sk-panel-row - a.sk-a.info.sk-panel-row.condensed( - ng-click="self.openPrivilegesModal('')", - ng-show='!self.state.user' - ) Manage Privileges a.sk-a.info.sk-panel-row.condensed( ng-click='self.changePasscodePressed()' ) Change Passcode diff --git a/app/assets/templates/directives/privileges-auth-modal.pug b/app/assets/templates/directives/privileges-auth-modal.pug deleted file mode 100644 index 3c578b256..000000000 --- a/app/assets/templates/directives/privileges-auth-modal.pug +++ /dev/null @@ -1,37 +0,0 @@ -.sk-modal-background(ng-click="ctrl.cancel()") -#privileges-modal.sk-modal-content - .sn-component - .sk-panel - .sk-panel-header - .sk-panel-header-title Authentication Required - a.close-button.info(ng-click="ctrl.cancel()") Cancel - .sk-panel-content - .sk-panel-section - div(ng-repeat="credential in ctrl.requiredCredentials") - .sk-p.sk-bold.sk-panel-row - strong {{ctrl.promptForCredential(credential)}} - .sk-panel-row - input.sk-input.contrast( - ng-model="ctrl.authParameters[credential]" - should-focus="$index == 0" - sn-autofocus="true" - sn-enter="ctrl.submit()" - type="password" - ) - .sk-panel-row - label.sk-label.danger( - ng-if="ctrl.isCredentialInFailureState(credential)" - ) Invalid authentication. Please try again. - .sk-panel-row - .sk-panel-row - .sk-horizontal-group - .sk-p.sk-bold Remember For - a.sk-a.info( - ng-repeat="option in ctrl.sessionLengthOptions" - ng-class="{'boxed' : option.value == ctrl.selectedSessionLength}" - ng-click="ctrl.selectSessionLength(option.value)" - ) - | {{option.label}} - .sk-panel-footer.extra-padding - .sk-button.info.big.block.bold(ng-click="ctrl.submit()") - .sk-label Submit diff --git a/app/assets/templates/directives/privileges-management-modal.pug b/app/assets/templates/directives/privileges-management-modal.pug deleted file mode 100644 index cc697e901..000000000 --- a/app/assets/templates/directives/privileges-management-modal.pug +++ /dev/null @@ -1,51 +0,0 @@ -.sk-modal-background(ng-click='ctrl.cancel()') -#privileges-modal.sk-modal-content - .sn-component - .sk-panel - .sk-panel-header - .sk-panel-header-title Manage Privileges - a.sk-a.close-button.info(ng-click='ctrl.cancel()') Done - .sk-panel-content - .sk-panel-section - table.sk-table - thead - tr - th - th(ng-repeat='cred in ctrl.availableCredentials') - .priv-header - strong {{ctrl.credentialDisplayInfo[cred].label}} - .sk-p.font-small( - ng-show='!ctrl.credentialDisplayInfo[cred].availability', - style='margin-top: 2px' - ) Not Configured - tbody - tr(ng-repeat='action in ctrl.availableActions') - td - .sk-p {{ctrl.displayInfoForAction(action)}} - th(ng-repeat='credential in ctrl.availableCredentials') - input( - ng-checked='ctrl.isCredentialRequiredForAction(action, credential)', - ng-click='ctrl.checkboxValueChanged(action, credential)', - ng-disabled='!ctrl.credentialDisplayInfo[credential].availability', - type='checkbox' - ) - .sk-panel-section(ng-if='ctrl.sessionExpirey && !ctrl.sessionExpired') - .sk-p.sk-panel-row - | You will not be asked to authenticate until {{ctrl.sessionExpirey}}. - a.sk-a.sk-panel-row.info(ng-click='ctrl.clearSession()') Clear Session - .sk-panel-footer - .sk-h2.sk-bold About Privileges - .sk-panel-section.no-bottom-pad - .sk-panel-row - .text-content - .sk-p - | Privileges represent interface level authentication for accessing - | certain items and features. Note that when your application is unlocked, - | your data exists in temporary memory in an unencrypted state. - | Privileges are meant to protect against unwanted access in the event of - | an unlocked application, but do not affect data encryption state. - p.sk-p - | Privileges sync across your other devices; however, note that if you - | require an "Application Passcode" privilege, and another device does not have - | an application passcode set up, the application passcode requirement will be ignored - | on that device. From 46ab8b9e9555c43624ddfbb7d2659c9da1242438 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 19 Jan 2021 13:54:40 +0100 Subject: [PATCH 05/55] fix: do not close editor when editing an archived note --- app/assets/javascripts/ui_models/app_state.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index 1028099de..63bee0407 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -9,6 +9,7 @@ import { DeinitSource, UuidString, SyncOpStatus, + PrefKey, } from '@standardnotes/snjs'; import { WebApplication } from '@/ui_models/application'; import { Editor } from '@/ui_models/editor'; @@ -285,7 +286,14 @@ export class AppState { this.closeEditor(editor); } else if (note.trashed && !this.selectedTag?.isTrashTag) { this.closeEditor(editor); - } else if (note.archived && !this.selectedTag?.isArchiveTag) { + } else if ( + note.archived && + !this.selectedTag?.isArchiveTag && + !this.application.getPreference( + PrefKey.NotesShowArchived, + false + ) + ) { this.closeEditor(editor); } } From 8c9b3df3d711c88f577d1660da358b8a35e5ec3d Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 19 Jan 2021 13:54:55 +0100 Subject: [PATCH 06/55] chore: remove progress indicator for webpack dev server --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7fd2c0e2c..2c33a338c 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "setup": "yarn submodules && yarn install", - "start": "webpack-dev-server --progress --config webpack.dev.js", + "start": "webpack-dev-server --config webpack.dev.js", "watch": "webpack -w --config webpack.dev.js", "watch:desktop": "webpack -w --config webpack.dev.js --env.platform='desktop'", "bundle": "webpack --config webpack.prod.js && yarn tsc", From 83eb0bd76c0963527fe7416e23aaf84201534150 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 19 Jan 2021 16:48:52 +0100 Subject: [PATCH 07/55] fix: add rel="noreferrer" to bugsnag links --- app/assets/javascripts/directives/views/accountMenu.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index 737799ce9..a0e76fa5d 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -533,9 +533,9 @@ class AccountMenuCtrl extends PureViewCtrl { alertDialog({ title: 'Data sent during automatic error reporting', text: ` - We use Bugsnag + We use Bugsnag to automatically report errors that occur while the app is running. See - + this article, paragraph 'Browser' under 'Sending diagnostic data', to see what data is included in error reports. From 4bac38f15f36feb08a93bf46b696462ae71cdf03 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 19 Jan 2021 17:20:27 +0100 Subject: [PATCH 08/55] chore(deps): upgrade snjs --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 2c33a338c..ba1679247 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@reach/alert-dialog": "^0.12.1", "@reach/dialog": "^0.12.1", "@standardnotes/sncrypto-web": "^1.2.9", - "@standardnotes/snjs": "^2.0.41", + "@standardnotes/snjs": "^2.0.43", "babel-loader": "^8.2.2", "mobx": "^6.0.4", "preact": "^10.5.7" diff --git a/yarn.lock b/yarn.lock index af8099b2f..f254cb4c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1045,10 +1045,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.41": - version "2.0.41" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.41.tgz#131f3a206b220be5359c43963c47b1929b92f037" - integrity sha512-/6hoBcb/Ib8voqwk1YLVTAM6L2ZJV/AZDXJz/oEKY9cjO0onFMbl0T+AAWEal1d6zojyjC4Wv6Pc9fkNInvBSQ== +"@standardnotes/snjs@^2.0.43": + version "2.0.43" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.43.tgz#891f80d83cfbdc865ebf31f46577bbc726387519" + integrity sha512-GlqaKm6+24jn0uo13AA+0Shs8x3WK6ni1FQmsHp/h1mkuv0tgzNUPR7Z6dW/o3wVEWlWYlO2OwflcaxioSc0yg== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" From c6ff28b40e43a311b164df2c78aefc8642999eaa Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Thu, 21 Jan 2021 11:54:33 +0100 Subject: [PATCH 09/55] chore(deps): upgrade snjs --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ba1679247..6b63597bd 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@reach/alert-dialog": "^0.12.1", "@reach/dialog": "^0.12.1", "@standardnotes/sncrypto-web": "^1.2.9", - "@standardnotes/snjs": "^2.0.43", + "@standardnotes/snjs": "^2.0.45", "babel-loader": "^8.2.2", "mobx": "^6.0.4", "preact": "^10.5.7" diff --git a/yarn.lock b/yarn.lock index f254cb4c3..42107434c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1045,10 +1045,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.43": - version "2.0.43" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.43.tgz#891f80d83cfbdc865ebf31f46577bbc726387519" - integrity sha512-GlqaKm6+24jn0uo13AA+0Shs8x3WK6ni1FQmsHp/h1mkuv0tgzNUPR7Z6dW/o3wVEWlWYlO2OwflcaxioSc0yg== +"@standardnotes/snjs@^2.0.45": + version "2.0.45" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.45.tgz#d1c47af28a309e3b1bd30a2540fcd0c7e656972c" + integrity sha512-OqHccVx+ijqAK0aHlOtma5P3Z2JBj3l5h3KWaWoG5UR3EIIp8CpyI7nOWE8VO4y1ALfPk754D8y8d9Rx4ti7eA== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" From 5d65364885d259933e9a1f1d5462d3639fddea1a Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 22 Jan 2021 11:37:58 +0100 Subject: [PATCH 10/55] feat: batch manager protection + react challenge modal + eslint fix --- .eslintrc | 9 +- .github/workflows/dev.yml | 5 +- .github/workflows/pr.yml | 9 + .github/workflows/prod.yml | 5 +- .../directives/views/sessionsModal.tsx | 37 +- .../javascripts/services/browserBridge.ts | 11 +- .../javascripts/services/keyboardManager.ts | 10 +- .../javascripts/services/nativeExtManager.ts | 10 +- .../javascripts/services/themeManager.ts | 4 +- app/assets/javascripts/typings/pug.d.ts | 2 +- app/assets/javascripts/ui_models/app_state.ts | 6 +- .../javascripts/ui_models/application.ts | 32 +- .../javascripts/ui_models/component_group.ts | 10 +- .../javascripts/ui_models/editor_group.ts | 2 +- .../views/abstract/pure_view_ctrl.ts | 5 + .../views/application/application-view.pug | 7 + .../views/application/application_view.ts | 27 +- .../views/challenge_modal/challenge-modal.pug | 71 -- .../views/challenge_modal/challenge_modal.ts | 216 ---- .../views/challenge_modal/challenge_modal.tsx | 404 ++++++++ app/assets/javascripts/views/index.ts | 2 +- app/assets/stylesheets/_reach-sub.scss | 2 + app/assets/stylesheets/_sessions-modal.scss | 3 + package.json | 21 +- yarn.lock | 928 +++++++++--------- 25 files changed, 1009 insertions(+), 829 deletions(-) delete mode 100644 app/assets/javascripts/views/challenge_modal/challenge-modal.pug delete mode 100644 app/assets/javascripts/views/challenge_modal/challenge_modal.ts create mode 100644 app/assets/javascripts/views/challenge_modal/challenge_modal.tsx diff --git a/.eslintrc b/.eslintrc index c88737d79..28f7be1df 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,6 +1,13 @@ { - "extends": ["eslint:recommended", "prettier"], + "root": true, "parser": "@typescript-eslint/parser", + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier", + "plugin:react-hooks/recommended" + ], + "plugins": ["@typescript-eslint", "react"], "parserOptions": { "project": "./app/assets/javascripts/tsconfig.json" }, diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index a84a4cff6..e5f7cac43 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -8,7 +8,7 @@ jobs: tsc: - name: Check types + name: Check types & lint runs-on: ubuntu-latest @@ -22,6 +22,9 @@ jobs: - name: Typescript run: yarn tsc + - name: ESLint + run: yarn lint --quiet + deploy: runs-on: ubuntu-latest diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 37fa0189d..53ad2afa9 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -7,12 +7,21 @@ on: - master jobs: + tsc: + runs-on: ubuntu-latest + steps: + - name: Checkout code uses: actions/checkout@v2 + - name: Install dependencies run: yarn install --pure-lockfile + - name: Typescript run: yarn tsc + + - name: ESLint + run: yarn lint --quiet diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml index dd741654b..c8d191aa2 100644 --- a/.github/workflows/prod.yml +++ b/.github/workflows/prod.yml @@ -8,7 +8,7 @@ jobs: tsc: - name: Check types + name: Check types & lint runs-on: ubuntu-latest @@ -23,6 +23,9 @@ jobs: - name: Typescript run: yarn tsc + - name: ESLint + run: yarn lint --quiet + deploy: runs-on: ubuntu-latest diff --git a/app/assets/javascripts/directives/views/sessionsModal.tsx b/app/assets/javascripts/directives/views/sessionsModal.tsx index dd51d4e51..18a53c0f3 100644 --- a/app/assets/javascripts/directives/views/sessionsModal.tsx +++ b/app/assets/javascripts/directives/views/sessionsModal.tsx @@ -9,7 +9,7 @@ import { } from '@standardnotes/snjs'; import { autorun, IAutorunOptions, IReactionPublic } from 'mobx'; import { render, FunctionComponent } from 'preact'; -import { useState, useEffect, useRef } from 'preact/hooks'; +import { useState, useEffect, useRef, useMemo } from 'preact/hooks'; import { Dialog } from '@reach/dialog'; import { Alert } from '@reach/alert'; import { @@ -19,7 +19,7 @@ import { } from '@reach/alert-dialog'; function useAutorun(view: (r: IReactionPublic) => any, opts?: IAutorunOptions) { - useEffect(() => autorun(view, opts), []); + useEffect(() => autorun(view, opts), [view, opts]); } type Session = RemoteSession & { @@ -57,16 +57,16 @@ function useSessions( } setRefreshing(false); })(); - }, [lastRefreshDate]); + }, [application, lastRefreshDate]); function refresh() { setLastRefreshDate(Date.now()); } async function revokeSession(uuid: UuidString) { - const responsePromise = application.revokeSession(uuid); + const sessionsBeforeRevoke = sessions; - let sessionsBeforeRevoke = sessions; + const responsePromise = application.revokeSession(uuid); const sessionsDuringRevoke = sessions.slice(); const toRemoveIndex = sessions.findIndex( @@ -114,19 +114,23 @@ const SessionsModal: FunctionComponent<{ const closeRevokeSessionAlert = () => setRevokingSessionUuid(''); const cancelRevokeRef = useRef(); - const formatter = new Intl.DateTimeFormat(undefined, { - year: 'numeric', - month: 'long', - day: 'numeric', - weekday: 'long', - hour: 'numeric', - minute: 'numeric', - }); + const formatter = useMemo( + () => + new Intl.DateTimeFormat(undefined, { + year: 'numeric', + month: 'long', + day: 'numeric', + weekday: 'long', + hour: 'numeric', + minute: 'numeric', + }), + [] + ); return ( <> - -
+ +
@@ -250,7 +254,7 @@ const Sessions: FunctionComponent<{ } }; -class SessionsModalCtrl extends PureViewCtrl<{}, {}> { +class SessionsModalCtrl extends PureViewCtrl { /* @ngInject */ constructor(private $element: JQLite, $timeout: ng.ITimeoutService) { super($timeout); @@ -264,6 +268,7 @@ class SessionsModalCtrl extends PureViewCtrl<{}, {}> { } } +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function SessionsModalDirective() { return { controller: SessionsModalCtrl, diff --git a/app/assets/javascripts/services/browserBridge.ts b/app/assets/javascripts/services/browserBridge.ts index ff8eb9ac6..d0408ffa6 100644 --- a/app/assets/javascripts/services/browserBridge.ts +++ b/app/assets/javascripts/services/browserBridge.ts @@ -24,9 +24,10 @@ export class BrowserBridge implements Bridge { /** No-ops */ - syncComponents() {} - onMajorDataChange() {} - onInitialDataLoad() {} - onSearch() {} - downloadBackup() {} + /* eslint-disable @typescript-eslint/no-empty-function */ + syncComponents(): void {} + onMajorDataChange(): void {} + onInitialDataLoad(): void {} + onSearch(): void {} + downloadBackup(): void {} } diff --git a/app/assets/javascripts/services/keyboardManager.ts b/app/assets/javascripts/services/keyboardManager.ts index 85918c3f7..b786bcd43 100644 --- a/app/assets/javascripts/services/keyboardManager.ts +++ b/app/assets/javascripts/services/keyboardManager.ts @@ -4,7 +4,7 @@ export enum KeyboardKey { Backspace = "Backspace", Up = "ArrowUp", Down = "ArrowDown", -}; +} export enum KeyboardModifier { Shift = "Shift", @@ -12,12 +12,12 @@ export enum KeyboardModifier { /** ⌘ key on Mac, ⊞ key on Windows */ Meta = "Meta", Alt = "Alt", -}; +} enum KeyboardKeyEvent { Down = "KeyEventDown", Up = "KeyEventUp" -}; +} type KeyboardObserver = { key?: KeyboardKey | string @@ -39,10 +39,10 @@ export class KeyboardManager { constructor() { this.handleKeyDown = (event: KeyboardEvent) => { this.notifyObserver(event, KeyboardKeyEvent.Down); - } + }; this.handleKeyUp = (event: KeyboardEvent) => { this.notifyObserver(event, KeyboardKeyEvent.Up); - } + }; window.addEventListener('keydown', this.handleKeyDown); window.addEventListener('keyup', this.handleKeyUp); } diff --git a/app/assets/javascripts/services/nativeExtManager.ts b/app/assets/javascripts/services/nativeExtManager.ts index 955193a3c..42e52b6d8 100644 --- a/app/assets/javascripts/services/nativeExtManager.ts +++ b/app/assets/javascripts/services/nativeExtManager.ts @@ -9,9 +9,9 @@ import { ComponentMutator, Copy, dictToArray -} from '@standardnotes/snjs'; -import { PayloadContent } from '@standardnotes/snjs'; -import { ComponentPermission } from '@standardnotes/snjs'; +, PayloadContent , ComponentPermission } from '@standardnotes/snjs'; + + /** A class for handling installation of system extensions */ export class NativeExtManager extends ApplicationService { @@ -82,7 +82,7 @@ export class NativeExtManager extends ApplicationService { // Handle addition of SN|ExtensionRepo permission const permissions = Copy(extensionsManager!.permissions) as ComponentPermission[]; const permission = permissions.find((p) => { - return p.name === ComponentAction.StreamItems + return p.name === ComponentAction.StreamItems; }); if (permission && !permission.content_types!.includes(ContentType.ExtensionRepo)) { permission.content_types!.push(ContentType.ExtensionRepo); @@ -160,7 +160,7 @@ export class NativeExtManager extends ApplicationService { // Handle addition of SN|ExtensionRepo permission const permissions = Copy(batchManager!.permissions) as ComponentPermission[]; const permission = permissions.find((p) => { - return p.name === ComponentAction.StreamItems + return p.name === ComponentAction.StreamItems; }); if (permission && !permission.content_types!.includes(ContentType.ExtensionRepo)) { permission.content_types!.push(ContentType.ExtensionRepo); diff --git a/app/assets/javascripts/services/themeManager.ts b/app/assets/javascripts/services/themeManager.ts index ef9b65eb3..cdd81aa8a 100644 --- a/app/assets/javascripts/services/themeManager.ts +++ b/app/assets/javascripts/services/themeManager.ts @@ -22,8 +22,6 @@ export class ThemeManager extends ApplicationService { this.deactivateAllThemes(); } else if (event === ApplicationEvent.StorageReady) { await this.activateCachedThemes(); - if (!this.webApplication.getDesktopService().isDesktop) { - } } } @@ -75,7 +73,7 @@ export class ThemeManager extends ApplicationService { this.deactivateTheme(theme.uuid); } } - }) + }); } private clearAppThemeState() { diff --git a/app/assets/javascripts/typings/pug.d.ts b/app/assets/javascripts/typings/pug.d.ts index 8005eaa90..73500cba1 100644 --- a/app/assets/javascripts/typings/pug.d.ts +++ b/app/assets/javascripts/typings/pug.d.ts @@ -1,5 +1,5 @@ declare module "*.pug" { - import { compileTemplate } from 'pug' + import { compileTemplate } from 'pug'; const content: compileTemplate; export default content; } \ No newline at end of file diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index 63bee0407..e41ffcb7c 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -10,6 +10,7 @@ import { UuidString, SyncOpStatus, PrefKey, + Challenge, } from '@standardnotes/snjs'; import { WebApplication } from '@/ui_models/application'; import { Editor } from '@/ui_models/editor'; @@ -289,10 +290,7 @@ export class AppState { } else if ( note.archived && !this.selectedTag?.isArchiveTag && - !this.application.getPreference( - PrefKey.NotesShowArchived, - false - ) + !this.application.getPreference(PrefKey.NotesShowArchived, false) ) { this.closeEditor(editor); } diff --git a/app/assets/javascripts/ui_models/application.ts b/app/assets/javascripts/ui_models/application.ts index 76dadcc68..aa8315fc6 100644 --- a/app/assets/javascripts/ui_models/application.ts +++ b/app/assets/javascripts/ui_models/application.ts @@ -7,7 +7,6 @@ import { PasswordWizardType, PasswordWizardScope } from '@/types'; import { SNApplication, platformFromString, - Challenge, SNComponent, PermissionDialog, DeinitSource, @@ -42,9 +41,9 @@ type WebServices = { export class WebApplication extends SNApplication { - private scope?: ng.IScope + private scope?: angular.IScope private webServices!: WebServices - private currentAuthenticationElement?: JQLite + private currentAuthenticationElement?: angular.IRootElementService public editorGroup: EditorGroup public componentGroup: ComponentGroup @@ -52,8 +51,8 @@ export class WebApplication extends SNApplication { constructor( deviceInterface: WebDeviceInterface, identifier: string, - private $compile: ng.ICompileService, - scope: ng.IScope, + private $compile: angular.ICompileService, + scope: angular.IScope, defaultSyncServerHost: string, private bridge: Bridge, ) { @@ -98,10 +97,10 @@ export class WebApplication extends SNApplication { * to complete before destroying the global application instance and all its services */ setTimeout(() => { super.deinit(source); - }, 0) + }, 0); } - onStart() { + onStart(): void { super.onStart(); this.componentManager!.openModalComponent = this.openModalComponent; this.componentManager!.presentPermissionsDialog = this.presentPermissionsDialog; @@ -158,18 +157,6 @@ export class WebApplication extends SNApplication { this.applicationElement.append(el); } - promptForChallenge(challenge: Challenge) { - const scope: any = this.scope!.$new(true); - scope.challenge = challenge; - scope.application = this; - const el = this.$compile!( - "" + - "" - )(scope); - this.applicationElement.append(el); - } - authenticationInProgress() { return this.currentAuthenticationElement != null; } @@ -214,7 +201,12 @@ export class WebApplication extends SNApplication { this.applicationElement.append(el); } - openModalComponent(component: SNComponent) { + async openModalComponent(component: SNComponent): Promise { + if (component.package_info?.identifier === "org.standardnotes.batch-manager") { + if (!await this.authorizeBatchManagerAccess()) { + return; + } + } const scope = this.scope!.$new(true) as Partial; scope.componentUuid = component.uuid; scope.application = this; diff --git a/app/assets/javascripts/ui_models/component_group.ts b/app/assets/javascripts/ui_models/component_group.ts index 77e69ee5d..16bdffe58 100644 --- a/app/assets/javascripts/ui_models/component_group.ts +++ b/app/assets/javascripts/ui_models/component_group.ts @@ -1,13 +1,13 @@ -import { SNComponent, ComponentArea, removeFromArray, addIfUnique } from '@standardnotes/snjs'; +import { SNComponent, ComponentArea, removeFromArray, addIfUnique , UuidString } from '@standardnotes/snjs'; import { WebApplication } from './application'; -import { UuidString } from '@standardnotes/snjs'; + /** Areas that only allow a single component to be active */ const SingleComponentAreas = [ ComponentArea.Editor, ComponentArea.NoteTags, ComponentArea.TagsList -] +]; export class ComponentGroup { @@ -20,7 +20,7 @@ export class ComponentGroup { } get componentManager() { - return this.application?.componentManager!; + return this.application.componentManager!; } public deinit() { @@ -91,7 +91,7 @@ export class ComponentGroup { callback(); return () => { removeFromArray(this.changeObservers, callback); - } + }; } private notifyObservers() { diff --git a/app/assets/javascripts/ui_models/editor_group.ts b/app/assets/javascripts/ui_models/editor_group.ts index 46e46a136..0ed73352c 100644 --- a/app/assets/javascripts/ui_models/editor_group.ts +++ b/app/assets/javascripts/ui_models/editor_group.ts @@ -68,7 +68,7 @@ export class EditorGroup { } return () => { removeFromArray(this.changeObservers, callback); - } + }; } private notifyObservers() { diff --git a/app/assets/javascripts/views/abstract/pure_view_ctrl.ts b/app/assets/javascripts/views/abstract/pure_view_ctrl.ts index fb8af1751..41b7f9c3d 100644 --- a/app/assets/javascripts/views/abstract/pure_view_ctrl.ts +++ b/app/assets/javascripts/views/abstract/pure_view_ctrl.ts @@ -77,10 +77,15 @@ export class PureViewCtrl

{ */ this.state = Object.freeze(Object.assign({}, this.state, state)); resolve(); + this.afterStateChange(); }); }); } + /** @override */ + afterStateChange() { + } + /** @returns a promise that resolves after the UI has been updated. */ flushUI() { return this.$timeout(); diff --git a/app/assets/javascripts/views/application/application-view.pug b/app/assets/javascripts/views/application/application-view.pug index bb7149b0a..59eea6acc 100644 --- a/app/assets/javascripts/views/application/application-view.pug +++ b/app/assets/javascripts/views/application/application-view.pug @@ -27,3 +27,10 @@ sessions-modal( application='self.application' ) + challenge-modal( + ng-repeat="challenge in self.state.challenges track by challenge.id" + class="sk-modal" + application="self.application" + challenge="challenge" + on-dismiss="self.removeChallenge(challenge)" + ) diff --git a/app/assets/javascripts/views/application/application_view.ts b/app/assets/javascripts/views/application/application_view.ts index fe477fdd4..f71ac35d4 100644 --- a/app/assets/javascripts/views/application/application_view.ts +++ b/app/assets/javascripts/views/application/application_view.ts @@ -3,7 +3,7 @@ import { WebDirective } from '@/types'; import { getPlatformString } from '@/utils'; import template from './application-view.pug'; import { AppStateEvent } from '@/ui_models/app_state'; -import { ApplicationEvent } from '@standardnotes/snjs'; +import { ApplicationEvent, Challenge } from '@standardnotes/snjs'; import { PANEL_NAME_NOTES, PANEL_NAME_TAGS @@ -14,7 +14,12 @@ import { import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl'; import { alertDialog } from '@/services/alertService'; -class ApplicationViewCtrl extends PureViewCtrl { +class ApplicationViewCtrl extends PureViewCtrl { private $location?: ng.ILocationService private $rootScope?: ng.IRootScopeService public platformString: string @@ -31,7 +36,7 @@ class ApplicationViewCtrl extends PureViewCtrl { this.$location = $location; this.$rootScope = $rootScope; this.platformString = getPlatformString(); - this.state = { appClass: '' }; + this.state = { appClass: '', challenges: [] }; this.onDragDrop = this.onDragDrop.bind(this); this.onDragOver = this.onDragOver.bind(this); this.addDragDropHandlers(); @@ -40,11 +45,11 @@ class ApplicationViewCtrl extends PureViewCtrl { deinit() { this.$location = undefined; this.$rootScope = undefined; - (this.application as any) = undefined; + (this.application as unknown) = undefined; window.removeEventListener('dragover', this.onDragOver, true); window.removeEventListener('drop', this.onDragDrop, true); - (this.onDragDrop as any) = undefined; - (this.onDragOver as any) = undefined; + (this.onDragDrop as unknown) = undefined; + (this.onDragOver as unknown) = undefined; super.deinit(); } @@ -59,12 +64,20 @@ class ApplicationViewCtrl extends PureViewCtrl { ); await this.application!.prepareForLaunch({ receiveChallenge: async (challenge) => { - this.application!.promptForChallenge(challenge); + this.setState({ + challenges: this.state.challenges.concat(challenge) + }); } }); await this.application!.launch(); } + public removeChallenge(challenge: Challenge) { + this.setState({ + challenges: this.state.challenges.filter(c => c.id !== challenge.id) + }); + } + async onAppStart() { super.onAppStart(); this.setState({ diff --git a/app/assets/javascripts/views/challenge_modal/challenge-modal.pug b/app/assets/javascripts/views/challenge_modal/challenge-modal.pug deleted file mode 100644 index 6277aef49..000000000 --- a/app/assets/javascripts/views/challenge_modal/challenge-modal.pug +++ /dev/null @@ -1,71 +0,0 @@ -.sk-modal-background(ng-click="ctrl.cancel()") -.challenge-modal.sk-modal-content(ng-if='ctrl.templateReady') - .sn-component - .sk-panel - .sk-panel-header - .sk-panel-header-title {{ctrl.challenge.modalTitle}} - .sk-panel-content - .sk-panel-section - .sk-p.sk-panel-row.centered.prompt - strong {{ctrl.challenge.heading}} - .sk-p.sk-panel-row.centered.subprompt(ng-if='ctrl.challenge.subheading') - | {{ctrl.challenge.subheading}} - .sk-panel-section - div(ng-repeat="prompt in ctrl.state.prompts track by prompt.id") - .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" - sn-autofocus="true" - sn-enter="ctrl.submit()" , - 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" - ) Invalid authentication. Please try again. - .sk-panel-footer.extra-padding - .sk-button.info.big.block.bold( - ng-click="ctrl.submit()", - ng-class="{'info' : !ctrl.state.processing, 'neutral': ctrl.state.processing}" - ng-disabled="ctrl.state.processing" - ) - .sk-label {{ctrl.state.processing ? 'Generating Keys...' : 'Submit'}} - .sk-panel-row(ng-if="ctrl.challenge.cancelable") - a.sk-panel-row.sk-a.info.centered( - ng-if="ctrl.challenge.cancelable" - ng-click="ctrl.cancel()" - ) Cancel - - .sk-panel-footer(ng-if="ctrl.state.showForgotPasscodeLink") - a.sk-panel-row.sk-a.info.centered( - ng-if="!ctrl.state.forgotPasscode" - ng-click="ctrl.onForgotPasscodeClick()" - ) Forgot your passcode? - p.sk-panel-row.sk-p(ng-if="ctrl.state.forgotPasscode"). - {{ - ctrl.state.hasAccount - ? "If you forgot your application passcode, your only option is to clear - your local data from this device and sign back in to your account." - : "If you forgot your application passcode, your only option is - to delete your data." - }} - a.sk-panel-row.sk-a.danger.centered( - ng-if="ctrl.state.forgotPasscode" - ng-click="ctrl.destroyLocalData()" - ) Delete Local Data - .sk-panel-row diff --git a/app/assets/javascripts/views/challenge_modal/challenge_modal.ts b/app/assets/javascripts/views/challenge_modal/challenge_modal.ts deleted file mode 100644 index a69f88b33..000000000 --- a/app/assets/javascripts/views/challenge_modal/challenge_modal.ts +++ /dev/null @@ -1,216 +0,0 @@ -import { WebApplication } from '@/ui_models/application'; -import template from './challenge-modal.pug'; -import { - ChallengeValue, - removeFromArray, - Challenge, - ChallengeReason, - 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'; - -type InputValue = { - prompt: ChallengePrompt; - value: string | number | boolean; - invalid: boolean; -}; - -type Values = Record; - -type ChallengeModalState = { - prompts: ChallengePrompt[]; - values: Partial; - processing: boolean; - forgotPasscode: boolean; - showForgotPasscodeLink: boolean; - processingPrompts: ChallengePrompt[]; - hasAccount: boolean; - protectedNoteAccessDuration: number; -}; - -class ChallengeModalCtrl extends PureViewCtrl { - application!: WebApplication; - challenge!: Challenge; - - /** @template */ - protectionsSessionDurations = ProtectionSessionDurations; - protectionsSessionValidation = - ChallengeValidation.ProtectionSessionDuration; - - /* @ngInject */ - constructor(private $element: JQLite, $timeout: ng.ITimeoutService) { - super($timeout); - } - - getState() { - return this.state as ChallengeModalState; - } - - $onInit() { - super.$onInit(); - const values = {} as Values; - const prompts = this.challenge.prompts; - for (const prompt of prompts) { - values[prompt.id] = { - prompt, - value: prompt.initialValue ?? '', - invalid: false, - }; - } - const showForgotPasscodeLink = [ - ChallengeReason.ApplicationUnlock, - ChallengeReason.Migration, - ].includes(this.challenge.reason); - this.setState({ - prompts, - values, - processing: false, - forgotPasscode: false, - showForgotPasscodeLink, - hasAccount: this.application.hasAccount(), - processingPrompts: [], - protectedNoteAccessDuration: ProtectionSessionDurations[0].valueInSeconds, - }); - 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(); - } - }, - onComplete: () => { - this.dismiss(); - }, - onCancel: () => { - this.dismiss(); - }, - }); - } - - deinit() { - (this.application as any) = undefined; - (this.challenge as any) = undefined; - super.deinit(); - } - - reloadProcessingStatus() { - return this.setState({ - processing: this.state.processingPrompts.length > 0, - }); - } - - async destroyLocalData() { - if ( - await confirmDialog({ - text: STRING_SIGN_OUT_CONFIRMATION, - confirmButtonStyle: 'danger', - }) - ) { - await this.application.signOut(); - this.dismiss(); - } - } - - /** @template */ - cancel() { - if (this.challenge.cancelable) { - this.application!.cancelChallenge(this.challenge); - } - } - - onForgotPasscodeClick() { - this.setState({ - forgotPasscode: true, - }); - } - - onTextValueChange(prompt: ChallengePrompt) { - const values = this.getState().values; - values[prompt.id]!.invalid = false; - this.setState({ values }); - } - - onValueChange(prompt: ChallengePrompt, value: number) { - const values = this.state.values; - values[prompt.id]!.invalid = false; - values[prompt.id]!.value = value; - } - - validate() { - 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 === 0; - } - - async submit() { - if (!this.validate()) { - return; - } - await this.setState({ processing: true }); - const values: ChallengeValue[] = []; - for (const inputValue of Object.values(this.getState().values)) { - 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, - }); - /** - * 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 - * (crypto key generation) - */ - this.$timeout(() => { - if (values.length > 0) { - this.application.submitValuesForChallenge(this.challenge, values); - } else { - this.setState({ processing: false }); - } - }, 50); - } - - dismiss() { - const elem = this.$element; - const scope = elem.scope(); - scope.$destroy(); - elem.remove(); - } -} - -export class ChallengeModal extends WebDirective { - constructor() { - super(); - this.restrict = 'E'; - this.template = template; - this.controller = ChallengeModalCtrl; - this.controllerAs = 'ctrl'; - this.bindToController = true; - this.scope = { - challenge: '=', - application: '=', - }; - } -} diff --git a/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx b/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx new file mode 100644 index 000000000..53b587df4 --- /dev/null +++ b/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx @@ -0,0 +1,404 @@ +import { WebApplication } from '@/ui_models/application'; +import { Dialog } from '@reach/dialog'; +import { + ChallengeValue, + removeFromArray, + Challenge, + ChallengeReason, + 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 { Ref, render } from 'preact'; +import { useRef } from 'preact/hooks'; +import ng from 'angular'; + +type InputValue = { + prompt: ChallengePrompt; + value: string | number | boolean; + invalid: boolean; +}; + +type Values = Record; + +type ChallengeModalState = { + prompts: ChallengePrompt[]; + values: Partial; + processing: boolean; + forgotPasscode: boolean; + showForgotPasscodeLink: boolean; + processingPrompts: ChallengePrompt[]; + hasAccount: boolean; + protectedNoteAccessDuration: number; +}; + +class ChallengeModalCtrl extends PureViewCtrl { + application!: WebApplication; + challenge!: Challenge; + onDismiss!: () => void; + + /** @template */ + protectionsSessionDurations = ProtectionSessionDurations; + protectionsSessionValidation = ChallengeValidation.ProtectionSessionDuration; + + /* @ngInject */ + constructor( + private $element: ng.IRootElementService, + $timeout: ng.ITimeoutService + ) { + super($timeout); + } + + getState() { + return this.state as ChallengeModalState; + } + + $onInit() { + super.$onInit(); + const values = {} as Values; + const prompts = this.challenge.prompts; + for (const prompt of prompts) { + values[prompt.id] = { + prompt, + value: prompt.initialValue ?? '', + invalid: false, + }; + } + const showForgotPasscodeLink = [ + ChallengeReason.ApplicationUnlock, + ChallengeReason.Migration, + ].includes(this.challenge.reason); + this.setState({ + prompts, + values, + processing: false, + forgotPasscode: false, + showForgotPasscodeLink, + hasAccount: this.application.hasAccount(), + processingPrompts: [], + protectedNoteAccessDuration: ProtectionSessionDurations[0].valueInSeconds, + }); + this.application.addChallengeObserver(this.challenge, { + onValidValue: (value) => { + this.state.values[value.prompt.id]!.invalid = false; + removeFromArray(this.state.processingPrompts, value.prompt); + this.reloadProcessingStatus(); + /** Trigger UI update */ + this.afterStateChange(); + }, + onInvalidValue: (value) => { + this.state.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(); + } + /** Trigger UI update */ + this.afterStateChange(); + }, + onComplete: () => { + this.dismiss(); + }, + onCancel: () => { + this.dismiss(); + }, + }); + } + + deinit() { + (this.application as any) = undefined; + (this.challenge as any) = undefined; + super.deinit(); + } + + reloadProcessingStatus() { + return this.setState({ + processing: this.state.processingPrompts.length > 0, + }); + } + + async destroyLocalData() { + if ( + await confirmDialog({ + text: STRING_SIGN_OUT_CONFIRMATION, + confirmButtonStyle: 'danger', + }) + ) { + await this.application.signOut(); + this.dismiss(); + } + } + + /** @template */ + cancel() { + if (this.challenge.cancelable) { + this.application!.cancelChallenge(this.challenge); + } + } + + onForgotPasscodeClick() { + this.setState({ + forgotPasscode: true, + }); + } + + onTextValueChange(prompt: ChallengePrompt) { + const values = this.getState().values; + values[prompt.id]!.invalid = false; + this.setState({ values }); + } + + onNumberValueChange(prompt: ChallengePrompt, value: number) { + const values = this.state.values; + values[prompt.id]!.invalid = false; + values[prompt.id]!.value = value; + this.setState({ values }); + } + + validate() { + 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 === 0; + } + + async submit() { + if (!this.validate()) { + return; + } + await this.setState({ processing: true }); + const values: ChallengeValue[] = []; + for (const inputValue of Object.values(this.getState().values)) { + 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, + }); + /** + * 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 + * (crypto key generation) + */ + this.$timeout(() => { + if (values.length > 0) { + this.application.submitValuesForChallenge(this.challenge, values); + } else { + this.setState({ processing: false }); + } + }, 50); + } + + afterStateChange() { + this.render(); + } + + dismiss() { + this.onDismiss(); + } + + $onDestroy() { + render(<>, this.$element[0]); + } + + private render() { + if (!this.state.prompts) return; + render(, this.$element[0]); + } +} + +export class ChallengeModal extends WebDirective { + constructor() { + super(); + this.restrict = 'E'; + // this.template = template; + this.controller = ChallengeModalCtrl; + this.controllerAs = 'ctrl'; + this.bindToController = true; + this.scope = { + challenge: '=', + application: '=', + onDismiss: '&', + }; + } +} + +function ChallengeModalView({ ctrl }: { ctrl: ChallengeModalCtrl }) { + const initialFocusRef = useRef(); + return ( +

{ + if (ctrl.challenge.cancelable) { + ctrl.dismiss(); + } + }} + > +
+
+
+
+
+ {ctrl.challenge.modalTitle} +
+
+
+
+
+ {ctrl.challenge.heading} +
+ {ctrl.challenge.subheading && ( +
+ {ctrl.challenge.subheading} +
+ )} +
+ +
+ {ChallengePrompts({ ctrl, initialFocusRef })} +
+
+
+
ctrl.submit()} + > +
+ {ctrl.state.processing ? 'Generating Keys…' : 'Submit'} +
+
+ {ctrl.challenge.cancelable && ( + <> +
+ ctrl.cancel()} + > + Cancel + + + )} +
+ {ctrl.state.showForgotPasscodeLink && ( +
+ {ctrl.state.forgotPasscode ? ( + <> +

+ {ctrl.state.hasAccount + ? 'If you forgot your application passcode, your ' + + 'only option is to clear your local data from this ' + + 'device and sign back in to your account.' + : 'If you forgot your application passcode, your ' + + 'only option is to delete your data.'} +

+ { + ctrl.destroyLocalData(); + }} + > + Delete Local Data + + + ) : ( + ctrl.onForgotPasscodeClick()} + > + Forgot your passcode? + + )} +
+
+ )} +
+
+
+
+ ); +} + +function ChallengePrompts({ + ctrl, + initialFocusRef, +}: { + ctrl: ChallengeModalCtrl; + initialFocusRef: Ref; +}) { + return ctrl.state.prompts.map((prompt, index) => ( + <> + {/** ProtectionSessionDuration can't just be an input field */} + {prompt.validation === ChallengeValidation.ProtectionSessionDuration ? ( + + ) : ( +
+ { + const value = (event.target as HTMLInputElement).value; + ctrl.state.values[prompt.id]!.value = value; + ctrl.onTextValueChange(prompt); + }} + onKeyDown={(event) => { + if (event.key === 'Enter') { + event.preventDefault(); + event.stopPropagation(); + ctrl.submit(); + } + }} + ref={index === 0 ? initialFocusRef : undefined} + placeholder={prompt.title} + type={prompt.secureTextEntry ? 'password' : 'text'} + /> +
+ )} + + {ctrl.state.values[prompt.id]!.invalid && ( +
+ +
+ )} + + )); +} diff --git a/app/assets/javascripts/views/index.ts b/app/assets/javascripts/views/index.ts index 55b48fe36..31cbe1ad1 100644 --- a/app/assets/javascripts/views/index.ts +++ b/app/assets/javascripts/views/index.ts @@ -6,4 +6,4 @@ export { EditorView } from './editor/editor_view'; export { FooterView } from './footer/footer_view'; export { NotesView } from './notes/notes_view'; export { TagsView } from './tags/tags_view'; -export { ChallengeModal } from './challenge_modal/challenge_modal' \ No newline at end of file +export { ChallengeModal } from './challenge_modal/challenge_modal'; \ No newline at end of file diff --git a/app/assets/stylesheets/_reach-sub.scss b/app/assets/stylesheets/_reach-sub.scss index af80a7ccf..346817713 100644 --- a/app/assets/stylesheets/_reach-sub.scss +++ b/app/assets/stylesheets/_reach-sub.scss @@ -20,11 +20,13 @@ } [data-reach-dialog-content] { + width: auto; padding: 0; margin: 0; position: relative; overflow: unset; flex-basis: 0; + min-width: 400px; max-width: 600px; } diff --git a/app/assets/stylesheets/_sessions-modal.scss b/app/assets/stylesheets/_sessions-modal.scss index 09b9f919f..6ec272de5 100644 --- a/app/assets/stylesheets/_sessions-modal.scss +++ b/app/assets/stylesheets/_sessions-modal.scss @@ -1,4 +1,7 @@ .sessions-modal { + min-width: 40vw; + width: auto; + h2, ul, p { margin: 0; padding: 0; diff --git a/package.json b/package.json index 6b63597bd..e9e55faa1 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "bundle:desktop:beta": "webpack --config webpack.prod.js --env.platform='desktop' --env.public_beta='true'", "build": "bundle install && yarn install --pure-lockfile && bundle exec rails assets:precompile && yarn bundle", "submodules": "git submodule update --init --force", - "lint": "eslint --fix app/assets/javascripts/**/*.js", + "lint": "eslint --fix app/assets/javascripts/**/*.{ts,tsx}", "tsc": "tsc --project app/assets/javascripts/tsconfig.json" }, "devDependencies": { @@ -30,8 +30,8 @@ "@types/mocha": "^7.0.2", "@types/pug": "^2.0.4", "@types/react": "^17.0.0", - "@typescript-eslint/eslint-plugin": "^3.10.1", - "@typescript-eslint/parser": "^3.10.1", + "@typescript-eslint/eslint-plugin": "^4.14.0", + "@typescript-eslint/parser": "^4.14.0", "angular": "^1.8.2", "apply-loader": "^2.0.0", "babel-eslint": "^10.1.0", @@ -40,10 +40,10 @@ "connect": "^3.7.0", "css-loader": "^3.4.2", "dotenv": "^8.2.0", - "eslint": "^6.8.0", - "eslint-config-prettier": "^6.10.0", - "eslint-plugin-import": "^2.20.1", - "eslint-plugin-promise": "^4.2.1", + "eslint": "^7.18.0", + "eslint-config-prettier": "^7.2.0", + "eslint-plugin-react": "^7.22.0", + "eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-standard": "^4.0.1", "file-loader": "^5.1.0", "html-webpack-plugin": "^4.3.0", @@ -71,12 +71,9 @@ "@reach/alert-dialog": "^0.12.1", "@reach/dialog": "^0.12.1", "@standardnotes/sncrypto-web": "^1.2.9", - "@standardnotes/snjs": "^2.0.45", + "@standardnotes/snjs": "^2.0.47", "babel-loader": "^8.2.2", "mobx": "^6.0.4", - "preact": "^10.5.7" - }, - "peerDependencies": { - "react": "^16.8.0" + "preact": "^10.5.11" } } diff --git a/yarn.lock b/yarn.lock index 42107434c..afe2486d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -966,6 +966,43 @@ resolved "https://registry.yarnpkg.com/@bugsnag/safe-json-stringify/-/safe-json-stringify-6.0.0.tgz#22abdcd83e008c369902976730c34c150148a758" integrity sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA== +"@eslint/eslintrc@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" + integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.20" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@nodelib/fs.scandir@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" + integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA== + dependencies: + "@nodelib/fs.stat" "2.0.4" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655" + integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063" + integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow== + dependencies: + "@nodelib/fs.scandir" "2.1.4" + fastq "^1.6.0" + "@reach/alert-dialog@^0.12.1": version "0.12.1" resolved "https://registry.yarnpkg.com/@reach/alert-dialog/-/alert-dialog-0.12.1.tgz#61f9bd20722761555aded777c80ec29b30c25040" @@ -1045,10 +1082,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.45": - version "2.0.45" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.45.tgz#d1c47af28a309e3b1bd30a2540fcd0c7e656972c" - integrity sha512-OqHccVx+ijqAK0aHlOtma5P3Z2JBj3l5h3KWaWoG5UR3EIIp8CpyI7nOWE8VO4y1ALfPk754D8y8d9Rx4ti7eA== +"@standardnotes/snjs@^2.0.47": + version "2.0.47" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.47.tgz#b6235faed52369168d383d6bf1ba45302f9b9cea" + integrity sha512-2d4CKdcKXg0dKYMdPPqQrLQE1NS62IWusfD2OZ0zRNbzhOHUhap/eRIURCDa0UQphKTaDaGa70x2rJl3PW4J6Q== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" @@ -1079,11 +1116,6 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.14.tgz#44d2dd0b5de6185089375d976b4ec5caf6861193" integrity sha512-G+ITQPXkwTrslfG5L/BksmbLUA0M1iybEsmCWPqzSxsRRhJZimBKJkoMi8fr/CPygPTj4zO5pJH7I2/cm9M7SQ== -"@types/eslint-visitor-keys@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" - integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== - "@types/glob@^7.1.1": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" @@ -1102,11 +1134,6 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= - "@types/lodash@^4.14.149": version "4.14.165" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.165.tgz#74d55d947452e2de0742bad65270433b63a8c30f" @@ -1188,65 +1215,76 @@ "@types/webpack-sources" "*" source-map "^0.6.0" -"@typescript-eslint/eslint-plugin@^3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" - integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== +"@typescript-eslint/eslint-plugin@^4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.0.tgz#92db8e7c357ed7d69632d6843ca70b71be3a721d" + integrity sha512-IJ5e2W7uFNfg4qh9eHkHRUCbgZ8VKtGwD07kannJvM5t/GU8P8+24NX8gi3Hf5jST5oWPY8kyV1s/WtfiZ4+Ww== dependencies: - "@typescript-eslint/experimental-utils" "3.10.1" + "@typescript-eslint/experimental-utils" "4.14.0" + "@typescript-eslint/scope-manager" "4.14.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" + lodash "^4.17.15" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" - integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== +"@typescript-eslint/experimental-utils@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.0.tgz#5aa7b006736634f588a69ee343ca959cd09988df" + integrity sha512-6i6eAoiPlXMKRbXzvoQD5Yn9L7k9ezzGRvzC/x1V3650rUk3c3AOjQyGYyF9BDxQQDK2ElmKOZRD0CbtdkMzQQ== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" + "@typescript-eslint/scope-manager" "4.14.0" + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/typescript-estree" "4.14.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" - integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== +"@typescript-eslint/parser@^4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.14.0.tgz#62d4cd2079d5c06683e9bfb200c758f292c4dee7" + integrity sha512-sUDeuCjBU+ZF3Lzw0hphTyScmDDJ5QVkyE21pRoBo8iDl7WBtVFS+WDN3blY1CH3SBt7EmYCw6wfmJjF0l/uYg== dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.10.1" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/types@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" - integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== - -"@typescript-eslint/typescript-estree@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" - integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== - dependencies: - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/visitor-keys" "3.10.1" + "@typescript-eslint/scope-manager" "4.14.0" + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/typescript-estree" "4.14.0" debug "^4.1.1" - glob "^7.1.6" + +"@typescript-eslint/scope-manager@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.14.0.tgz#55a4743095d684e1f7b7180c4bac2a0a3727f517" + integrity sha512-/J+LlRMdbPh4RdL4hfP1eCwHN5bAhFAGOTsvE6SxsrM/47XQiPSgF5MDgLyp/i9kbZV9Lx80DW0OpPkzL+uf8Q== + dependencies: + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/visitor-keys" "4.14.0" + +"@typescript-eslint/types@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.14.0.tgz#d8a8202d9b58831d6fd9cee2ba12f8a5a5dd44b6" + integrity sha512-VsQE4VvpldHrTFuVPY1ZnHn/Txw6cZGjL48e+iBxTi2ksa9DmebKjAeFmTVAYoSkTk7gjA7UqJ7pIsyifTsI4A== + +"@typescript-eslint/typescript-estree@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.0.tgz#4bcd67486e9acafc3d0c982b23a9ab8ac8911ed7" + integrity sha512-wRjZ5qLao+bvS2F7pX4qi2oLcOONIB+ru8RGBieDptq/SudYwshveORwCVU4/yMAd4GK7Fsf8Uq1tjV838erag== + dependencies: + "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/visitor-keys" "4.14.0" + debug "^4.1.1" + globby "^11.0.1" is-glob "^4.0.1" lodash "^4.17.15" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" - integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== +"@typescript-eslint/visitor-keys@4.14.0": + version "4.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.0.tgz#b1090d9d2955b044b2ea2904a22496849acbdf54" + integrity sha512-MeHHzUyRI50DuiPgV9+LxcM52FCJFYjJiWHtXlbyC27b80mfOwKeiKI+MHOTEpcpfmoPFm/vvQS88bYIx6PZTA== dependencies: - eslint-visitor-keys "^1.1.0" + "@typescript-eslint/types" "4.14.0" + eslint-visitor-keys "^2.0.0" "@webassemblyjs/ast@1.9.0": version "1.9.0" @@ -1423,7 +1461,7 @@ acorn-globals@^3.0.0: dependencies: acorn "^4.0.4" -acorn-jsx@^5.2.0: +acorn-jsx@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== @@ -1443,7 +1481,7 @@ acorn@^6.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== -acorn@^7.1.1: +acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -1468,6 +1506,16 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.3.tgz#13ae747eff125cafb230ac504b2406cf371eece2" + integrity sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -1497,12 +1545,10 @@ ansi-colors@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== -ansi-escapes@^4.2.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" - integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== - dependencies: - type-fest "^0.11.0" +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-html@0.0.7: version "0.0.7" @@ -1541,7 +1587,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -1621,7 +1667,7 @@ array-flatten@^2.1.0: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -array-includes@^3.1.1: +array-includes@^3.1.1, array-includes@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8" integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw== @@ -1639,6 +1685,11 @@ array-union@^1.0.1: dependencies: array-uniq "^1.0.1" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -1649,14 +1700,15 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -array.prototype.flat@^1.2.3: +array.prototype.flatmap@^1.2.3: version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" - integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" + integrity sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q== dependencies: call-bind "^1.0.0" define-properties "^1.1.3" es-abstract "^1.18.0-next.1" + function-bind "^1.1.1" asap@~2.0.3: version "2.0.6" @@ -1703,10 +1755,10 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async-each@^1.0.1: version "1.0.3" @@ -2124,6 +2176,14 @@ call-bind@^1.0.0: function-bind "^1.1.1" get-intrinsic "^1.0.0" +call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -2209,7 +2269,7 @@ chalk@^1.1.1: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2218,7 +2278,7 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.0: +chalk@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -2233,11 +2293,6 @@ character-parser@^2.1.1: dependencies: is-regex "^1.0.3" -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" @@ -2329,18 +2384,6 @@ clean-css@4.2.x, clean-css@^4.1.11, clean-css@^4.2.3: dependencies: source-map "~0.6.0" -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -2522,11 +2565,6 @@ constants-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= - content-disposition@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -2641,6 +2679,15 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -2721,7 +2768,7 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -2778,7 +2825,7 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= @@ -2890,6 +2937,13 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -2910,13 +2964,12 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" - isarray "^1.0.0" doctrine@^3.0.0: version "3.0.0" @@ -3073,6 +3126,13 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0: memory-fs "^0.5.0" tapable "^1.0.0" +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + entities@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -3163,52 +3223,32 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-config-prettier@^6.10.0: - version "6.15.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" - integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== - dependencies: - get-stdin "^6.0.0" +eslint-config-prettier@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz#f4a4bd2832e810e8cc7c1411ec85b3e85c0c53f9" + integrity sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg== -eslint-import-resolver-node@^0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" - integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== - dependencies: - debug "^2.6.9" - resolve "^1.13.1" +eslint-plugin-react-hooks@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" + integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== -eslint-module-utils@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" - integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA== - dependencies: - debug "^2.6.9" - pkg-dir "^2.0.0" - -eslint-plugin-import@^2.20.1: - version "2.22.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" - integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== +eslint-plugin-react@^7.22.0: + version "7.22.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz#3d1c542d1d3169c45421c1215d9470e341707269" + integrity sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA== dependencies: array-includes "^3.1.1" - array.prototype.flat "^1.2.3" - contains-path "^0.1.0" - debug "^2.6.9" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.4" - eslint-module-utils "^2.6.0" + array.prototype.flatmap "^1.2.3" + doctrine "^2.1.0" has "^1.0.3" - minimatch "^3.0.4" + jsx-ast-utils "^2.4.1 || ^3.0.0" + object.entries "^1.1.2" + object.fromentries "^2.0.2" object.values "^1.1.1" - read-pkg-up "^2.0.0" - resolve "^1.17.0" - tsconfig-paths "^3.9.0" - -eslint-plugin-promise@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" - integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== + prop-types "^15.7.2" + resolve "^1.18.1" + string.prototype.matchall "^4.0.2" eslint-plugin-standard@^4.0.1: version "4.1.0" @@ -3223,7 +3263,7 @@ eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^5.0.0: +eslint-scope@^5.0.0, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -3231,83 +3271,81 @@ eslint-scope@^5.0.0: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-utils@^2.0.0: +eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.18.0: + version "7.18.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.18.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67" + integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== dependencies: "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.3.0" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" + chalk "^4.0.0" + cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.2.0" esutils "^2.0.2" - file-entry-cache "^5.0.1" + file-entry-cache "^6.0.0" functional-red-black-tree "^1.0.1" glob-parent "^5.0.0" globals "^12.1.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" + levn "^0.4.1" + lodash "^4.17.20" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" + optionator "^0.9.1" progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.4" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.1.2: - version "6.2.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" - integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== dependencies: - acorn "^7.1.1" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: +esquery@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== @@ -3455,15 +3493,6 @@ extend@^3.0.0, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -3493,12 +3522,24 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-glob@^3.1.1: + version "3.2.5" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661" + integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -3508,6 +3549,13 @@ fastparse@^1.0.0: resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== +fastq@^1.6.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.0.tgz#74dbefccade964932cdf500473ef302719c652bb" + integrity sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA== + dependencies: + reusify "^1.0.4" + faye-websocket@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" @@ -3527,19 +3575,12 @@ figgy-pudding@^3.5.1: resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== +file-entry-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" + integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" + flat-cache "^3.0.4" file-loader@^5.1.0: version "5.1.0" @@ -3617,13 +3658,6 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - find-up@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -3642,14 +3676,13 @@ findup-sync@^3.0.0: micromatch "^3.0.4" resolve-dir "^1.0.1" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" + flatted "^3.1.0" + rimraf "^3.0.2" flat@^4.1.0: version "4.1.1" @@ -3658,10 +3691,10 @@ flat@^4.1.0: dependencies: is-buffer "~2.0.3" -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +flatted@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" + integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== flush-write-stream@^1.0.0: version "1.1.1" @@ -3820,6 +3853,15 @@ get-intrinsic@^1.0.0, get-intrinsic@^1.0.1: has "^1.0.3" has-symbols "^1.0.1" +get-intrinsic@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" + integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-nonce@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" @@ -3830,11 +3872,6 @@ get-stdin@^4.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -3862,7 +3899,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -3881,7 +3918,7 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -3941,6 +3978,18 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" +globby@^11.0.1: + version "11.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.2.tgz#1af538b766a3b540ebfb58a32b2e2d5897321d83" + integrity sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -4240,7 +4289,7 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4269,6 +4318,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + import-fresh@^3.0.0: version "3.2.2" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e" @@ -4277,6 +4331,14 @@ import-fresh@^3.0.0: parent-module "^1.0.0" resolve-from "^4.0.0" +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" @@ -4340,25 +4402,6 @@ ini@^1.3.4, ini@^1.3.5: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -inquirer@^7.0.0: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.19" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.6.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - internal-ip@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" @@ -4367,6 +4410,15 @@ internal-ip@^4.3.0: default-gateway "^4.2.0" ipaddr.js "^1.9.0" +internal-slot@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" + integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g== + dependencies: + es-abstract "^1.17.0-next.1" + has "^1.0.3" + side-channel "^1.0.2" + interpret@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" @@ -4744,6 +4796,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -4796,6 +4853,14 @@ jstransformer@1.0.0: is-promise "^2.0.0" promise "^7.0.1" +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" + integrity sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q== + dependencies: + array-includes "^3.1.2" + object.assign "^4.1.2" + killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -4830,13 +4895,13 @@ lazy-cache@^1.0.3: resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" + prelude-ls "^1.2.1" + type-check "~0.4.0" libsodium-wrappers@^0.7.8: version "0.7.8" @@ -4861,16 +4926,6 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" @@ -4885,14 +4940,6 @@ loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4 emojis-list "^3.0.0" json5 "^1.0.1" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -5062,6 +5109,11 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -5086,7 +5138,7 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.0: +micromatch@^4.0.0, micromatch@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== @@ -5129,11 +5181,6 @@ mime@^2.4.4: resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - mini-css-extract-plugin@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" @@ -5272,11 +5319,6 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - nan@^2.12.1, nan@^2.13.2: version "2.14.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" @@ -5519,7 +5561,7 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.8.0: +object-inspect@^1.8.0, object-inspect@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== @@ -5554,7 +5596,7 @@ object.assign@4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.assign@^4.1.0, object.assign@^4.1.1: +object.assign@^4.1.0, object.assign@^4.1.1, object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== @@ -5564,6 +5606,26 @@ object.assign@^4.1.0, object.assign@^4.1.1: has-symbols "^1.0.1" object-keys "^1.1.1" +object.entries@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.3.tgz#c601c7f168b62374541a07ddbd3e2d5e4f7711a6" + integrity sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has "^1.0.3" + +object.fromentries@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.3.tgz#13cefcffa702dc67750314a3305e8cb3fad1d072" + integrity sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has "^1.0.3" + object.getownpropertydescriptors@^2.0.3: version "2.1.1" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz#0dfda8d108074d9c563e80490c883b6661091544" @@ -5614,13 +5676,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - opn@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" @@ -5628,17 +5683,17 @@ opn@^5.5.0: dependencies: is-wsl "^1.1.0" -optionator@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" original@^1.0.0: version "1.0.2" @@ -5657,7 +5712,7 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= @@ -5675,13 +5730,6 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -5689,13 +5737,6 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -5722,11 +5763,6 @@ p-retry@^3.0.1: dependencies: retry "^0.12.0" -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -5851,6 +5887,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -5870,12 +5911,10 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== pathval@^1.1.0: version "1.1.0" @@ -5925,13 +5964,6 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -6017,15 +6049,15 @@ postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: source-map "^0.6.1" supports-color "^6.1.0" -preact@^10.5.7: - version "10.5.7" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.5.7.tgz#f1d84725539e18f7ccbea937cf3db5895661dbd3" - integrity sha512-4oEpz75t/0UNcwmcsjk+BIcDdk68oao+7kxcpc1hQPNs2Oo3ZL9xFz8UBf350mxk/VEdD41L5b4l2dE3Ug3RYg== +preact@^10.5.11: + version "10.5.11" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.5.11.tgz#2c8a431f16613e442901068175771806cf1cc0f6" + integrity sha512-BdtFePVilR1430kDuzh3VkkZktCmp8RTqHOjG8qesyGZXHNYJjdrjEBuc2f7O/vthhVENxJd0/aTjWtYeH46aw== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prepend-http@^1.0.0: version "1.0.4" @@ -6388,14 +6420,6 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -6405,15 +6429,6 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -6512,12 +6527,15 @@ regexp.prototype.flags@^1.2.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== +regexp.prototype.flags@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" + integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" -regexpp@^3.0.0: +regexpp@^3.0.0, regexpp@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== @@ -6615,6 +6633,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -6655,7 +6678,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.18.1: version "1.19.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== @@ -6663,14 +6686,6 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13. is-core-module "^2.1.0" path-parse "^1.0.6" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -6681,6 +6696,11 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -6695,10 +6715,10 @@ rimraf@2, rimraf@^2.5.4, rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" @@ -6710,10 +6730,10 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== +run-parallel@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" + integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" @@ -6722,13 +6742,6 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.6.0: - version "6.6.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" - integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== - dependencies: - tslib "^1.9.0" - safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -6820,12 +6833,12 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.2: +semver@^7.2.1, semver@^7.3.2: version "7.3.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== @@ -6938,12 +6951,33 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= -signal-exit@^3.0.0, signal-exit@^3.0.2: +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.2, side-channel@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== @@ -6953,14 +6987,19 @@ simple-is@~0.2.0: resolved "https://registry.yarnpkg.com/simple-is/-/simple-is-0.2.0.tgz#2abb75aade39deb5cc815ce10e6191164850baf0" integrity sha1-Krt1qt453rXMgVzhDmGRFkhQuvA= -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" sn-stylekit@2.1.0: version "2.1.0" @@ -7254,7 +7293,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0: +string-width@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== @@ -7263,6 +7302,19 @@ string-width@^4.1.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string.prototype.matchall@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz#24243399bc31b0a49d19e2b74171a15653ec996a" + integrity sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has-symbols "^1.0.1" + internal-slot "^1.0.2" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.3" + string.prototype.trimend@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" @@ -7328,11 +7380,6 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -7350,7 +7397,7 @@ strip-json-comments@2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -strip-json-comments@^3.0.1: +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -7388,15 +7435,15 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== +table@^6.0.4: + version "6.0.7" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" + integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g== dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" + ajv "^7.0.2" + lodash "^4.17.20" + slice-ansi "^4.0.0" + string-width "^4.2.0" tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" @@ -7449,11 +7496,6 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" @@ -7466,13 +7508,6 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -7561,16 +7596,6 @@ ts-loader@^8.0.12: micromatch "^4.0.0" semver "^6.0.0" -tsconfig-paths@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" - integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.1" - minimist "^1.2.0" - strip-bom "^3.0.0" - tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -7605,23 +7630,18 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: - prelude-ls "~1.1.2" + prelude-ls "^1.2.1" type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" - integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== - type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -8057,6 +8077,13 @@ which@1, which@1.3.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + wide-align@1.1.3, wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" @@ -8077,7 +8104,7 @@ with@^5.0.0: acorn "^3.1.0" acorn-globals "^3.0.0" -word-wrap@~1.2.3: +word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -8108,13 +8135,6 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" From a0909399f8a1a97024372a2caaa9f8b8d76a152d Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 22 Jan 2021 11:52:24 +0100 Subject: [PATCH 11/55] fix: lint errors --- app/assets/javascripts/database.ts | 1 + .../directives/functional/click-outside.ts | 2 +- .../directives/functional/delay-hide.ts | 8 ++--- .../directives/functional/elemReady.ts | 2 +- .../directives/functional/infiniteScroll.ts | 2 +- .../directives/views/accountMenu.ts | 2 +- .../directives/views/actionsMenu.ts | 8 ++--- .../directives/views/componentView.ts | 3 +- .../directives/views/editorMenu.ts | 6 ++-- .../directives/views/historyMenu.ts | 2 +- .../directives/views/panelResizer.ts | 6 ++-- .../directives/views/passwordWizard.ts | 2 +- app/assets/javascripts/index.ts | 1 - app/assets/javascripts/strings.ts | 8 ++--- app/assets/javascripts/utils.ts | 12 ++++--- .../views/abstract/pure_view_ctrl.ts | 5 +-- .../account_switcher/account_switcher.ts | 8 ++--- .../views/application/application_view.ts | 2 +- .../javascripts/views/editor/editor_view.ts | 32 +++++++++---------- .../views/editor_group/editor_group_view.ts | 7 +--- .../javascripts/views/footer/footer_view.ts | 4 +-- .../javascripts/views/notes/note_utils.ts | 2 +- .../javascripts/views/notes/notes_view.ts | 8 ++--- .../javascripts/views/tags/tags_view.ts | 14 ++++---- package.json | 2 +- 25 files changed, 74 insertions(+), 75 deletions(-) diff --git a/app/assets/javascripts/database.ts b/app/assets/javascripts/database.ts index deac64b9e..5134c0fd6 100644 --- a/app/assets/javascripts/database.ts +++ b/app/assets/javascripts/database.ts @@ -135,6 +135,7 @@ export class Database { const db = (await this.openDatabase())!; const transaction = db.transaction(STORE_NAME, READ_WRITE); return new Promise((resolve, reject) => { + // eslint-disable-next-line @typescript-eslint/no-empty-function transaction.oncomplete = () => { }; transaction.onerror = (event) => { const target = event!.target! as any; diff --git a/app/assets/javascripts/directives/functional/click-outside.ts b/app/assets/javascripts/directives/functional/click-outside.ts index 0b6246bdd..5f0a6d034 100644 --- a/app/assets/javascripts/directives/functional/click-outside.ts +++ b/app/assets/javascripts/directives/functional/click-outside.ts @@ -22,7 +22,7 @@ export function clickOutside($document: ng.IDocumentService) { $scope.$apply(attrs.clickOutside); didApplyClickOutside = true; } - }; + } $scope.$on('$destroy', () => { attrs.clickOutside = undefined; diff --git a/app/assets/javascripts/directives/functional/delay-hide.ts b/app/assets/javascripts/directives/functional/delay-hide.ts index 8625c4c21..f28588edb 100644 --- a/app/assets/javascripts/directives/functional/delay-hide.ts +++ b/app/assets/javascripts/directives/functional/delay-hide.ts @@ -16,23 +16,23 @@ export function delayHide($timeout: ng.ITimeoutService) { scopeAny.hidePromise = null; } showElement(true); - } + }; const hideSpinner = () => { scopeAny.hidePromise = $timeout( showElement.bind(this as any, false), getDelay() ); - } + }; const showElement = (show: boolean) => { show ? elem.css({ display: '' }) : elem.css({ display: 'none' }); - } + }; const getDelay = () => { const delay = parseInt(scopeAny.delay); return angular.isNumber(delay) ? delay : 200; - } + }; showElement(false); // Whenever the scope variable updates we simply diff --git a/app/assets/javascripts/directives/functional/elemReady.ts b/app/assets/javascripts/directives/functional/elemReady.ts index 2387f0083..f5d91ec28 100644 --- a/app/assets/javascripts/directives/functional/elemReady.ts +++ b/app/assets/javascripts/directives/functional/elemReady.ts @@ -5,7 +5,7 @@ export function elemReady($parse: ng.IParseService) { link: function($scope: ng.IScope, elem: JQLite, attrs: any) { elem.ready(function() { $scope.$apply(function() { - var func = $parse(attrs.elemReady); + const func = $parse(attrs.elemReady); func($scope); }); }); diff --git a/app/assets/javascripts/directives/functional/infiniteScroll.ts b/app/assets/javascripts/directives/functional/infiniteScroll.ts index 1e8b10241..349a59946 100644 --- a/app/assets/javascripts/directives/functional/infiniteScroll.ts +++ b/app/assets/javascripts/directives/functional/infiniteScroll.ts @@ -19,7 +19,7 @@ export function infiniteScroll() { }; elem.on('scroll', scopeAny.onScroll); scope.$on('$destroy', () => { - elem.off('scroll', scopeAny.onScroll);; + elem.off('scroll', scopeAny.onScroll); }); } }; diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index a0e76fa5d..7c044bc51 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -140,7 +140,7 @@ class AccountMenuCtrl extends PureViewCtrl { syncInProgress: sync.inProgress, syncError: sync.errorMessage, }); - }) + }); this.removeBetaWarningListener = autorun(() => { this.setState({ showBetaWarning: this.appState.showBetaWarning diff --git a/app/assets/javascripts/directives/views/actionsMenu.ts b/app/assets/javascripts/directives/views/actionsMenu.ts index 99d60426a..e9f2a6689 100644 --- a/app/assets/javascripts/directives/views/actionsMenu.ts +++ b/app/assets/javascripts/directives/views/actionsMenu.ts @@ -40,7 +40,7 @@ type ActionsMenuState = { }[] } -class ActionsMenuCtrl extends PureViewCtrl<{}, ActionsMenuState> implements ActionsMenuScope { +class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { application!: WebApplication item!: SNItem private removeHiddenExtensionsListener?: IReactionDisposer; @@ -63,7 +63,7 @@ class ActionsMenuCtrl extends PureViewCtrl<{}, ActionsMenuState> implements Acti hiddenExtensions: this.appState.actionsMenu.hiddenExtensions }); }); - }; + } deinit() { this.removeHiddenExtensionsListener?.(); @@ -74,7 +74,7 @@ class ActionsMenuCtrl extends PureViewCtrl<{}, ActionsMenuState> implements Acti const extensions = this.application.actionsManager!.getExtensions().sort((a, b) => { return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; }); - let extensionsState: Record = {}; + const extensionsState: Record = {}; extensions.map((extension) => { extensionsState[extension.uuid] = { loading: false, @@ -114,7 +114,7 @@ class ActionsMenuCtrl extends PureViewCtrl<{}, ActionsMenuState> implements Acti return { ...action, subrows: this.subRowsForAction(action, extension) - } + }; } else { return action; } diff --git a/app/assets/javascripts/directives/views/componentView.ts b/app/assets/javascripts/directives/views/componentView.ts index 4819a002f..a4488e17a 100644 --- a/app/assets/javascripts/directives/views/componentView.ts +++ b/app/assets/javascripts/directives/views/componentView.ts @@ -159,7 +159,7 @@ class ComponentViewCtrl implements ComponentViewScope { this.$timeout(() => { this.reloading = false; }); - }) + }); } private onVisibilityChange() { @@ -228,6 +228,7 @@ class ComponentViewCtrl implements ComponentViewScope { if (!iframe.contentWindow!.origin || iframe.contentWindow!.origin === 'null') { desktopError = true; } + // eslint-disable-next-line no-empty } catch (e) { } } this.$timeout.cancel(this.loadTimeout); diff --git a/app/assets/javascripts/directives/views/editorMenu.ts b/app/assets/javascripts/directives/views/editorMenu.ts index d4e4c4906..3f2d0244e 100644 --- a/app/assets/javascripts/directives/views/editorMenu.ts +++ b/app/assets/javascripts/directives/views/editorMenu.ts @@ -52,14 +52,14 @@ class EditorMenuCtrl extends PureViewCtrl implements EditorMenuScope { editors: editors, defaultEditor: defaultEditor }); - }; + } selectComponent(component: SNComponent) { if (component) { if (component.conflictOf) { this.application.changeAndSaveItem(component.uuid, (mutator) => { mutator.conflictOf = undefined; - }) + }); } } this.$timeout(() => { @@ -87,7 +87,7 @@ class EditorMenuCtrl extends PureViewCtrl implements EditorMenuScope { this.application.changeItem(currentDefault.uuid, (m) => { const mutator = m as ComponentMutator; mutator.defaultEditor = false; - }) + }); } this.application.changeAndSaveItem(component.uuid, (m) => { const mutator = m as ComponentMutator; diff --git a/app/assets/javascripts/directives/views/historyMenu.ts b/app/assets/javascripts/directives/views/historyMenu.ts index c933d91a1..762791070 100644 --- a/app/assets/javascripts/directives/views/historyMenu.ts +++ b/app/assets/javascripts/directives/views/historyMenu.ts @@ -16,7 +16,7 @@ interface HistoryScope { item: SNItem } -class HistoryMenuCtrl extends PureViewCtrl<{}, HistoryState> implements HistoryScope { +class HistoryMenuCtrl extends PureViewCtrl implements HistoryScope { diskEnabled = false autoOptimize = false diff --git a/app/assets/javascripts/directives/views/panelResizer.ts b/app/assets/javascripts/directives/views/panelResizer.ts index 352aaca9c..67307e618 100644 --- a/app/assets/javascripts/directives/views/panelResizer.ts +++ b/app/assets/javascripts/directives/views/panelResizer.ts @@ -6,12 +6,12 @@ import { debounce } from '@/utils'; enum PanelSide { Right = 'right', Left = 'left' -}; +} enum MouseEventType { Move = 'mousemove', Down = 'mousedown', Up = 'mouseup' -}; +} enum CssClass { Hoverable = 'hoverable', AlwaysVisible = 'always-visible', @@ -19,7 +19,7 @@ enum CssClass { NoSelection = 'no-selection', Collapsed = 'collapsed', AnimateOpacity = 'animate-opacity', -}; +} const WINDOW_EVENT_RESIZE = 'resize'; type ResizeFinishCallback = ( diff --git a/app/assets/javascripts/directives/views/passwordWizard.ts b/app/assets/javascripts/directives/views/passwordWizard.ts index 36ea4fa71..934ebb1fe 100644 --- a/app/assets/javascripts/directives/views/passwordWizard.ts +++ b/app/assets/javascripts/directives/views/passwordWizard.ts @@ -7,7 +7,7 @@ const DEFAULT_CONTINUE_TITLE = "Continue"; enum Steps { PasswordStep = 1, FinishStep = 2 -}; +} type FormData = { currentPassword?: string, diff --git a/app/assets/javascripts/index.ts b/app/assets/javascripts/index.ts index 2e0778d4a..d623c79f5 100644 --- a/app/assets/javascripts/index.ts +++ b/app/assets/javascripts/index.ts @@ -15,5 +15,4 @@ import '../../../vendor/assets/javascripts/zip/zip'; import '../../../vendor/assets/javascripts/zip/z-worker'; // entry point -// eslint-disable-next-line import/first import './app'; diff --git a/app/assets/javascripts/strings.ts b/app/assets/javascripts/strings.ts index 6f4dbff99..cf2c79458 100644 --- a/app/assets/javascripts/strings.ts +++ b/app/assets/javascripts/strings.ts @@ -13,7 +13,7 @@ export const STRING_NEW_UPDATE_READY = "A new update is ready to install. Please export const STRING_DELETE_TAG = "Are you sure you want to delete this tag? Note: deleting a tag will not delete its notes."; /** @editor */ -export const STRING_SAVING_WHILE_DOCUMENT_HIDDEN = 'Attempting to save an item while the application is hidden. To protect data integrity, please refresh the application window and try again.' +export const STRING_SAVING_WHILE_DOCUMENT_HIDDEN = 'Attempting to save an item while the application is hidden. To protect data integrity, please refresh the application window and try again.'; export const STRING_DELETED_NOTE = "The note you are attempting to edit has been deleted, and is awaiting sync. Changes you make will be disregarded."; export const STRING_INVALID_NOTE = "The note you are attempting to save can not be found or has been deleted. Changes you make will not be synced. Please copy this note's text and start a new note."; export const STRING_ELLIPSES = "..."; @@ -56,15 +56,15 @@ export const STRING_FAILED_PASSWORD_CHANGE = "There was an error re-encrypting y export const STRING_CONFIRM_APP_QUIT_DURING_UPGRADE = "The encryption upgrade is in progress. You may lose data if you quit the app. " + - "Are you sure you want to quit?" + "Are you sure you want to quit?"; export const STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_CHANGE = "A passcode change is in progress. You may lose data if you quit the app. " + - "Are you sure you want to quit?" + "Are you sure you want to quit?"; export const STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL = "A passcode removal is in progress. You may lose data if you quit the app. " + - "Are you sure you want to quit?" + "Are you sure you want to quit?"; export const STRING_UPGRADE_ACCOUNT_CONFIRM_TITLE = 'Encryption upgrade available'; export const STRING_UPGRADE_ACCOUNT_CONFIRM_TEXT = diff --git a/app/assets/javascripts/utils.ts b/app/assets/javascripts/utils.ts index 586d943c9..54e51b6bc 100644 --- a/app/assets/javascripts/utils.ts +++ b/app/assets/javascripts/utils.ts @@ -50,7 +50,9 @@ export function dateToLocalizedString(date: Date) { export function debounce(this: any, func: any, wait: number, immediate = false) { let timeout: any; return () => { + // eslint-disable-next-line @typescript-eslint/no-this-alias const context = this; + // eslint-disable-next-line prefer-rest-params const args = arguments; const later = function () { timeout = null; @@ -61,7 +63,7 @@ export function debounce(this: any, func: any, wait: number, immediate = false) timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; -}; +} // https://tc39.github.io/ecma262/#sec-array.prototype.includes if (!Array.prototype.includes) { @@ -73,10 +75,10 @@ if (!Array.prototype.includes) { } // 1. Let O be ? ToObject(this value). - var o = Object(this); + const o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). - var len = o.length >>> 0; + const len = o.length >>> 0; // 3. If len is 0, return false. if (len === 0) { @@ -85,14 +87,14 @@ if (!Array.prototype.includes) { // 4. Let n be ? ToInteger(fromIndex). // (If fromIndex is undefined, this step produces the value 0.) - var n = fromIndex | 0; + const n = fromIndex | 0; // 5. If n ≥ 0, then // a. Let k be n. // 6. Else n < 0, // a. Let k be len + n. // b. If k < 0, let k be 0. - var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); + let k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); function sameValueZero(x: number, y: number) { return ( diff --git a/app/assets/javascripts/views/abstract/pure_view_ctrl.ts b/app/assets/javascripts/views/abstract/pure_view_ctrl.ts index 41b7f9c3d..0c104d7dd 100644 --- a/app/assets/javascripts/views/abstract/pure_view_ctrl.ts +++ b/app/assets/javascripts/views/abstract/pure_view_ctrl.ts @@ -30,7 +30,7 @@ export class PureViewCtrl

{ this.state = { ...this.getInitialState(), ...this.state, - } + }; this.addAppEventObserver(); this.addAppStateObserver(); this.templateReady = true; @@ -83,7 +83,8 @@ export class PureViewCtrl

{ } /** @override */ - afterStateChange() { + // eslint-disable-next-line @typescript-eslint/no-empty-function + afterStateChange(): void { } /** @returns a promise that resolves after the UI has been updated. */ diff --git a/app/assets/javascripts/views/account_switcher/account_switcher.ts b/app/assets/javascripts/views/account_switcher/account_switcher.ts index 3cbb1d4ed..9ca75b1eb 100644 --- a/app/assets/javascripts/views/account_switcher/account_switcher.ts +++ b/app/assets/javascripts/views/account_switcher/account_switcher.ts @@ -7,7 +7,7 @@ import { import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl'; import { WebDirective } from '@/types'; -class AccountSwitcherCtrl extends PureViewCtrl<{}, { +class AccountSwitcherCtrl extends PureViewCtrl { @@ -38,7 +38,7 @@ class AccountSwitcherCtrl extends PureViewCtrl<{}, { reloadApplications() { this.setState({ descriptors: this.mainApplicationGroup.getDescriptors() - }) + }); } /** @template */ @@ -63,7 +63,7 @@ class AccountSwitcherCtrl extends PureViewCtrl<{}, { this.setState({ editingDescriptor: descriptor }).then(() => { const input = this.inputForDescriptor(descriptor); input?.focus(); - }) + }); } /** @template */ @@ -71,7 +71,7 @@ class AccountSwitcherCtrl extends PureViewCtrl<{}, { this.mainApplicationGroup.renameDescriptor( this.state.editingDescriptor!, this.state.editingDescriptor!.label - ) + ); this.setState({ editingDescriptor: undefined }); } diff --git a/app/assets/javascripts/views/application/application_view.ts b/app/assets/javascripts/views/application/application_view.ts index f71ac35d4..eef430c3c 100644 --- a/app/assets/javascripts/views/application/application_view.ts +++ b/app/assets/javascripts/views/application/application_view.ts @@ -94,7 +94,7 @@ class ApplicationViewCtrl extends PureViewCtrl { this.onPanelResizeFinish = this.onPanelResizeFinish.bind(this); this.onEditorLoad = () => { this.application!.getDesktopService().redoSearch(); - } + }; } deinit() { @@ -199,7 +199,7 @@ class EditorViewCtrl extends PureViewCtrl { if (note.lastSyncBegan) { if (note.lastSyncEnd) { if (note.lastSyncBegan!.getTime() > note.lastSyncEnd!.getTime()) { - this.showSavingStatus() + this.showSavingStatus(); } else if (note.lastSyncEnd!.getTime() > note.lastSyncBegan!.getTime()) { this.showAllChangesSavedStatus(); } @@ -412,7 +412,7 @@ class EditorViewCtrl extends PureViewCtrl { await this.application.changeItem(this.note.uuid, (mutator) => { const noteMutator = mutator as NoteMutator; noteMutator.prefersPlainEditor = false; - }) + }); } await this.associateComponentWithCurrentNote(component); } @@ -471,7 +471,7 @@ class EditorViewCtrl extends PureViewCtrl { (mutator) => { mutator.addItemAsRelationship(note); } - ) + ); } if (!this.application.findItem(note.uuid)) { this.application.alertService!.alert( @@ -494,7 +494,7 @@ class EditorViewCtrl extends PureViewCtrl { noteMutator.preview_plain = previewPlain; noteMutator.preview_html = undefined; } - }, isUserModified) + }, isUserModified); if (this.saveTimeout) { this.$timeout.cancel(this.saveTimeout); } @@ -549,7 +549,7 @@ class EditorViewCtrl extends PureViewCtrl { this.statusTimeout = this.$timeout(() => { this.setState({ noteStatus: status - }) + }); }, MINIMUM_STATUS_DURATION); } else { this.setState({ @@ -702,7 +702,7 @@ class EditorViewCtrl extends PureViewCtrl { false, true, (mutator) => { - mutator.pinned = !this.note.pinned + mutator.pinned = !this.note.pinned; } ); } @@ -713,7 +713,7 @@ class EditorViewCtrl extends PureViewCtrl { false, true, (mutator) => { - mutator.locked = !this.note.locked + mutator.locked = !this.note.locked; } ); } @@ -724,7 +724,7 @@ class EditorViewCtrl extends PureViewCtrl { false, true, (mutator) => { - mutator.protected = !this.note.protected + mutator.protected = !this.note.protected; } ); } @@ -735,7 +735,7 @@ class EditorViewCtrl extends PureViewCtrl { false, true, (mutator) => { - mutator.hidePreview = !this.note.hidePreview + mutator.hidePreview = !this.note.hidePreview; } ); } @@ -754,7 +754,7 @@ class EditorViewCtrl extends PureViewCtrl { false, true, (mutator) => { - mutator.archived = !this.note.archived + mutator.archived = !this.note.archived; }, /** If we are unarchiving, and we are in the archived tag, close the editor */ this.note.archived && this.appState.selectedTag?.isArchiveTag @@ -863,7 +863,7 @@ class EditorViewCtrl extends PureViewCtrl { (mutator) => { mutator.addItemAsRelationship(note); } - ) + ); } this.application.sync(); this.reloadTags(); @@ -970,7 +970,7 @@ class EditorViewCtrl extends PureViewCtrl { ); await this.setState({ [key]: !currentValue - }) + }); this.reloadFont(); if (key === PrefKey.EditorSpellcheck) { @@ -1061,7 +1061,7 @@ class EditorViewCtrl extends PureViewCtrl { (mutator) => { mutator.addItemAsRelationship(this.note); } - ) + ); } } } @@ -1120,7 +1120,7 @@ class EditorViewCtrl extends PureViewCtrl { const mutator = m as ComponentMutator; mutator.removeAssociatedItemId(note.uuid); mutator.disassociateWithItem(note.uuid); - }) + }); } async associateComponentWithCurrentNote(component: SNComponent) { @@ -1129,7 +1129,7 @@ class EditorViewCtrl extends PureViewCtrl { const mutator = m as ComponentMutator; mutator.removeDisassociatedItemId(note.uuid); mutator.associateWithItem(note.uuid); - }) + }); } registerKeyboardShortcuts() { diff --git a/app/assets/javascripts/views/editor_group/editor_group_view.ts b/app/assets/javascripts/views/editor_group/editor_group_view.ts index 3848f133a..d365fd6b6 100644 --- a/app/assets/javascripts/views/editor_group/editor_group_view.ts +++ b/app/assets/javascripts/views/editor_group/editor_group_view.ts @@ -8,15 +8,10 @@ class EditorGroupViewCtrl { private application!: WebApplication public editors: Editor[] = [] - /* @ngInject */ - constructor() { - - } - $onInit() { this.application.editorGroup.addChangeObserver(() => { this.editors = this.application.editorGroup.editors; - }) + }); } } diff --git a/app/assets/javascripts/views/footer/footer_view.ts b/app/assets/javascripts/views/footer/footer_view.ts index 1e029617a..4012a2176 100644 --- a/app/assets/javascripts/views/footer/footer_view.ts +++ b/app/assets/javascripts/views/footer/footer_view.ts @@ -208,7 +208,7 @@ class FooterViewCtrl extends PureViewCtrl { +class NotesViewCtrl extends PureViewCtrl { private panelPuppet?: PanelPuppet private reloadNotesPromise?: any @@ -410,7 +410,7 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { if (activeNote && activeNote.conflictOf) { this.application!.changeAndSaveItem(activeNote.uuid, (mutator) => { mutator.conflictOf = undefined; - }) + }); } if (this.isFiltering()) { this.application!.getDesktopService().searchText(this.getState().noteFilter.text); @@ -641,7 +641,7 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { selectNextNote() { const displayableNotes = this.displayableNotes(); const currentIndex = displayableNotes.findIndex((candidate) => { - return candidate.uuid === this.activeEditorNote!.uuid + return candidate.uuid === this.activeEditorNote!.uuid; }); if (currentIndex + 1 < displayableNotes.length) { this.selectNote(displayableNotes[currentIndex + 1]); @@ -798,7 +798,7 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { ], onKeyDown: () => { const searchBar = this.getSearchBar(); - if (searchBar) { searchBar.focus(); }; + if (searchBar) { searchBar.focus(); } } }); } diff --git a/app/assets/javascripts/views/tags/tags_view.ts b/app/assets/javascripts/views/tags/tags_view.ts index 01f9bcb8a..b4a609f59 100644 --- a/app/assets/javascripts/views/tags/tags_view.ts +++ b/app/assets/javascripts/views/tags/tags_view.ts @@ -36,7 +36,7 @@ type TagState = { templateTag?: SNTag } -class TagsViewCtrl extends PureViewCtrl<{}, TagState> { +class TagsViewCtrl extends PureViewCtrl { /** Passed through template */ readonly application!: WebApplication @@ -136,7 +136,7 @@ class TagsViewCtrl extends PureViewCtrl<{}, TagState> { } else { this.setState({ selectedTag: matchingTag - }) + }); } } } @@ -186,14 +186,14 @@ class TagsViewCtrl extends PureViewCtrl<{}, TagState> { const notes = this.application.notesMatchingSmartTag(tag as SNSmartTag) .filter((note) => { return !note.archived && !note.trashed; - }) + }); noteCounts[tag.uuid] = notes.length; } } else { const notes = this.application.referencesForItem(tag, ContentType.Note) .filter((note) => { return !note.archived && !note.trashed; - }) + }); noteCounts[tag.uuid] = notes.length; } } @@ -264,7 +264,7 @@ class TagsViewCtrl extends PureViewCtrl<{}, TagState> { if (tag.conflictOf) { this.application.changeAndSaveItem(tag.uuid, (mutator) => { mutator.conflictOf = undefined; - }) + }); } this.application.getAppState().setSelectedTag(tag); } @@ -326,7 +326,7 @@ class TagsViewCtrl extends PureViewCtrl<{}, TagState> { "A tag with this name already exists." ); return; - }; + } await this.application.changeAndSaveItem(tag.uuid, (mutator) => { mutator.title = newTitle; }); @@ -350,7 +350,7 @@ class TagsViewCtrl extends PureViewCtrl<{}, TagState> { "A tag with this name already exists." ); return; - }; + } const insertedTag = await this.application.insertItem(newTag); const changedTag = await this.application.changeItem(insertedTag.uuid, (m) => { m.title = newTitle; diff --git a/package.json b/package.json index e9e55faa1..609a14a91 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "bundle:desktop:beta": "webpack --config webpack.prod.js --env.platform='desktop' --env.public_beta='true'", "build": "bundle install && yarn install --pure-lockfile && bundle exec rails assets:precompile && yarn bundle", "submodules": "git submodule update --init --force", - "lint": "eslint --fix app/assets/javascripts/**/*.{ts,tsx}", + "lint": "eslint --fix app/assets/javascripts", "tsc": "tsc --project app/assets/javascripts/tsconfig.json" }, "devDependencies": { From afb12f1420fd57ab6477308c729786252131647d Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 22 Jan 2021 12:08:48 +0100 Subject: [PATCH 12/55] fix: launch state error --- .../javascripts/views/application/application_view.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/views/application/application_view.ts b/app/assets/javascripts/views/application/application_view.ts index eef430c3c..9e3223253 100644 --- a/app/assets/javascripts/views/application/application_view.ts +++ b/app/assets/javascripts/views/application/application_view.ts @@ -36,7 +36,7 @@ class ApplicationViewCtrl extends PureViewCtrl { + this.setState({ challenges: this.state.challenges.concat(challenge) }); From 611ca2fd1308d998165c0a6e5c99ae8554dd1609 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 22 Jan 2021 12:48:14 +0100 Subject: [PATCH 13/55] fix: challenge modal: cancel instead of dismiss when pressing escape --- .../javascripts/views/challenge_modal/challenge_modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx b/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx index 53b587df4..cc4495e74 100644 --- a/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx +++ b/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx @@ -244,7 +244,7 @@ function ChallengeModalView({ ctrl }: { ctrl: ChallengeModalCtrl }) { initialFocusRef={initialFocusRef} onDismiss={() => { if (ctrl.challenge.cancelable) { - ctrl.dismiss(); + ctrl.cancel(); } }} > From 5f025406681815f192083139f9d18b19d4e49936 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 22 Jan 2021 12:56:11 +0100 Subject: [PATCH 14/55] feat: improve focus styles --- app/assets/stylesheets/_editor.scss | 8 ++++++++ app/assets/stylesheets/_notes.scss | 6 ------ app/assets/stylesheets/_stylekit-sub.scss | 13 ++++++++++++- app/assets/stylesheets/_tags.scss | 1 + 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/_editor.scss b/app/assets/stylesheets/_editor.scss index 5ae221361..18ac1d6a3 100644 --- a/app/assets/stylesheets/_editor.scss +++ b/app/assets/stylesheets/_editor.scss @@ -64,6 +64,9 @@ $heading-height: 75px; &:disabled { color: var(--sn-stylekit-editor-foreground-color); } + &:focus { + box-shadow: none; + } } } @@ -117,6 +120,7 @@ $heading-height: 75px; &:focus { outline: 0; + box-shadow: none; } } } @@ -182,3 +186,7 @@ $heading-height: 75px; } } } + +#note-text-editor:focus { + box-shadow: none; +} diff --git a/app/assets/stylesheets/_notes.scss b/app/assets/stylesheets/_notes.scss index 38a22d8a7..72ba2f762 100644 --- a/app/assets/stylesheets/_notes.scss +++ b/app/assets/stylesheets/_notes.scss @@ -67,12 +67,6 @@ border-color: transparent; width: 100%; position: relative; - - &:focus { - outline: 0; - border-color: var(--sn-stylekit-info-color); - border-width: 1px; - } } #search-clear-button { diff --git a/app/assets/stylesheets/_stylekit-sub.scss b/app/assets/stylesheets/_stylekit-sub.scss index 70dc79d8f..2a500e677 100644 --- a/app/assets/stylesheets/_stylekit-sub.scss +++ b/app/assets/stylesheets/_stylekit-sub.scss @@ -49,6 +49,7 @@ .sk-panel { .sk-panel-header { .close-button { + border-radius: var(--sn-stylekit-general-border-radius); &:hover { text-decoration: none; } @@ -88,5 +89,15 @@ button.sk-a { } *:focus { - outline: solid var(--sn-stylekit-info-color) 2px; + outline: none; + box-shadow: 0 0 0 2px var(--sn-stylekit-info-color); +} + +input:focus { + box-shadow: 0 0 0 1px var(--sn-stylekit-info-color); +} + +.sk-button:focus, button:focus { + box-shadow: 0 0 0 2px var(--sn-stylekit-background-color), + 0 0 0 4px var(--sn-stylekit-info-color); } diff --git a/app/assets/stylesheets/_tags.scss b/app/assets/stylesheets/_tags.scss index d0669405f..95060e799 100644 --- a/app/assets/stylesheets/_tags.scss +++ b/app/assets/stylesheets/_tags.scss @@ -91,6 +91,7 @@ &:focus { outline: 0; + box-shadow: 0; } pointer-events: none; From d9576b4afe2b5b003575c7a3503735488e6616a8 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 22 Jan 2021 12:56:41 +0100 Subject: [PATCH 15/55] fix: cancel session revoking when pressing escape on confirm dialog --- app/assets/javascripts/directives/views/sessionsModal.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/directives/views/sessionsModal.tsx b/app/assets/javascripts/directives/views/sessionsModal.tsx index 18a53c0f3..c1d66fc1a 100644 --- a/app/assets/javascripts/directives/views/sessionsModal.tsx +++ b/app/assets/javascripts/directives/views/sessionsModal.tsx @@ -197,7 +197,12 @@ const SessionsModal: FunctionComponent<{

{confirmRevokingSessionUuid && ( - + { + setRevokingSessionUuid(''); + }} + leastDestructiveRef={cancelRevokeRef} + >
From 7e39d7c2831b70e252c0039cc316619e8e963d6b Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 22 Jan 2021 12:56:52 +0100 Subject: [PATCH 16/55] fix: lint warning --- app/assets/javascripts/directives/views/sessionsModal.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/directives/views/sessionsModal.tsx b/app/assets/javascripts/directives/views/sessionsModal.tsx index c1d66fc1a..89ad38eff 100644 --- a/app/assets/javascripts/directives/views/sessionsModal.tsx +++ b/app/assets/javascripts/directives/views/sessionsModal.tsx @@ -18,7 +18,10 @@ import { AlertDialogLabel, } from '@reach/alert-dialog'; -function useAutorun(view: (r: IReactionPublic) => any, opts?: IAutorunOptions) { +function useAutorun( + view: (r: IReactionPublic) => unknown, + opts?: IAutorunOptions +) { useEffect(() => autorun(view, opts), [view, opts]); } From 30ddaec0f7a219849d3959ffa7885885ba61149d Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 22 Jan 2021 13:07:11 +0100 Subject: [PATCH 17/55] chore(deps): upgrade minor versions --- package.json | 18 ++-- yarn.lock | 238 ++++++++++++++++++++++++--------------------------- 2 files changed, 121 insertions(+), 135 deletions(-) diff --git a/package.json b/package.json index 609a14a91..cf8300d96 100644 --- a/package.json +++ b/package.json @@ -21,12 +21,11 @@ }, "devDependencies": { "@babel/core": "^7.12.10", - "@babel/plugin-transform-react-jsx": "^7.12.10", - "@babel/preset-env": "^7.12.10", + "@babel/plugin-transform-react-jsx": "^7.12.12", + "@babel/preset-env": "^7.12.11", "@babel/preset-typescript": "^7.12.7", "@types/angular": "^1.8.0", - "@types/chai": "^4.2.11", - "@types/lodash": "^4.14.149", + "@types/lodash": "^4.14.168", "@types/mocha": "^7.0.2", "@types/pug": "^2.0.4", "@types/react": "^17.0.0", @@ -44,10 +43,9 @@ "eslint-config-prettier": "^7.2.0", "eslint-plugin-react": "^7.22.0", "eslint-plugin-react-hooks": "^4.2.0", - "eslint-plugin-standard": "^4.0.1", "file-loader": "^5.1.0", "html-webpack-plugin": "^4.3.0", - "lodash": "^4.17.19", + "lodash": "^4.17.20", "mini-css-extract-plugin": "^0.9.0", "mocha": "^7.1.0", "ng-cache-loader": "0.0.26", @@ -57,20 +55,20 @@ "sass-loader": "^8.0.2", "serve-static": "^1.14.1", "sn-stylekit": "2.1.0", - "ts-loader": "^8.0.12", + "ts-loader": "^8.0.14", "typescript": "^4.1.3", "typescript-eslint": "0.0.1-alpha.0", "webpack": "^4.44.1", "webpack-cli": "^3.3.12", - "webpack-dev-server": "^3.11.0", + "webpack-dev-server": "^3.11.2", "webpack-merge": "^4.2.2" }, "dependencies": { - "@bugsnag/js": "^7.5.1", + "@bugsnag/js": "^7.6.0", "@reach/alert": "^0.12.1", "@reach/alert-dialog": "^0.12.1", "@reach/dialog": "^0.12.1", - "@standardnotes/sncrypto-web": "^1.2.9", + "@standardnotes/sncrypto-web": "^1.2.10", "@standardnotes/snjs": "^2.0.47", "babel-loader": "^8.2.2", "mobx": "^6.0.4", diff --git a/yarn.lock b/yarn.lock index afe2486d0..93efa3aea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -75,23 +75,6 @@ "@babel/helper-explode-assignable-expression" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-builder-react-jsx-experimental@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.10.tgz#a58cb96a793dc0fcd5c9ed3bb36d62fdc60534c2" - integrity sha512-3Kcr2LGpL7CTRDTTYm1bzeor9qZbxbvU2AxsLA6mUG9gYarSfIKMK0UlU+azLWI+s0+BH768bwyaziWB2NOJlQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.10" - "@babel/helper-module-imports" "^7.12.5" - "@babel/types" "^7.12.10" - -"@babel/helper-builder-react-jsx@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" - integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/helper-compilation-targets@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" @@ -246,11 +229,21 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + "@babel/helper-validator-option@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9" integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== +"@babel/helper-validator-option@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== + "@babel/helper-wrap-function@^7.10.4": version "7.12.3" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" @@ -517,10 +510,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-block-scoping@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz#f0ee727874b42a208a48a586b84c3d222c2bbef1" - integrity sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w== +"@babel/plugin-transform-block-scoping@^7.12.11": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -678,15 +671,16 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-jsx@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.10.tgz#a7af3097c73479123594c8c8fe39545abebd44e3" - integrity sha512-MM7/BC8QdHXM7Qc1wdnuk73R4gbuOpfrSUgfV/nODGc86sPY1tgmY2M9E9uAnf2e4DOIp8aKGWqgZfQxnTNGuw== +"@babel/plugin-transform-react-jsx@^7.12.12": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e" + integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw== dependencies: - "@babel/helper-builder-react-jsx" "^7.10.4" - "@babel/helper-builder-react-jsx-experimental" "^7.12.10" + "@babel/helper-annotate-as-pure" "^7.12.10" + "@babel/helper-module-imports" "^7.12.5" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.12.1" + "@babel/types" "^7.12.12" "@babel/plugin-transform-regenerator@^7.12.1": version "7.12.1" @@ -762,16 +756,16 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/preset-env@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.10.tgz#ca981b95f641f2610531bd71948656306905e6ab" - integrity sha512-Gz9hnBT/tGeTE2DBNDkD7BiWRELZt+8lSysHuDwmYXUIvtwZl0zI+D6mZgXZX0u8YBlLS4tmai9ONNY9tjRgRA== +"@babel/preset-env@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" + integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== dependencies: "@babel/compat-data" "^7.12.7" "@babel/helper-compilation-targets" "^7.12.5" "@babel/helper-module-imports" "^7.12.5" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-validator-option" "^7.12.1" + "@babel/helper-validator-option" "^7.12.11" "@babel/plugin-proposal-async-generator-functions" "^7.12.1" "@babel/plugin-proposal-class-properties" "^7.12.1" "@babel/plugin-proposal-dynamic-import" "^7.12.1" @@ -800,7 +794,7 @@ "@babel/plugin-transform-arrow-functions" "^7.12.1" "@babel/plugin-transform-async-to-generator" "^7.12.1" "@babel/plugin-transform-block-scoped-functions" "^7.12.1" - "@babel/plugin-transform-block-scoping" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.11" "@babel/plugin-transform-classes" "^7.12.1" "@babel/plugin-transform-computed-properties" "^7.12.1" "@babel/plugin-transform-destructuring" "^7.12.1" @@ -830,7 +824,7 @@ "@babel/plugin-transform-unicode-escapes" "^7.12.1" "@babel/plugin-transform-unicode-regex" "^7.12.1" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.10" + "@babel/types" "^7.12.11" core-js-compat "^3.8.0" semver "^5.5.0" @@ -918,17 +912,26 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@bugsnag/browser@^7.5.3": - version "7.5.3" - resolved "https://registry.yarnpkg.com/@bugsnag/browser/-/browser-7.5.3.tgz#a91e9fe74422f5866d4058a05cf6d6881e15c26d" - integrity sha512-iGmKFtHz91hNovWW8rb/qLD9X5TMVEc7OUEfwE5s1M8ElReEmUAVbgTfQjkahG8aHvjGQ+M+zyM0gHfk+tTczg== +"@babel/types@^7.12.11", "@babel/types@^7.12.12": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== dependencies: - "@bugsnag/core" "^7.5.3" + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" -"@bugsnag/core@^7.5.3": - version "7.5.3" - resolved "https://registry.yarnpkg.com/@bugsnag/core/-/core-7.5.3.tgz#2851284a9f7d9e0628b5f73da3e91ae1d83fc8fb" - integrity sha512-HaAPWN+z3ZlEjwF2JeuAx83eKoVd6osgx2Hyn8dlmGsRfUvpi+7rG9DI483PGexEM0O6i/ORvD6Qx92/E9zW7w== +"@bugsnag/browser@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@bugsnag/browser/-/browser-7.6.0.tgz#3a34a1e8e151d09b3bf8cdd9d1358abc102db792" + integrity sha512-8sth20TM8BVfebkqxqJQOCM2P2L4foOgFH2QA3ruG0iknDKZDhE7XcoWgmUP9zVSNJqkCyiIzcBOuiwZW8JaSQ== + dependencies: + "@bugsnag/core" "^7.6.0" + +"@bugsnag/core@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@bugsnag/core/-/core-7.6.0.tgz#f18deb534ea5f95c1e02bdb3656e1e6605b16334" + integrity sha512-hBYAZJw4ScqoyM1jA1x/m2e4iS2EqYEs0I2hdzBCZFv2ls17ILmU58eRSyVdUfyzbv0J7Hi6DwwBGC4Yb6ROZA== dependencies: "@bugsnag/cuid" "^3.0.0" "@bugsnag/safe-json-stringify" "^6.0.0" @@ -941,20 +944,20 @@ resolved "https://registry.yarnpkg.com/@bugsnag/cuid/-/cuid-3.0.0.tgz#2ee7642a30aee6dc86f5e7f824653741e42e5c35" integrity sha512-LOt8aaBI+KvOQGneBtpuCz3YqzyEAehd1f3nC5yr9TIYW1+IzYKa2xWS4EiMz5pPOnRPHkyyS5t/wmSmN51Gjg== -"@bugsnag/js@^7.5.1": - version "7.5.3" - resolved "https://registry.yarnpkg.com/@bugsnag/js/-/js-7.5.3.tgz#83362da1c4aac5cac0cc05898d11fccea291b652" - integrity sha512-xdwfq+bQPWZFwc02IIFk7rVsxoEsAMOLiZLJpjnRK/HtzwWPUciMTRIIlUzb/uZaAmd05UieVQ/TxuwQYdMgEA== +"@bugsnag/js@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@bugsnag/js/-/js-7.6.0.tgz#fec736b592220713bbeffac7805024088b3220d9" + integrity sha512-EcI3sTpyOs94/OOjwI7fOg1iZ800o3kkOAipAnULRoP62j1vmErH2l/2xubny7g0JTOL59iZEkt+5O5MhbQJ2A== dependencies: - "@bugsnag/browser" "^7.5.3" - "@bugsnag/node" "^7.5.3" + "@bugsnag/browser" "^7.6.0" + "@bugsnag/node" "^7.6.0" -"@bugsnag/node@^7.5.3": - version "7.5.3" - resolved "https://registry.yarnpkg.com/@bugsnag/node/-/node-7.5.3.tgz#1da15d414d49712196d15f6c347e6b8714c69f77" - integrity sha512-irNGOTcxi7u8lUziLfv7rKzWGg2Yd+ZXZnwD0r6ZDhdlOwA3UnGq6Fud3SOTJNKPcUk/16Sv0mcuKkcLdHTodg== +"@bugsnag/node@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@bugsnag/node/-/node-7.6.0.tgz#45fbfafb26bde0dec79f81b442765863eef5e910" + integrity sha512-n3BVb04bq4z16nOM4gbWoXsi6k8R9bryWS/NAYi/jQg6tgyBkNYzmK0ojf3fYJ7uAgCjUJNMX6S9UHSJy/MMcQ== dependencies: - "@bugsnag/core" "^7.5.3" + "@bugsnag/core" "^7.6.0" byline "^5.0.0" error-stack-parser "^2.0.2" iserror "^0.0.2" @@ -1074,10 +1077,10 @@ resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.2.9.tgz#5212a959e4ec563584e42480bfd39ef129c3cbdf" integrity sha512-xJ5IUGOZztjSgNP/6XL+Ut5+q9UgSTv6xMtKkcQC5aJxCOkJy9u6RamPLdF00WQgwibxx2tu0e43bKUjTgzMig== -"@standardnotes/sncrypto-web@^1.2.9": - version "1.2.9" - resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-web/-/sncrypto-web-1.2.9.tgz#17c1a75727a65a4a8dc0cc28ddc1d21e25adabfc" - integrity sha512-OJVsoLiKoFHkEnrRImZQ6fH5H0ptk67IrVrb97Y4WEDLVABqEkX/HgdjaQwnreXWc489fqtg3BVvfgIPS7GXnQ== +"@standardnotes/sncrypto-web@^1.2.10": + version "1.2.10" + resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-web/-/sncrypto-web-1.2.10.tgz#ddda0c8ec92754c1334d9a83be7b320433c55b79" + integrity sha512-mmHlXFFovBqOdctpMkyXTpK0zI/k4NuXoV5LRGLKIXUktT9/cZg1pgNNfGPFUP+g4C5M2qxeFmZKFh581ipolQ== dependencies: "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" @@ -1111,11 +1114,6 @@ dependencies: "@types/babel-types" "*" -"@types/chai@^4.2.11": - version "4.2.14" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.14.tgz#44d2dd0b5de6185089375d976b4ec5caf6861193" - integrity sha512-G+ITQPXkwTrslfG5L/BksmbLUA0M1iybEsmCWPqzSxsRRhJZimBKJkoMi8fr/CPygPTj4zO5pJH7I2/cm9M7SQ== - "@types/glob@^7.1.1": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" @@ -1134,10 +1132,10 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== -"@types/lodash@^4.14.149": - version "4.14.165" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.165.tgz#74d55d947452e2de0742bad65270433b63a8c30f" - integrity sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg== +"@types/lodash@^4.14.168": + version "4.14.168" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008" + integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q== "@types/minimatch@*": version "3.0.3" @@ -2269,7 +2267,7 @@ chalk@^1.1.1: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2278,7 +2276,7 @@ chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -2782,7 +2780,7 @@ debug@3.2.6: dependencies: ms "^2.1.1" -debug@^3.1.1, debug@^3.2.5: +debug@^3.1.1, debug@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -3250,11 +3248,6 @@ eslint-plugin-react@^7.22.0: resolve "^1.18.1" string.prototype.matchall "^4.0.2" -eslint-plugin-standard@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz#0c3bf3a67e853f8bbbc580fb4945fbf16f41b7c5" - integrity sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ== - eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" @@ -3556,14 +3549,7 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -faye-websocket@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" - integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= - dependencies: - websocket-driver ">=0.5.1" - -faye-websocket@~0.11.1: +faye-websocket@^0.11.3: version "0.11.3" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== @@ -4816,7 +4802,7 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json3@^3.3.2: +json3@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== @@ -4931,7 +4917,7 @@ loader-runner@^2.4.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: +loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -4940,6 +4926,15 @@ loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4 emojis-list "^3.0.0" json5 "^1.0.1" +loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -6816,7 +6811,7 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= -selfsigned@^1.10.7: +selfsigned@^1.10.8: version "1.10.8" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30" integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w== @@ -6838,7 +6833,7 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1, semver@^7.3.2: +semver@^7.2.1, semver@^7.3.2, semver@^7.3.4: version "7.3.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== @@ -7036,26 +7031,26 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sockjs-client@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" - integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== +sockjs-client@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add" + integrity sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q== dependencies: - debug "^3.2.5" + debug "^3.2.6" eventsource "^1.0.7" - faye-websocket "~0.11.1" - inherits "^2.0.3" - json3 "^3.3.2" - url-parse "^1.4.3" + faye-websocket "^0.11.3" + inherits "^2.0.4" + json3 "^3.3.3" + url-parse "^1.4.7" -sockjs@0.3.20: - version "0.3.20" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.20.tgz#b26a283ec562ef8b2687b44033a4eeceac75d855" - integrity sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA== +sockjs@^0.3.21: + version "0.3.21" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" + integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== dependencies: - faye-websocket "^0.10.0" + faye-websocket "^0.11.3" uuid "^3.4.0" - websocket-driver "0.6.5" + websocket-driver "^0.7.4" sort-keys@^1.0.0: version "1.1.2" @@ -7585,16 +7580,16 @@ trim-newlines@^1.0.0: dependencies: glob "^7.1.2" -ts-loader@^8.0.12: - version "8.0.12" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.12.tgz#1de9f1de65176318c1e6d187bfc496182f8dc2a0" - integrity sha512-UIivVfGVJDdwwjgSrbtcL9Nf10c1BWnL1mxAQUVcnhNIn/P9W3nP5v60Z0aBMtc7ZrE11lMmU6+5jSgAXmGaYw== +ts-loader@^8.0.14: + version "8.0.14" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.14.tgz#e46ac1f8dcb88808d0b1335d2eae65b74bd78fe8" + integrity sha512-Jt/hHlUnApOZjnSjTmZ+AbD5BGlQFx3f1D0nYuNKwz0JJnuDGHJas6az+FlWKwwRTu+26GXpv249A8UAnYUpqA== dependencies: - chalk "^2.3.0" + chalk "^4.1.0" enhanced-resolve "^4.0.0" - loader-utils "^1.0.2" + loader-utils "^2.0.0" micromatch "^4.0.0" - semver "^6.0.0" + semver "^7.3.4" tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" @@ -7780,7 +7775,7 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url-parse@^1.4.3: +url-parse@^1.4.3, url-parse@^1.4.7: version "1.4.7" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== @@ -7953,10 +7948,10 @@ webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c" - integrity sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg== +webpack-dev-server@^3.11.2: + version "3.11.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708" + integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -7978,11 +7973,11 @@ webpack-dev-server@^3.11.0: p-retry "^3.0.1" portfinder "^1.0.26" schema-utils "^1.0.0" - selfsigned "^1.10.7" + selfsigned "^1.10.8" semver "^6.3.0" serve-index "^1.9.1" - sockjs "0.3.20" - sockjs-client "1.4.0" + sockjs "^0.3.21" + sockjs-client "^1.5.0" spdy "^4.0.2" strip-ansi "^3.0.1" supports-color "^6.1.0" @@ -8044,14 +8039,7 @@ webpack@^4.44.1: watchpack "^1.7.4" webpack-sources "^1.4.1" -websocket-driver@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" - integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY= - dependencies: - websocket-extensions ">=0.1.1" - -websocket-driver@>=0.5.1: +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== From 2c4742a91dad3bfa8a1a7799991fd6da7bd6d0e1 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Thu, 21 Jan 2021 11:56:20 +0100 Subject: [PATCH 18/55] feat: make SNWebCrypto a constant --- app/assets/javascripts/crypto.ts | 3 +++ app/assets/javascripts/ui_models/application.ts | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 app/assets/javascripts/crypto.ts diff --git a/app/assets/javascripts/crypto.ts b/app/assets/javascripts/crypto.ts new file mode 100644 index 000000000..28c1edb8d --- /dev/null +++ b/app/assets/javascripts/crypto.ts @@ -0,0 +1,3 @@ +import { SNWebCrypto } from "@standardnotes/sncrypto-web"; + +export const Crypto = new SNWebCrypto(); diff --git a/app/assets/javascripts/ui_models/application.ts b/app/assets/javascripts/ui_models/application.ts index aa8315fc6..7684cd9e6 100644 --- a/app/assets/javascripts/ui_models/application.ts +++ b/app/assets/javascripts/ui_models/application.ts @@ -25,8 +25,8 @@ import { KeyboardManager } from '@/services'; import { AppState } from '@/ui_models/app_state'; -import { SNWebCrypto } from '@standardnotes/sncrypto-web'; import { Bridge } from '@/services/bridge'; +import { Crypto } from '@/crypto'; type WebServices = { appState: AppState; @@ -60,7 +60,7 @@ export class WebApplication extends SNApplication { bridge.environment, platformFromString(getPlatformString()), deviceInterface, - new SNWebCrypto(), + Crypto, new AlertService(), identifier, undefined, From 0bd3143481bcecc3d09673c7c1b0c86e4d289bf2 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 22 Jan 2021 15:31:56 +0100 Subject: [PATCH 19/55] feat: add random identifier to bugsnag reports --- app/assets/javascripts/crypto.ts | 2 +- .../directives/views/accountMenu.ts | 11 ++++++-- .../javascripts/services/errorReporting.ts | 27 ++++++++++++++++++- .../javascripts/services/localStorage.ts | 6 +++-- .../javascripts/ui_models/application.ts | 4 +-- .../templates/directives/account-menu.pug | 7 +++++ 6 files changed, 49 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/crypto.ts b/app/assets/javascripts/crypto.ts index 28c1edb8d..d93163eac 100644 --- a/app/assets/javascripts/crypto.ts +++ b/app/assets/javascripts/crypto.ts @@ -1,3 +1,3 @@ import { SNWebCrypto } from "@standardnotes/sncrypto-web"; -export const Crypto = new SNWebCrypto(); +export const WebCrypto = new SNWebCrypto(); diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index 7c044bc51..10a9fd367 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -24,6 +24,11 @@ import { BackupFile, ContentType } from '@standardnotes/snjs'; import { confirmDialog, alertDialog } from '@/services/alertService'; import { autorun, IReactionDisposer } from 'mobx'; import { storage, StorageKey } from '@/services/localStorage'; +import { + disableErrorReporting, + enableErrorReporting, + errorReportingId +} from '@/services/errorReporting'; const ELEMENT_ID_IMPORT_PASSWORD_INPUT = 'import-password-request'; @@ -66,6 +71,7 @@ type AccountMenuState = { syncInProgress: boolean; syncError: string; showSessions: boolean; + errorReportingId: string | null; } class AccountMenuCtrl extends PureViewCtrl { @@ -99,6 +105,7 @@ class AccountMenuCtrl extends PureViewCtrl { showBetaWarning: false, errorReportingEnabled: storage.get(StorageKey.DisableErrorReporting) === false, showSessions: false, + errorReportingId: errorReportingId(), } as AccountMenuState; } @@ -550,9 +557,9 @@ class AccountMenuCtrl extends PureViewCtrl { toggleErrorReportingEnabled() { if (this.state.errorReportingEnabled) { - storage.set(StorageKey.DisableErrorReporting, true); + disableErrorReporting(); } else { - storage.set(StorageKey.DisableErrorReporting, false); + enableErrorReporting(); } if (!this.state.syncInProgress) { window.location.reload(); diff --git a/app/assets/javascripts/services/errorReporting.ts b/app/assets/javascripts/services/errorReporting.ts index 0a309e3ab..c3cd66a66 100644 --- a/app/assets/javascripts/services/errorReporting.ts +++ b/app/assets/javascripts/services/errorReporting.ts @@ -2,6 +2,7 @@ import { isNullOrUndefined, SNLog } from '@standardnotes/snjs'; import { isDesktopApplication, isDev } from '@/utils'; import { storage, StorageKey } from './localStorage'; import Bugsnag from '@bugsnag/js'; +import { WebCrypto } from '../crypto'; declare const __VERSION__: string; declare global { @@ -21,7 +22,7 @@ function redactFilePath(line: string): string { } } -export function startErrorReporting() { +export function startErrorReporting(): void { const disableErrorReporting = storage.get(StorageKey.DisableErrorReporting); if ( /** @@ -37,6 +38,15 @@ export function startErrorReporting() { return; } try { + const storedUserId = storage.get(StorageKey.AnonymousUserId); + let anonymousUserId: string; + if (storedUserId === null) { + anonymousUserId = WebCrypto.generateUUIDSync(); + storage.set(StorageKey.AnonymousUserId, anonymousUserId); + } else { + anonymousUserId = storedUserId; + } + Bugsnag.start({ apiKey: window._bugsnag_api_key, appType: isDesktopApplication() ? 'desktop' : 'web', @@ -46,6 +56,8 @@ export function startErrorReporting() { releaseStage: isDev ? 'development' : undefined, enabledBreadcrumbTypes: ['error', 'log'], onError(event) { + event.setUser(anonymousUserId); + /** * Redact any data that could be used to identify user, * such as file paths. @@ -95,3 +107,16 @@ export function startErrorReporting() { SNLog.onError = console.error; } } + +export function disableErrorReporting() { + storage.remove(StorageKey.AnonymousUserId); + storage.set(StorageKey.DisableErrorReporting, true); +} + +export function enableErrorReporting() { + storage.set(StorageKey.DisableErrorReporting, false); +} + +export function errorReportingId() { + return storage.get(StorageKey.AnonymousUserId); +} diff --git a/app/assets/javascripts/services/localStorage.ts b/app/assets/javascripts/services/localStorage.ts index ac20a5243..07e11fe5a 100644 --- a/app/assets/javascripts/services/localStorage.ts +++ b/app/assets/javascripts/services/localStorage.ts @@ -1,9 +1,11 @@ export enum StorageKey { DisableErrorReporting = 'DisableErrorReporting', + AnonymousUserId = 'AnonymousUserId', } export type StorageValue = { [StorageKey.DisableErrorReporting]: boolean; + [StorageKey.AnonymousUserId]: string; } export const storage = { @@ -11,10 +13,10 @@ export const storage = { const value = localStorage.getItem(key); return value ? JSON.parse(value) : null; }, - set(key: K, value: StorageValue[K]) { + set(key: K, value: StorageValue[K]): void { localStorage.setItem(key, JSON.stringify(value)); }, - remove(key: StorageKey) { + remove(key: StorageKey): void { localStorage.removeItem(key); }, }; diff --git a/app/assets/javascripts/ui_models/application.ts b/app/assets/javascripts/ui_models/application.ts index 7684cd9e6..b18f6dc3c 100644 --- a/app/assets/javascripts/ui_models/application.ts +++ b/app/assets/javascripts/ui_models/application.ts @@ -26,7 +26,7 @@ import { } from '@/services'; import { AppState } from '@/ui_models/app_state'; import { Bridge } from '@/services/bridge'; -import { Crypto } from '@/crypto'; +import { WebCrypto } from '@/crypto'; type WebServices = { appState: AppState; @@ -60,7 +60,7 @@ export class WebApplication extends SNApplication { bridge.environment, platformFromString(getPlatformString()), deviceInterface, - Crypto, + WebCrypto, new AlertService(), identifier, undefined, diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index 39953a61c..4dcddbdf2 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -293,6 +293,13 @@ p.sk-p | Help us improve Standard Notes by automatically submitting | anonymized error reports. + p.sk-p.selectable(ng-if="self.state.errorReportingId") + | Your random identifier is + strong {{ self.state.errorReportingId }} + p.sk-p(ng-if="self.state.errorReportingId") + | Disabling error reporting will remove that identifier from your + | local storage, and a new identifier will be created should you + | decide to enable error reporting again in the future. .sk-panel-row button(ng-click="self.toggleErrorReportingEnabled()").sk-button.info span.sk-label {{ self.state.errorReportingEnabled ? 'Disable' : 'Enable'}} Error Reporting From 1576da01c4399be83db9521fd0882a8ee29a0ded Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Wed, 27 Jan 2021 15:32:26 +0100 Subject: [PATCH 20/55] fix: check onKeyUp instead of onKeyDown --- .../views/challenge_modal/challenge_modal.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx b/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx index cc4495e74..a1f486b7c 100644 --- a/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx +++ b/app/assets/javascripts/views/challenge_modal/challenge_modal.tsx @@ -40,6 +40,7 @@ class ChallengeModalCtrl extends PureViewCtrl { application!: WebApplication; challenge!: Challenge; onDismiss!: () => void; + submitting = false; /** @template */ protectionsSessionDurations = ProtectionSessionDurations; @@ -177,6 +178,10 @@ class ChallengeModalCtrl extends PureViewCtrl { if (!this.validate()) { return; } + if (this.submitting) { + return; + } + this.submitting = true; await this.setState({ processing: true }); const values: ChallengeValue[] = []; for (const inputValue of Object.values(this.getState().values)) { @@ -200,6 +205,7 @@ class ChallengeModalCtrl extends PureViewCtrl { } else { this.setState({ processing: false }); } + this.submitting = false; }, 50); } @@ -378,10 +384,9 @@ function ChallengePrompts({ ctrl.state.values[prompt.id]!.value = value; ctrl.onTextValueChange(prompt); }} - onKeyDown={(event) => { + onKeyUp={(event) => { if (event.key === 'Enter') { event.preventDefault(); - event.stopPropagation(); ctrl.submit(); } }} From d4f02a124df66432aeb569cf7e48c125cf085ea6 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Thu, 28 Jan 2021 15:28:55 +0100 Subject: [PATCH 21/55] feat: implement SNJS backup file password retrieval --- .../directives/views/accountMenu.ts | 70 ++++++------------ app/assets/javascripts/ui_models/app_state.ts | 11 ++- .../views/application/application-view.pug | 2 +- .../views/application/application_view.ts | 74 ++++++++++--------- .../templates/directives/account-menu.pug | 18 ----- package.json | 4 +- yarn.lock | 8 +- 7 files changed, 74 insertions(+), 113 deletions(-) diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index 10a9fd367..2f53b42ac 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -342,13 +342,6 @@ class AccountMenuCtrl extends PureViewCtrl { } } - async submitImportPassword() { - await this.performImport( - this.getState().importData.data, - this.getState().importData.password - ); - } - showRegister() { this.setFormDataState({ showRegister: true @@ -384,73 +377,52 @@ class AccountMenuCtrl extends PureViewCtrl { 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) + 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); - } + await this.performImport(data); } else { - await this.performImport(data, undefined); + await this.setState({ importData: null }); + void alertDialog({ text: STRING_UNSUPPORTED_BACKUP_FILE_VERSION }); } } else { - await this.performImport(data, undefined); + await this.performImport(data); } } - async performImport(data: BackupFile, password?: string) { - if (!(await this.application.authorizeFileImport())) { - return; - } + async performImport(data: BackupFile) { await this.setState({ importData: { ...this.getState().importData, loading: true } }); - const result = await this.application!.importData( - data, - password - ); + const result = await this.application.importData(data); this.setState({ importData: null }); - if ('error' in result) { - this.application!.alertService!.alert( - result.error - ); + if (!result) { + return; + } else if ('error' in result) { + void alertDialog({ + text: result.error + }); } else if (result.errorCount) { - const message = StringImportError(result.errorCount); - this.application!.alertService!.alert( - message - ); + void alertDialog({ + text: StringImportError(result.errorCount) + }); } else { - this.application!.alertService!.alert( - STRING_IMPORT_SUCCESS - ); + void alertDialog({ + 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( + return this.application.getItems( [ ContentType.Note, ContentType.Tag diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index e41ffcb7c..dca220cc9 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -10,7 +10,6 @@ import { UuidString, SyncOpStatus, PrefKey, - Challenge, } from '@standardnotes/snjs'; import { WebApplication } from '@/ui_models/application'; import { Editor } from '@/ui_models/editor'; @@ -28,6 +27,11 @@ export enum AppStateEvent { WindowDidBlur, } +export type PanelResizedData = { + panel: string; + collapsed: boolean; +} + export enum EventSource { UserInteraction, Script, @@ -392,10 +396,11 @@ export class AppState { } panelDidResize(name: string, collapsed: boolean) { - this.notifyEvent(AppStateEvent.PanelResized, { + const data: PanelResizedData = { panel: name, collapsed: collapsed, - }); + }; + this.notifyEvent(AppStateEvent.PanelResized, data); } editorDidFocus(eventSource: EventSource) { diff --git a/app/assets/javascripts/views/application/application-view.pug b/app/assets/javascripts/views/application/application-view.pug index 59eea6acc..91f15b7fd 100644 --- a/app/assets/javascripts/views/application/application-view.pug +++ b/app/assets/javascripts/views/application/application-view.pug @@ -28,7 +28,7 @@ application='self.application' ) challenge-modal( - ng-repeat="challenge in self.state.challenges track by challenge.id" + ng-repeat="challenge in self.challenges track by challenge.id" class="sk-modal" application="self.application" challenge="challenge" diff --git a/app/assets/javascripts/views/application/application_view.ts b/app/assets/javascripts/views/application/application_view.ts index 9e3223253..3dbf4ab91 100644 --- a/app/assets/javascripts/views/application/application_view.ts +++ b/app/assets/javascripts/views/application/application_view.ts @@ -2,8 +2,8 @@ import { RootScopeMessages } from './../../messages'; import { WebDirective } from '@/types'; import { getPlatformString } from '@/utils'; import template from './application-view.pug'; -import { AppStateEvent } from '@/ui_models/app_state'; -import { ApplicationEvent, Challenge } from '@standardnotes/snjs'; +import { AppStateEvent, PanelResizedData } from '@/ui_models/app_state'; +import { ApplicationEvent, Challenge, removeFromArray } from '@standardnotes/snjs'; import { PANEL_NAME_NOTES, PANEL_NAME_TAGS @@ -18,18 +18,20 @@ class ApplicationViewCtrl extends PureViewCtrl { - private $location?: ng.ILocationService - private $rootScope?: ng.IRootScopeService public platformString: string private notesCollapsed = false private tagsCollapsed = false + /** + * To prevent stale state reads (setState is async), + * challenges is a mutable array + */ + private challenges: Challenge[] = []; /* @ngInject */ constructor( - $location: ng.ILocationService, - $rootScope: ng.IRootScopeService, + private $location: ng.ILocationService, + private $rootScope: ng.IRootScopeService, $timeout: ng.ITimeoutService ) { super($timeout); @@ -43,8 +45,8 @@ class ApplicationViewCtrl extends PureViewCtrl { - - this.setState({ - challenges: this.state.challenges.concat(challenge) + this.$timeout(() => { + this.challenges.push(challenge); }); } }); - await this.application!.launch(); + await this.application.launch(); } - public removeChallenge(challenge: Challenge) { - this.setState({ - challenges: this.state.challenges.filter(c => c.id !== challenge.id) + public async removeChallenge(challenge: Challenge) { + this.$timeout(() => { + removeFromArray(this.challenges, challenge); }); } @@ -90,7 +91,7 @@ class ApplicationViewCtrl extends PureViewCtrl 0) { + if (event.dataTransfer?.files.length) { event.preventDefault(); } } onDragDrop(event: DragEvent) { - if (event.dataTransfer!.files.length > 0) { + if (event.dataTransfer?.files.length) { event.preventDefault(); - this.application!.alertService!.alert( - STRING_DEFAULT_FILE_ERROR - ); + void alertDialog({ + text: STRING_DEFAULT_FILE_ERROR + }); } } async handleDemoSignInFromParams() { if ( - this.$location!.search().demo === 'true' && + this.$location.search().demo === 'true' && !this.application.hasAccount() ) { - await this.application!.setHost( + await this.application.setHost( 'https://syncing-server-demo.standardnotes.org' ); - this.application!.signIn( + this.application.signIn( 'demo@standardnotes.org', 'password', ); diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index 4dcddbdf2..b8aa78e1d 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -266,24 +266,6 @@ span(ng-if='self.isDesktopApplication()') | Backups are automatically created on desktop and can be managed | via the "Backups" top-level menu. - #import-password-request(ng-if='self.state.importData.requestPassword') - form.sk-panel-form.stretch(ng-submit='self.submitImportPassword()') - p Enter the account password associated with the import file. - input.sk-input.contrast.mt-5( - autofocus='true', - ng-model='self.state.importData.password', - placeholder='Enter File Account Password', - type='password' - ) - .sk-button-group.stretch.sk-panel-row.form-submit - button.sk-button.info(type='submit') - .sk-label Decrypt & Import - p - | Importing from backup will not overwrite existing data, - | but instead create a duplicate of any differing data. - p - | If you'd like to import only a selection of items instead of - | the whole file, please use the Batch Manager extension. .sk-panel-row .sk-spinner.small.info(ng-if='self.state.importData.loading') .sk-panel-section diff --git a/package.json b/package.json index 33aa5bcbb..fe53262fc 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "angular": "^1.8.2", "apply-loader": "^2.0.0", "babel-eslint": "^10.1.0", + "babel-loader": "^8.2.2", "babel-plugin-angularjs-annotate": "^0.10.0", "chai": "^4.2.0", "connect": "^3.7.0", @@ -69,8 +70,7 @@ "@reach/alert-dialog": "^0.12.1", "@reach/dialog": "^0.12.1", "@standardnotes/sncrypto-web": "^1.2.10", - "@standardnotes/snjs": "^2.0.47", - "babel-loader": "^8.2.2", + "@standardnotes/snjs": "^2.0.48", "mobx": "^6.0.4", "preact": "^10.5.11" } diff --git a/yarn.lock b/yarn.lock index 93efa3aea..4fe185ef8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1085,10 +1085,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.47": - version "2.0.47" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.47.tgz#b6235faed52369168d383d6bf1ba45302f9b9cea" - integrity sha512-2d4CKdcKXg0dKYMdPPqQrLQE1NS62IWusfD2OZ0zRNbzhOHUhap/eRIURCDa0UQphKTaDaGa70x2rJl3PW4J6Q== +"@standardnotes/snjs@^2.0.48": + version "2.0.48" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.48.tgz#0e61b21e9a3d70d02867b86d2ced5dd1e8c861a1" + integrity sha512-OnlG6D0QNTu+jePJqUpyqeC81VMxKwyu3yNfGQyC6/p5j/nFcBC6W0aU6xBTeVsE2zEOX+Dltj6olY6dN4vgdQ== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" From 94473da61b540d251879b885c3bcd50c79300dfc Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Thu, 28 Jan 2021 15:31:28 +0100 Subject: [PATCH 22/55] chore(deps): upgrade snjs --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fe53262fc..0bfcffb1d 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "@reach/alert-dialog": "^0.12.1", "@reach/dialog": "^0.12.1", "@standardnotes/sncrypto-web": "^1.2.10", - "@standardnotes/snjs": "^2.0.48", + "@standardnotes/snjs": "^2.0.49", "mobx": "^6.0.4", "preact": "^10.5.11" } diff --git a/yarn.lock b/yarn.lock index 4fe185ef8..827ed6026 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1085,10 +1085,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.48": - version "2.0.48" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.48.tgz#0e61b21e9a3d70d02867b86d2ced5dd1e8c861a1" - integrity sha512-OnlG6D0QNTu+jePJqUpyqeC81VMxKwyu3yNfGQyC6/p5j/nFcBC6W0aU6xBTeVsE2zEOX+Dltj6olY6dN4vgdQ== +"@standardnotes/snjs@^2.0.49": + version "2.0.49" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.49.tgz#1bc045196f284071369844d0cfccce82f61fc386" + integrity sha512-1Bp2WInpMsz2xia7SZp50OKKd8AqjH8eUer9SumHyhwk22TQiEQMLUoEZLcmPtN/mnqwc99FBW34amBUbD3lvQ== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" From c084268f51b46bc5008a33010b6c7c58f5725f88 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 2 Feb 2021 15:40:20 +0100 Subject: [PATCH 23/55] feat: display warning banner when using the app with no account --- app/assets/fonts/ionicons.svg | 38 -- app/assets/icons/ic_close.svg | 3 + app/assets/javascripts/@types/modules.ts | 3 + app/assets/javascripts/app.ts | 6 +- .../components/NoAccountWarning.tsx | 46 +++ .../SessionsModal.tsx} | 42 +-- app/assets/javascripts/components/utils.ts | 56 +++ .../javascripts/services/desktopManager.ts | 2 +- .../javascripts/services/localStorage.ts | 4 + app/assets/javascripts/tsconfig.json | 3 +- app/assets/javascripts/ui_models/app_state.ts | 99 +++-- app/assets/javascripts/utils.ts | 6 + .../views/application/application-view.pug | 1 + .../javascripts/views/footer/footer_view.ts | 17 +- .../javascripts/views/notes/notes-view.pug | 6 +- .../javascripts/views/tags/tags-view.pug | 12 +- app/assets/stylesheets/_ionicons.scss | 3 +- app/assets/stylesheets/_notes.scss | 10 +- app/assets/stylesheets/_sn.scss | 14 + app/assets/stylesheets/_ui.scss | 176 ++++++--- app/assets/stylesheets/index.css.scss | 1 + .../templates/directives/account-menu.pug | 2 +- .../directives/permissions-modal.pug | 8 +- package.json | 1 + webpack.config.js | 6 +- yarn.lock | 341 +++++++++++++++++- 26 files changed, 709 insertions(+), 197 deletions(-) delete mode 100644 app/assets/fonts/ionicons.svg create mode 100644 app/assets/icons/ic_close.svg create mode 100644 app/assets/javascripts/@types/modules.ts create mode 100644 app/assets/javascripts/components/NoAccountWarning.tsx rename app/assets/javascripts/{directives/views/sessionsModal.tsx => components/SessionsModal.tsx} (89%) create mode 100644 app/assets/javascripts/components/utils.ts create mode 100644 app/assets/stylesheets/_sn.scss diff --git a/app/assets/fonts/ionicons.svg b/app/assets/fonts/ionicons.svg deleted file mode 100644 index 67f37aadf..000000000 --- a/app/assets/fonts/ionicons.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - -Created by FontForge 20190318 at Thu Apr 11 10:47:26 2019 - By Mo Bitar -Copyright (c) 2019, Mo Bitar - - - - - - - - - - - diff --git a/app/assets/icons/ic_close.svg b/app/assets/icons/ic_close.svg new file mode 100644 index 000000000..0b2f305d8 --- /dev/null +++ b/app/assets/icons/ic_close.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/javascripts/@types/modules.ts b/app/assets/javascripts/@types/modules.ts new file mode 100644 index 000000000..b5518926f --- /dev/null +++ b/app/assets/javascripts/@types/modules.ts @@ -0,0 +1,3 @@ +declare module '*.svg' { + export default function SvgComponent(props: React.SVGProps): JSX.Element; +} diff --git a/app/assets/javascripts/app.ts b/app/assets/javascripts/app.ts index 1d414d8df..8f1aab4d7 100644 --- a/app/assets/javascripts/app.ts +++ b/app/assets/javascripts/app.ts @@ -55,7 +55,8 @@ import { BrowserBridge } from './services/browserBridge'; import { startErrorReporting } from './services/errorReporting'; import { StartApplication } from './startApplication'; import { Bridge } from './services/bridge'; -import { SessionsModalDirective } from './directives/views/sessionsModal'; +import { SessionsModalDirective } from './components/SessionsModal'; +import { NoAccountWarningDirective } from './components/NoAccountWarning'; function reloadHiddenFirefoxTab(): boolean { @@ -141,7 +142,8 @@ const startApplication: StartApplication = async function startApplication( .directive('revisionPreviewModal', () => new RevisionPreviewModal()) .directive('historyMenu', () => new HistoryMenu()) .directive('syncResolutionMenu', () => new SyncResolutionMenu()) - .directive('sessionsModal', SessionsModalDirective); + .directive('sessionsModal', SessionsModalDirective) + .directive('noAccountWarning', NoAccountWarningDirective); // Filters angular.module('app').filter('trusted', ['$sce', trusted]); diff --git a/app/assets/javascripts/components/NoAccountWarning.tsx b/app/assets/javascripts/components/NoAccountWarning.tsx new file mode 100644 index 000000000..299de54b0 --- /dev/null +++ b/app/assets/javascripts/components/NoAccountWarning.tsx @@ -0,0 +1,46 @@ +import { WebApplication } from '@/ui_models/application'; +import { toDirective, useAutorunValue } from './utils'; +import Close from '../../icons/ic_close.svg'; +import { AppState } from '@/ui_models/app_state'; + +function NoAccountWarning({ + application, + appState, +}: { + application: WebApplication; + appState: AppState; +}) { + const canShow = useAutorunValue(() => appState.noAccountWarning.show); + if (!canShow || application.hasAccount()) { + return null; + } + return ( +
+

Data not backed up

+

+ Sign in or register to back up your notes +

+ + +
+ ); +} + +export const NoAccountWarningDirective = toDirective(NoAccountWarning); diff --git a/app/assets/javascripts/directives/views/sessionsModal.tsx b/app/assets/javascripts/components/SessionsModal.tsx similarity index 89% rename from app/assets/javascripts/directives/views/sessionsModal.tsx rename to app/assets/javascripts/components/SessionsModal.tsx index 89ad38eff..52cbf4533 100644 --- a/app/assets/javascripts/directives/views/sessionsModal.tsx +++ b/app/assets/javascripts/components/SessionsModal.tsx @@ -1,14 +1,12 @@ import { AppState } from '@/ui_models/app_state'; -import { PureViewCtrl } from '@/views'; import { SNApplication, - RemoteSession, SessionStrings, UuidString, isNullOrUndefined, + RemoteSession, } from '@standardnotes/snjs'; -import { autorun, IAutorunOptions, IReactionPublic } from 'mobx'; -import { render, FunctionComponent } from 'preact'; +import { FunctionComponent } from 'preact'; import { useState, useEffect, useRef, useMemo } from 'preact/hooks'; import { Dialog } from '@reach/dialog'; import { Alert } from '@reach/alert'; @@ -17,13 +15,8 @@ import { AlertDialogDescription, AlertDialogLabel, } from '@reach/alert-dialog'; - -function useAutorun( - view: (r: IReactionPublic) => unknown, - opts?: IAutorunOptions -) { - useEffect(() => autorun(view, opts), [view, opts]); -} +import { toDirective, useAutorun } from './utils'; +import { WebApplication } from '@/ui_models/application'; type Session = RemoteSession & { revoking?: true; @@ -250,7 +243,7 @@ const SessionsModal: FunctionComponent<{ const Sessions: FunctionComponent<{ appState: AppState; - application: SNApplication; + application: WebApplication; }> = ({ appState, application }) => { const [showModal, setShowModal] = useState(false); useAutorun(() => setShowModal(appState.isSessionsModalVisible)); @@ -262,27 +255,4 @@ const Sessions: FunctionComponent<{ } }; -class SessionsModalCtrl extends PureViewCtrl { - /* @ngInject */ - constructor(private $element: JQLite, $timeout: ng.ITimeoutService) { - super($timeout); - this.$element = $element; - } - $onChanges() { - render( - , - this.$element[0] - ); - } -} - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export function SessionsModalDirective() { - return { - controller: SessionsModalCtrl, - bindToController: true, - scope: { - application: '=', - }, - }; -} +export const SessionsModalDirective = toDirective(Sessions); diff --git a/app/assets/javascripts/components/utils.ts b/app/assets/javascripts/components/utils.ts new file mode 100644 index 000000000..96fa8a4f8 --- /dev/null +++ b/app/assets/javascripts/components/utils.ts @@ -0,0 +1,56 @@ +import { WebApplication } from '@/ui_models/application'; +import { AppState } from '@/ui_models/app_state'; +import { autorun, IAutorunOptions, IReactionPublic } from 'mobx'; +import { FunctionComponent, h, render } from 'preact'; +import { useEffect } from 'preact/hooks'; +import { useState } from 'react'; + +export function useAutorunValue(query: () => T): T { + const [value, setValue] = useState(query); + useAutorun(() => { + setValue(query()); + }); + return value; +} + +export function useAutorun( + view: (r: IReactionPublic) => unknown, + opts?: IAutorunOptions +): void { + useEffect(() => autorun(view, opts), [view, opts]); +} + +export function toDirective( + component: FunctionComponent<{ + application: WebApplication; + appState: AppState; + }> +) { + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + return function () { + return { + controller: [ + '$element', + '$scope', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ($element: JQLite, $scope: any) => { + return { + $onChanges() { + render( + h(component, { + application: $scope.application, + appState: $scope.appState, + }), + $element[0] + ); + }, + }; + }, + ], + scope: { + application: '=', + appState: '=', + }, + }; + }; +} diff --git a/app/assets/javascripts/services/desktopManager.ts b/app/assets/javascripts/services/desktopManager.ts index 9da6afcf3..3587b174c 100644 --- a/app/assets/javascripts/services/desktopManager.ts +++ b/app/assets/javascripts/services/desktopManager.ts @@ -75,7 +75,7 @@ export class DesktopManager extends ApplicationService { getExtServerHost() { console.assert( - this.bridge.extensionsServerHost, + !!this.bridge.extensionsServerHost, 'extServerHost is null' ); return this.bridge.extensionsServerHost; diff --git a/app/assets/javascripts/services/localStorage.ts b/app/assets/javascripts/services/localStorage.ts index 07e11fe5a..fa03d7c9b 100644 --- a/app/assets/javascripts/services/localStorage.ts +++ b/app/assets/javascripts/services/localStorage.ts @@ -1,11 +1,15 @@ export enum StorageKey { DisableErrorReporting = 'DisableErrorReporting', AnonymousUserId = 'AnonymousUserId', + ShowBetaWarning = 'ShowBetaWarning', + ShowNoAccountWarning = 'ShowNoAccountWarning', } export type StorageValue = { [StorageKey.DisableErrorReporting]: boolean; [StorageKey.AnonymousUserId]: string; + [StorageKey.ShowBetaWarning]: boolean; + [StorageKey.ShowNoAccountWarning]: boolean; } export const storage = { diff --git a/app/assets/javascripts/tsconfig.json b/app/assets/javascripts/tsconfig.json index 1381b681e..afff29158 100644 --- a/app/assets/javascripts/tsconfig.json +++ b/app/assets/javascripts/tsconfig.json @@ -6,7 +6,7 @@ "allowJs": true, "noEmit": true, "strict": true, - "isolatedModules": true, + "isolatedModules": false, "esModuleInterop": true, "declaration": true, "newLine": "lf", @@ -14,6 +14,7 @@ "baseUrl": ".", "jsx": "react-jsx", "jsxImportSource": "preact", + "typeRoots": ["./@types"], "paths": { "%/*": ["../templates/*"], "@/*": ["./*"], diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index dca220cc9..8ab3b443b 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -15,6 +15,7 @@ import { WebApplication } from '@/ui_models/application'; import { Editor } from '@/ui_models/editor'; import { action, makeObservable, observable } from 'mobx'; import { Bridge } from '@/services/bridge'; +import { storage, StorageKey } from '@/services/localStorage'; export enum AppStateEvent { TagChanged, @@ -30,7 +31,7 @@ export enum AppStateEvent { export type PanelResizedData = { panel: string; collapsed: boolean; -} +}; export enum EventSource { UserInteraction, @@ -39,8 +40,6 @@ export enum EventSource { type ObserverCallback = (event: AppStateEvent, data?: any) => Promise; -const SHOW_BETA_WARNING_KEY = 'show_beta_warning'; - class ActionsMenuState { hiddenExtensions: Record = {}; @@ -75,7 +74,7 @@ export class SyncState { }); } - update(status: SyncOpStatus) { + update(status: SyncOpStatus): void { this.errorMessage = status.error?.message; this.inProgress = status.syncInProgress; const stats = status.getStats(); @@ -95,6 +94,41 @@ export class SyncState { } } +class AccountMenuState { + show = false; + constructor() { + makeObservable(this, { + show: observable, + setShow: action, + toggleShow: action, + }); + } + setShow(show: boolean) { + this.show = show; + } + toggleShow() { + this.show = !this.show; + } +} + +class NoAccountWarningState { + show: boolean; + constructor() { + this.show = storage.get(StorageKey.ShowNoAccountWarning) ?? true; + makeObservable(this, { + show: observable, + hide: action, + }); + } + hide() { + this.show = false; + storage.set(StorageKey.ShowNoAccountWarning, false); + } + reset() { + storage.remove(StorageKey.ShowNoAccountWarning); + } +} + export class AppState { readonly enableUnfinishedFeatures = isDev || location.host.includes('app-dev.standardnotes.org'); @@ -109,8 +143,10 @@ export class AppState { rootScopeCleanup2: any; onVisibilityChange: any; selectedTag?: SNTag; - showBetaWarning = false; + showBetaWarning: boolean; + readonly accountMenu = new AccountMenuState(); readonly actionsMenu = new ActionsMenuState(); + readonly noAccountWarning = new NoAccountWarningState(); readonly sync = new SyncState(); isSessionsModalVisible = false; @@ -124,15 +160,6 @@ export class AppState { this.$timeout = $timeout; this.$rootScope = $rootScope; this.application = application; - makeObservable(this, { - showBetaWarning: observable, - isSessionsModalVisible: observable, - - enableBetaWarning: action, - disableBetaWarning: action, - openSessionsModal: action, - closeSessionsModal: action, - }); this.addAppEventObserver(); this.streamNotesAndTags(); this.onVisibilityChange = () => { @@ -143,12 +170,28 @@ export class AppState { this.notifyEvent(event); }; this.registerVisibilityObservers(); - this.determineBetaWarningValue(); + + if (this.bridge.appVersion.includes('-beta')) { + this.showBetaWarning = storage.get(StorageKey.ShowBetaWarning) ?? true; + } else { + this.showBetaWarning = false; + } + + makeObservable(this, { + showBetaWarning: observable, + isSessionsModalVisible: observable, + + enableBetaWarning: action, + disableBetaWarning: action, + openSessionsModal: action, + closeSessionsModal: action, + }); } - deinit(source: DeinitSource) { + deinit(source: DeinitSource): void { if (source === DeinitSource.SignOut) { - localStorage.removeItem(SHOW_BETA_WARNING_KEY); + storage.remove(StorageKey.ShowBetaWarning); + this.noAccountWarning.reset(); } this.actionsMenu.deinit(); this.unsubApp(); @@ -174,30 +217,12 @@ export class AppState { disableBetaWarning() { this.showBetaWarning = false; - localStorage.setItem(SHOW_BETA_WARNING_KEY, 'false'); + storage.set(StorageKey.ShowBetaWarning, false); } enableBetaWarning() { this.showBetaWarning = true; - localStorage.setItem(SHOW_BETA_WARNING_KEY, 'true'); - } - - clearBetaWarning() { - localStorage.setItem(SHOW_BETA_WARNING_KEY, 'true'); - } - - private determineBetaWarningValue() { - if (this.bridge.appVersion.includes('-beta')) { - switch (localStorage.getItem(SHOW_BETA_WARNING_KEY)) { - case 'true': - default: - this.enableBetaWarning(); - break; - case 'false': - this.disableBetaWarning(); - break; - } - } + storage.set(StorageKey.ShowBetaWarning, true); } /** diff --git a/app/assets/javascripts/utils.ts b/app/assets/javascripts/utils.ts index 54e51b6bc..8c94fe42e 100644 --- a/app/assets/javascripts/utils.ts +++ b/app/assets/javascripts/utils.ts @@ -1,3 +1,9 @@ +declare const process : { + env: { + NODE_ENV: string | null | undefined + } +}; + export const isDev = process.env.NODE_ENV === 'development'; export function getPlatformString() { diff --git a/app/assets/javascripts/views/application/application-view.pug b/app/assets/javascripts/views/application/application-view.pug index 91f15b7fd..b428a9fab 100644 --- a/app/assets/javascripts/views/application/application-view.pug +++ b/app/assets/javascripts/views/application/application-view.pug @@ -26,6 +26,7 @@ path(d="M480 256l-75.53-33.53L256.1 290.6l-148.77-68.17L32 256l224 102 224-102z") sessions-modal( application='self.application' + app-state='self.appState' ) challenge-modal( ng-repeat="challenge in self.challenges track by challenge.id" diff --git a/app/assets/javascripts/views/footer/footer_view.ts b/app/assets/javascripts/views/footer/footer_view.ts index 4012a2176..5b36ebef0 100644 --- a/app/assets/javascripts/views/footer/footer_view.ts +++ b/app/assets/javascripts/views/footer/footer_view.ts @@ -62,7 +62,7 @@ class FooterViewCtrl extends PureViewCtrl void> = []; private completedInitialSync = false; private showingDownloadStatus = false; - private removeBetaWarningListener?: IReactionDisposer; + private autorunDisposer?: IReactionDisposer; /* @ngInject */ constructor( @@ -103,7 +103,7 @@ class FooterViewCtrl extends PureViewCtrl { + this.autorunDisposer = autorun(() => { const showBetaWarning = this.appState.showBetaWarning; + this.showAccountMenu = this.appState.accountMenu.show; this.setState({ showBetaWarning: showBetaWarning, showDataUpgrade: !showBetaWarning @@ -255,7 +256,7 @@ class FooterViewCtrl extends PureViewCtrl=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5: +mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -5525,7 +5771,7 @@ npm-run-path@^2.0.0: gauge "~2.7.3" set-blocking "~2.0.0" -nth-check@~1.0.1: +nth-check@^1.0.2, nth-check@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== @@ -5621,7 +5867,7 @@ object.fromentries@^2.0.2: es-abstract "^1.18.0-next.1" has "^1.0.3" -object.getownpropertydescriptors@^2.0.3: +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz#0dfda8d108074d9c563e80490c883b6661091544" integrity sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng== @@ -5637,7 +5883,7 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.1: +object.values@^1.1.0, object.values@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731" integrity sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag== @@ -5817,6 +6063,16 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -6292,6 +6548,11 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -6780,6 +7041,11 @@ sass-loader@^8.0.2: schema-utils "^2.6.1" semver "^6.3.0" +sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -7193,6 +7459,11 @@ ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + stack-generator@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36" @@ -7430,6 +7701,30 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +svg-parser@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" + integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== + +svgo@^1.2.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + table@^6.0.4: version "6.0.7" resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" @@ -7745,6 +8040,11 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -7822,6 +8122,16 @@ util.promisify@1.0.0: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" +util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" + util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" @@ -8155,6 +8465,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" + integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== + yargs-parser@13.1.2, yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" From 1b34331e9345471b0eca5782e4e7801a00c206b0 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 2 Feb 2021 16:12:02 +0100 Subject: [PATCH 24/55] fix: properly color svg button --- .../javascripts/components/NoAccountWarning.tsx | 4 ++-- app/assets/stylesheets/_sn.scss | 13 +++++++------ app/assets/stylesheets/_ui.scss | 14 +++++++++----- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/components/NoAccountWarning.tsx b/app/assets/javascripts/components/NoAccountWarning.tsx index 299de54b0..322cf5c9d 100644 --- a/app/assets/javascripts/components/NoAccountWarning.tsx +++ b/app/assets/javascripts/components/NoAccountWarning.tsx @@ -35,9 +35,9 @@ function NoAccountWarning({ }} title="Ignore" label="Ignore" - className="border-0 p-0 bg-transparent cursor-pointer rounded-md col-start-2 row-start-1" + className="border-0 p-0 bg-transparent cursor-pointer rounded-md col-start-2 row-start-1 color-neutral hover:color-info" > - +
); diff --git a/app/assets/stylesheets/_sn.scss b/app/assets/stylesheets/_sn.scss index 06ff43e0b..735334c0f 100644 --- a/app/assets/stylesheets/_sn.scss +++ b/app/assets/stylesheets/_sn.scss @@ -1,14 +1,15 @@ -/* Generic UI controls that have yet to be extracted in Stylekit */ +/* Generic UI controls that have yet to be extracted into Stylekit */ .sn-btn { - @extend .text-sm; + @extend .border-0; + @extend .bg-main; + @extend .cursor-pointer; @extend .font-bold; @extend .py-2; @extend .px-3; - @extend .bg-main; - @extend .text-info-contrast; - @extend .border-0; @extend .rounded; - @extend .cursor-pointer; + @extend .text-info-contrast; + @extend .text-sm; + @extend .hover\:brightness-130; } diff --git a/app/assets/stylesheets/_ui.scss b/app/assets/stylesheets/_ui.scss index a8558dd9e..76c23e573 100644 --- a/app/assets/stylesheets/_ui.scss +++ b/app/assets/stylesheets/_ui.scss @@ -153,6 +153,13 @@ $screen-md-max: ($screen-lg-min - 1) !default; grid-column-end: 3; } +.color-neutral { + color: var(--sn-stylekit-neutral-color) +} +.hover\:color-info:hover { + color: var(--sn-stylekit-info-color) +} + .hover\:brightness-130:hover { filter: brightness(130%); } @@ -161,11 +168,8 @@ $screen-md-max: ($screen-lg-min - 1) !default; cursor: pointer; } -.fill-neutral { - fill: var(--sn-stylekit-neutral-color); -} -.hover\:fill-info:hover { - fill: var(--sn-stylekit-info-color) +.fill-current { + fill: currentColor; } .font-semibold { From 117d414d6b9c0ecb7f93879230418a7fd168c625 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 2 Feb 2021 17:38:44 +0100 Subject: [PATCH 25/55] fix: wording --- app/assets/javascripts/components/NoAccountWarning.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/NoAccountWarning.tsx b/app/assets/javascripts/components/NoAccountWarning.tsx index 322cf5c9d..aeb26dd3d 100644 --- a/app/assets/javascripts/components/NoAccountWarning.tsx +++ b/app/assets/javascripts/components/NoAccountWarning.tsx @@ -18,7 +18,7 @@ function NoAccountWarning({

Data not backed up

- Sign in or register to back up your notes + Sign in or register to back up your notes.

diff --git a/app/assets/stylesheets/_ui.scss b/app/assets/stylesheets/_ui.scss index e1c8ff258..5b35658a3 100644 --- a/app/assets/stylesheets/_ui.scss +++ b/app/assets/stylesheets/_ui.scss @@ -111,6 +111,9 @@ $screen-md-max: ($screen-lg-min - 1) !default; margin-top: 1.25rem; } +.p-0 { + padding: 0rem; +} .p-5 { padding: 1.25rem; } From aa34bfc0c6a7f9dfdb05e11068f038bae9001095 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 15 Feb 2021 16:28:36 +0100 Subject: [PATCH 36/55] fix: hide protections paragraph when no account or passcode exist --- app/assets/javascripts/directives/views/accountMenu.ts | 4 ++++ app/assets/templates/directives/account-menu.pug | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index 0e31abf5d..abd423ece 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -189,6 +189,10 @@ class AccountMenuCtrl extends PureViewCtrl { }); } + hasProtections() { + return this.application.hasAccount() || this.application.hasPasscode(); + } + private getProtectionsDisabledUntil(): string | null { const protectionExpiry = this.application.getProtectionSessionExpiryDate(); const now = new Date(); diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index ceb885d15..1941afa56 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -164,7 +164,7 @@ | {{self.encryptionStatusForNotes()}} p.sk-p | {{self.state.encryptionStatusString}} - .sk-panel-section + .sk-panel-section(ng-if="self.hasProtections()") .sk-panel-section-title Protections .sk-panel-section-subtitle.info(ng-if="self.state.protectionsDisabledUntil") | Protections are disabled until {{self.state.protectionsDisabledUntil}} From 4426eb2c58f2f107bca73fd5ee902c2df63ff3b2 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 15 Feb 2021 16:41:16 +0100 Subject: [PATCH 37/55] chore(deps): remove unused dependencies --- package.json | 3 - yarn.lock | 244 ++++----------------------------------------------- 2 files changed, 19 insertions(+), 228 deletions(-) diff --git a/package.json b/package.json index 008797b11..7eb868c83 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "@svgr/webpack": "^5.5.0", "@types/angular": "^1.8.0", "@types/lodash": "^4.14.168", - "@types/mocha": "^7.0.2", "@types/pug": "^2.0.4", "@types/react": "^17.0.0", "@typescript-eslint/eslint-plugin": "^4.14.0", @@ -37,7 +36,6 @@ "babel-eslint": "^10.1.0", "babel-loader": "^8.2.2", "babel-plugin-angularjs-annotate": "^0.10.0", - "chai": "^4.2.0", "connect": "^3.7.0", "css-loader": "^3.4.2", "dotenv": "^8.2.0", @@ -49,7 +47,6 @@ "html-webpack-plugin": "^4.3.0", "lodash": "^4.17.20", "mini-css-extract-plugin": "^0.9.0", - "mocha": "^7.1.0", "ng-cache-loader": "0.0.26", "node-sass": "^4.14.1", "pug": "^2.0.4", diff --git a/yarn.lock b/yarn.lock index 549f70f34..20467740b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2005,11 +2005,6 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/mocha@^7.0.2": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce" - integrity sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w== - "@types/node@*": version "14.14.10" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.10.tgz#5958a82e41863cfc71f2307b3748e3491ba03785" @@ -2406,11 +2401,6 @@ angular@^1.8.2: resolved "https://registry.yarnpkg.com/angular/-/angular-1.8.2.tgz#5983bbb5a9fa63e213cb7749199e0d352de3a2f1" integrity sha512-IauMOej2xEe7/7Ennahkbb5qd/HFADiNuLSESz9Q27inmi32zB0lnAsFeLEWcox3Gd1F6YhNd1CP7/9IukJ0Gw== -ansi-colors@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== - ansi-colors@^3.0.0: version "3.2.4" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" @@ -2616,11 +2606,6 @@ assert@^1.1.1: object-assign "^4.1.1" util "0.10.3" -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -2882,11 +2867,6 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -3122,18 +3102,6 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" -chai@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" - integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - pathval "^1.1.0" - type-detect "^4.0.5" - chalk@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -3169,26 +3137,6 @@ character-parser@^2.1.1: dependencies: is-regex "^1.0.3" -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= - -chokidar@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" - integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.2.0" - optionalDependencies: - fsevents "~2.1.1" - chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -3714,13 +3662,6 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - debug@^3.1.1, debug@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -3745,13 +3686,6 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== - dependencies: - type-detect "^4.0.0" - deep-equal@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" @@ -3867,11 +3801,6 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -4162,7 +4091,7 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -4575,13 +4504,6 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-up@3.0.0, find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -4590,6 +4512,13 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + find-up@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -4616,13 +4545,6 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" -flat@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" - integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== - dependencies: - is-buffer "~2.0.3" - flatted@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" @@ -4715,7 +4637,7 @@ fsevents@^1.2.7: bindings "^1.5.0" nan "^2.12.1" -fsevents@~2.1.1, fsevents@~2.1.2: +fsevents@~2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== @@ -4771,11 +4693,6 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= - get-intrinsic@^1.0.0, get-intrinsic@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" @@ -4838,18 +4755,6 @@ glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" -glob@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -4947,11 +4852,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -4987,7 +4887,7 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.0, has-symbols@^1.0.1: +has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -5052,7 +4952,7 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -he@1.2.0, he@1.2.x, he@^1.2.0: +he@1.2.x, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -5428,11 +5328,6 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@~2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - is-callable@^1.1.4, is-callable@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" @@ -5687,14 +5582,6 @@ js-stringify@^1.0.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -5911,13 +5798,6 @@ lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.1 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -log-symbols@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== - dependencies: - chalk "^2.4.2" - loglevel@^1.6.8: version "1.7.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" @@ -6162,7 +6042,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2: +minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -6198,7 +6078,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -6210,36 +6090,6 @@ mobx@^6.1.6: resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.1.6.tgz#ae75e57ec07d190ed187273864002163fa357224" integrity sha512-3by0Avodad/3cdPAuJuj8jWXhe1YByHKaEkonD9yOdcMoMuot2jrjlSXmQPhR1bJpNHfSsOx122tM9Pv3IzFWA== -mocha@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" - integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== - dependencies: - ansi-colors "3.2.3" - browser-stdout "1.3.1" - chokidar "3.3.0" - debug "3.2.6" - diff "3.5.0" - escape-string-regexp "1.0.5" - find-up "3.0.0" - glob "7.1.3" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "3.0.0" - minimatch "3.0.4" - mkdirp "0.5.5" - ms "2.1.1" - node-environment-flags "1.0.6" - object.assign "4.1.0" - strip-json-comments "2.0.1" - supports-color "6.0.0" - which "1.3.1" - wide-align "1.1.3" - yargs "13.3.2" - yargs-parser "13.1.2" - yargs-unparser "1.6.0" - move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -6347,14 +6197,6 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -node-environment-flags@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" - integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - node-forge@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" @@ -6535,7 +6377,7 @@ object-is@^1.0.1: call-bind "^1.0.0" define-properties "^1.1.3" -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -6547,16 +6389,6 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - object.assign@^4.1.0, object.assign@^4.1.1, object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" @@ -6887,11 +6719,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= - pbkdf2@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" @@ -7436,13 +7263,6 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -readdirp@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" - integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== - dependencies: - picomatch "^2.0.4" - readdirp@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" @@ -7804,7 +7624,7 @@ selfsigned@^1.10.8: dependencies: node-forge "^0.10.0" -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -8378,23 +8198,11 @@ strip-indent@^1.0.1: dependencies: get-stdin "^4.0.1" -strip-json-comments@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -supports-color@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== - dependencies: - has-flag "^3.0.0" - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -8647,11 +8455,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -9088,7 +8891,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1, which@1.3.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: +which@1, which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -9102,7 +8905,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wide-align@1.1.3, wide-align@^1.1.0: +wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== @@ -9190,7 +8993,7 @@ yaml@^1.10.0: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== -yargs-parser@13.1.2, yargs-parser@^13.1.2: +yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== @@ -9198,16 +9001,7 @@ yargs-parser@13.1.2, yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-unparser@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== - dependencies: - flat "^4.1.0" - lodash "^4.17.15" - yargs "^13.3.0" - -yargs@13.3.2, yargs@^13.3.0, yargs@^13.3.2: +yargs@^13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== From 734505c133782a2a27c3b499c7d0f673922a7268 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 15 Feb 2021 17:20:13 +0100 Subject: [PATCH 38/55] fix: button casing --- app/assets/stylesheets/_sn.scss | 1 + app/assets/stylesheets/_ui.scss | 4 ++++ app/assets/templates/directives/account-menu.pug | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/_sn.scss b/app/assets/stylesheets/_sn.scss index 735334c0f..420dd8b24 100644 --- a/app/assets/stylesheets/_sn.scss +++ b/app/assets/stylesheets/_sn.scss @@ -4,6 +4,7 @@ @extend .border-0; @extend .bg-main; @extend .cursor-pointer; + @extend .capitalize; @extend .font-bold; @extend .py-2; @extend .px-3; diff --git a/app/assets/stylesheets/_ui.scss b/app/assets/stylesheets/_ui.scss index 5b35658a3..8ee59b19d 100644 --- a/app/assets/stylesheets/_ui.scss +++ b/app/assets/stylesheets/_ui.scss @@ -146,6 +146,10 @@ $screen-md-max: ($screen-lg-min - 1) !default; background-color: transparent; } +.capitalize { + text-transform: capitalize; +} + .col-start-1 { grid-column-start: 1; } diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index 1941afa56..f5dbf61e2 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -176,7 +176,7 @@ | 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 + span.sk-label.capitalize Enable protections .sk-panel-section .sk-panel-section-title Passcode Lock div(ng-if='!self.state.hasPasscode') From 1852b5e0454efe7aac369fd43201f6ff1037c405 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Thu, 18 Feb 2021 09:48:39 +0100 Subject: [PATCH 39/55] feat: implement SNApplication.hasProtectionSources --- app/assets/javascripts/directives/views/accountMenu.ts | 2 +- package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index abd423ece..82fc6cdca 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -190,7 +190,7 @@ class AccountMenuCtrl extends PureViewCtrl { } hasProtections() { - return this.application.hasAccount() || this.application.hasPasscode(); + return this.application.hasProtectionSources(); } private getProtectionsDisabledUntil(): string | null { diff --git a/package.json b/package.json index 7eb868c83..5c935ecb0 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@reach/alert-dialog": "^0.13.0", "@reach/dialog": "^0.13.0", "@standardnotes/sncrypto-web": "^1.2.10", - "@standardnotes/snjs": "^2.0.54", + "@standardnotes/snjs": "^2.0.57", "mobx": "^6.1.6", "preact": "^10.5.12" } diff --git a/yarn.lock b/yarn.lock index 20467740b..c5287e1bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1845,10 +1845,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@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== +"@standardnotes/snjs@^2.0.57": + version "2.0.57" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.57.tgz#758d30d9074aa463ca2b642783d929a10a1a1c9f" + integrity sha512-s2FP024TziZnt0nJ10Tbja3IQ2KOITA67EGchadAN+vapXEicTDX2MSCPzlvk2D1M494zu15vWwQX1ryeHvHHA== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" From 573734e6af28d26094125a3b541572a14f49132b Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 19 Feb 2021 11:06:09 +0100 Subject: [PATCH 40/55] chore(version): 3.6.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5c935ecb0..25a958730 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "standard-notes-web", - "version": "3.5.19", + "version": "3.6.0", "license": "AGPL-3.0-or-later", "repository": { "type": "git", From 4d30d019ee52aed511e0f23785ee27b27c9838ee Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Fri, 19 Feb 2021 12:19:31 +0100 Subject: [PATCH 41/55] feat: enable sessions management for every build --- app/assets/javascripts/directives/views/accountMenu.ts | 4 +--- app/assets/templates/directives/account-menu.pug | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index 82fc6cdca..6012d5fbe 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -148,9 +148,7 @@ class AccountMenuCtrl extends PureViewCtrl { async $onInit() { super.$onInit(); this.setState({ - showSessions: - this.appState.enableUnfinishedFeatures && - (await this.application.userCanManageSessions()), + showSessions: await this.application.userCanManageSessions() }); const sync = this.appState.sync; diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index f5dbf61e2..e56af6939 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -156,7 +156,6 @@ ) Change Password a.sk-a.info.sk-panel-row.condensed( ng-click="self.openSessionsModal()" - ng-if="self.state.showSessions" ) Manage Sessions .sk-panel-section .sk-panel-section-title Encryption From ed7f093e02c3e69a889651c5967fde080ca609a6 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 22 Feb 2021 11:38:35 +0100 Subject: [PATCH 42/55] feat: make "Protected" flag more subtle --- app/assets/javascripts/views/notes/notes-view.pug | 4 +++- app/assets/javascripts/views/notes/notes_view.ts | 6 ------ app/assets/stylesheets/_notes.scss | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/views/notes/notes-view.pug b/app/assets/javascripts/views/notes/notes-view.pug index 6271ce2b8..599faaea0 100644 --- a/app/assets/javascripts/views/notes/notes-view.pug +++ b/app/assets/javascripts/views/notes/notes-view.pug @@ -143,7 +143,9 @@ .default-preview( ng-show='!note.preview_html && !note.preview_plain' ) {{note.text}} - .date.faded(ng-show='!self.state.hideDate') + .bottom-info.faded(ng-show='!self.state.hideDate || note.protected') + span(ng-if="note.protected") + | Protected •{{self.state.hideDate ? '' : ' '}} span(ng-show="self.state.sortBy == 'userModifiedDate'") | Modified {{note.updatedAtString || 'Now'}} span(ng-show="self.state.sortBy != 'userModifiedDate'") diff --git a/app/assets/javascripts/views/notes/notes_view.ts b/app/assets/javascripts/views/notes/notes_view.ts index 154a5f7f6..3bd631cf6 100644 --- a/app/assets/javascripts/views/notes/notes_view.ts +++ b/app/assets/javascripts/views/notes/notes_view.ts @@ -576,12 +576,6 @@ class NotesViewCtrl extends PureViewCtrl { class: 'warning' }); } - if (note.protected) { - flags.push({ - text: "Protected", - class: 'success' - }); - } if (note.locked) { flags.push({ text: "Locked", diff --git a/app/assets/stylesheets/_notes.scss b/app/assets/stylesheets/_notes.scss index 794255703..fa7d78c10 100644 --- a/app/assets/stylesheets/_notes.scss +++ b/app/assets/stylesheets/_notes.scss @@ -126,7 +126,7 @@ text-overflow: ellipsis; } - > .date { + > .bottom-info { font-size: 12px; margin-top: 4px; } From 944d5db9b749a955d3f762936635c05515ab5d51 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 22 Feb 2021 12:01:29 +0100 Subject: [PATCH 43/55] fix: only match protected note title --- .../javascripts/views/notes/note_utils.ts | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/app/assets/javascripts/views/notes/note_utils.ts b/app/assets/javascripts/views/notes/note_utils.ts index 7ddb91a73..6f8265982 100644 --- a/app/assets/javascripts/views/notes/note_utils.ts +++ b/app/assets/javascripts/views/notes/note_utils.ts @@ -5,44 +5,54 @@ export function notePassesFilter( showArchived: boolean, hidePinned: boolean, filterText: string -) { - +): boolean { const canShowArchived = showArchived; const canShowPinned = !hidePinned; - if ( - (note.archived && !canShowArchived) || - (note.pinned && !canShowPinned) - ) { + if ((note.archived && !canShowArchived) || (note.pinned && !canShowPinned)) { return false; } - return noteMatchesQuery(note, filterText); + if (note.protected) { + const match = noteMatchesQuery(note, filterText); + /** Only match title to prevent leaking protected note text */ + return match === Match.Title || match === Match.TitleAndText; + } else { + return noteMatchesQuery(note, filterText) !== Match.None; + } } -function noteMatchesQuery( - note: SNNote, - query: string -) { +enum Match { + None = 0, + Title = 1, + Text = 2, + TitleAndText = Title + Text, + Uuid = 5, +} + +function noteMatchesQuery(note: SNNote, query: string): Match { if (query.length === 0) { - return true; + return Match.TitleAndText; } const title = note.safeTitle().toLowerCase(); const text = note.safeText().toLowerCase(); const lowercaseText = query.toLowerCase(); + const words = lowercaseText.split(' '); const quotedText = stringBetweenQuotes(lowercaseText); if (quotedText) { - return title.includes(quotedText) || text.includes(quotedText); + return ( + (title.includes(quotedText) ? Match.Title : Match.None) + + (text.includes(quotedText) ? Match.Text : Match.None) + ); } if (stringIsUuid(lowercaseText)) { - return note.uuid === lowercaseText; + return note.uuid === lowercaseText ? Match.Uuid : Match.None; } - const words = lowercaseText.split(" "); const matchesTitle = words.every((word) => { return title.indexOf(word) >= 0; }); const matchesBody = words.every((word) => { return text.indexOf(word) >= 0; }); - return matchesTitle || matchesBody; + return (matchesTitle ? Match.Title : 0) + (matchesBody ? Match.Text : 0); } function stringBetweenQuotes(text: string) { From 6a3e070ea67ac339bbcaa685a18991a81ceda496 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 22 Feb 2021 17:41:45 +0100 Subject: [PATCH 44/55] fix: remove inconsistencies between protected note label and date --- app/assets/javascripts/views/notes/notes-view.pug | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/views/notes/notes-view.pug b/app/assets/javascripts/views/notes/notes-view.pug index 599faaea0..a42e16bc1 100644 --- a/app/assets/javascripts/views/notes/notes-view.pug +++ b/app/assets/javascripts/views/notes/notes-view.pug @@ -145,10 +145,10 @@ ) {{note.text}} .bottom-info.faded(ng-show='!self.state.hideDate || note.protected') span(ng-if="note.protected") - | Protected •{{self.state.hideDate ? '' : ' '}} - span(ng-show="self.state.sortBy == 'userModifiedDate'") + | Protected{{self.state.hideDate ? '' : ' • '}} + span(ng-show="!self.state.hideDate && self.state.sortBy == 'userModifiedDate'") | Modified {{note.updatedAtString || 'Now'}} - span(ng-show="self.state.sortBy != 'userModifiedDate'") + span(ng-show="!self.state.hideDate && self.state.sortBy != 'userModifiedDate'") | {{note.createdAtString || 'Now'}} .tags-string(ng-if='!self.state.hideTags && self.state.renderedNotesTags[$index]') .faded {{self.state.renderedNotesTags[$index]}} From ef3a962d788c4d1c375ed0fee28ce92da5a914de Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Mon, 22 Feb 2021 17:51:45 +0100 Subject: [PATCH 45/55] feat: show warning when protecting a note with no protection source --- app/assets/javascripts/strings.ts | 2 ++ .../javascripts/views/editor/editor_view.ts | 22 +++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/strings.ts b/app/assets/javascripts/strings.ts index c8782ae29..25232bc9c 100644 --- a/app/assets/javascripts/strings.ts +++ b/app/assets/javascripts/strings.ts @@ -124,4 +124,6 @@ export const Strings = { : 'password manager'; return `Your keys are currently stored in your operating system's ${keychainName}. Adding a passcode prevents even your operating system from reading them.`; }, + protectingNoteWithoutProtectionSources: 'Access to this note will not be restricted until you set up a passcode or account.', + openAccountMenu: 'Open Account Menu' }; diff --git a/app/assets/javascripts/views/editor/editor_view.ts b/app/assets/javascripts/views/editor/editor_view.ts index c0f67f836..5fca2e50e 100644 --- a/app/assets/javascripts/views/editor/editor_view.ts +++ b/app/assets/javascripts/views/editor/editor_view.ts @@ -1,4 +1,4 @@ -import { STRING_ARCHIVE_LOCKED_ATTEMPT, STRING_SAVING_WHILE_DOCUMENT_HIDDEN, STRING_UNARCHIVE_LOCKED_ATTEMPT } from './../../strings'; +import { Strings, STRING_ARCHIVE_LOCKED_ATTEMPT, STRING_SAVING_WHILE_DOCUMENT_HIDDEN, STRING_UNARCHIVE_LOCKED_ATTEMPT } from './../../strings'; import { Editor } from '@/ui_models/editor'; import { WebApplication } from '@/ui_models/application'; import { PanelPuppet, WebDirective } from '@/types'; @@ -713,15 +713,23 @@ class EditorViewCtrl extends PureViewCtrl { ); } - toggleProtectNote() { - this.saveNote( - true, - false, - true, + async toggleProtectNote() { + const note = await this.application.changeAndSaveItem( + this.note.uuid, (mutator) => { mutator.protected = !this.note.protected; - } + }, + false ); + if (note?.protected && !this.application.hasProtectionSources()) { + if (await confirmDialog({ + text: Strings.protectingNoteWithoutProtectionSources, + confirmButtonText: Strings.openAccountMenu, + confirmButtonStyle: 'info', + })) { + this.appState.accountMenu.setShow(true); + } + } } toggleNotePreview() { From a3f73ba6645372a1be6628aa5c23e2d8c4d00534 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Tue, 23 Feb 2021 10:40:08 +0100 Subject: [PATCH 46/55] feat: make unprotecting a note a protected action --- .../javascripts/views/editor/editor_view.ts | 26 +++++++++---------- package.json | 2 +- yarn.lock | 8 +++--- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/app/assets/javascripts/views/editor/editor_view.ts b/app/assets/javascripts/views/editor/editor_view.ts index 5fca2e50e..f5ed13f1a 100644 --- a/app/assets/javascripts/views/editor/editor_view.ts +++ b/app/assets/javascripts/views/editor/editor_view.ts @@ -714,20 +714,18 @@ class EditorViewCtrl extends PureViewCtrl { } async toggleProtectNote() { - const note = await this.application.changeAndSaveItem( - this.note.uuid, - (mutator) => { - mutator.protected = !this.note.protected; - }, - false - ); - if (note?.protected && !this.application.hasProtectionSources()) { - if (await confirmDialog({ - text: Strings.protectingNoteWithoutProtectionSources, - confirmButtonText: Strings.openAccountMenu, - confirmButtonStyle: 'info', - })) { - this.appState.accountMenu.setShow(true); + if (this.note.protected) { + void this.application.unprotectNote(this.note); + } else { + const note = await this.application.protectNote(this.note); + if (note?.protected && !this.application.hasProtectionSources()) { + if (await confirmDialog({ + text: Strings.protectingNoteWithoutProtectionSources, + confirmButtonText: Strings.openAccountMenu, + confirmButtonStyle: 'info', + })) { + this.appState.accountMenu.setShow(true); + } } } } diff --git a/package.json b/package.json index 25a958730..5537d4f98 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@reach/alert-dialog": "^0.13.0", "@reach/dialog": "^0.13.0", "@standardnotes/sncrypto-web": "^1.2.10", - "@standardnotes/snjs": "^2.0.57", + "@standardnotes/snjs": "^2.0.58", "mobx": "^6.1.6", "preact": "^10.5.12" } diff --git a/yarn.lock b/yarn.lock index c5287e1bd..21cf08f3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1845,10 +1845,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.57": - version "2.0.57" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.57.tgz#758d30d9074aa463ca2b642783d929a10a1a1c9f" - integrity sha512-s2FP024TziZnt0nJ10Tbja3IQ2KOITA67EGchadAN+vapXEicTDX2MSCPzlvk2D1M494zu15vWwQX1ryeHvHHA== +"@standardnotes/snjs@^2.0.58": + version "2.0.58" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.58.tgz#b3cc340699effd9ab2b55e48eb84745f71e058cb" + integrity sha512-eJnCpwTpI55RM916xjdgcGdzIcgaGJQ5EeykKvLxD4Oy7FRPfQnZc5hCp4LbeZvdlQQze+E2gH1nY77zPDsVXw== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" From c94bc0edee2da752a1a2c41c80109d8d87969e40 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Thu, 25 Feb 2021 14:43:44 +0100 Subject: [PATCH 47/55] chore(deps): upgrade snjs --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5537d4f98..345e1b57f 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@reach/alert-dialog": "^0.13.0", "@reach/dialog": "^0.13.0", "@standardnotes/sncrypto-web": "^1.2.10", - "@standardnotes/snjs": "^2.0.58", + "@standardnotes/snjs": "^2.0.60", "mobx": "^6.1.6", "preact": "^10.5.12" } diff --git a/yarn.lock b/yarn.lock index 21cf08f3b..e308b8829 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1845,10 +1845,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.58": - version "2.0.58" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.58.tgz#b3cc340699effd9ab2b55e48eb84745f71e058cb" - integrity sha512-eJnCpwTpI55RM916xjdgcGdzIcgaGJQ5EeykKvLxD4Oy7FRPfQnZc5hCp4LbeZvdlQQze+E2gH1nY77zPDsVXw== +"@standardnotes/snjs@^2.0.60": + version "2.0.60" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.60.tgz#e8f4385a8c30f03658512725a3b2144b487ddfcc" + integrity sha512-y5AZeT1GyTrFnNPFNNI7M7RND5NlM1tsGuyCULCIwrGXEk4h+0dJwNdNRFsTkRuShosbthZV8hW91YdnqNIJFg== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" From 14e2808ac0ecb8c0d1ecb082edc7411d5a1afd47 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Thu, 25 Feb 2021 17:14:25 +0100 Subject: [PATCH 48/55] chore(version): 3.6.0-beta01 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 345e1b57f..be23193eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "standard-notes-web", - "version": "3.6.0", + "version": "3.6.0-beta01", "license": "AGPL-3.0-or-later", "repository": { "type": "git", From 3fa86428ba6ace9c91a924127fab077d1c982dc1 Mon Sep 17 00:00:00 2001 From: Darius JJ Chuck <79410894+standarius@users.noreply.github.com> Date: Tue, 2 Mar 2021 09:25:58 +0100 Subject: [PATCH 49/55] fix: run docker with root to fix crashing on Linux (undoes 62da387d3a) (#525) --- Dockerfile | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index d30d111ec..ef383b668 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,5 @@ FROM ruby:2.7.1-alpine3.12 -ARG UID=1000 -ARG GID=1000 - -RUN addgroup -S webapp -g $GID && adduser -D -S webapp -G webapp -u $UID - RUN apk add --update --no-cache \ alpine-sdk \ nodejs-current \ @@ -16,19 +11,15 @@ RUN apk add --update --no-cache \ WORKDIR /app/ -RUN chown -R $UID:$GID . +COPY package.json yarn.lock Gemfile Gemfile.lock /app/ -USER webapp - -COPY --chown=$UID:$GID package.json yarn.lock Gemfile Gemfile.lock /app/ - -COPY --chown=$UID:$GID vendor /app/vendor +COPY vendor /app/vendor RUN yarn install --pure-lockfile RUN gem install bundler && bundle install -COPY --chown=$UID:$GID . /app/ +COPY . /app/ RUN yarn bundle From d49e508cfce409a3578f57f0bc3642f06ff729b0 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Tue, 2 Mar 2021 08:06:47 -0300 Subject: [PATCH 50/55] feat: make encrypted backups protected (#524) Co-authored-by: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> --- app/assets/javascripts/services/archiveManager.ts | 2 +- package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/services/archiveManager.ts b/app/assets/javascripts/services/archiveManager.ts index 8d6b16a95..d80635a1d 100644 --- a/app/assets/javascripts/services/archiveManager.ts +++ b/app/assets/javascripts/services/archiveManager.ts @@ -32,7 +32,7 @@ export class ArchiveManager { ? EncryptionIntent.FileEncrypted : EncryptionIntent.FileDecrypted; - const data = await this.application.createBackupFile(intent); + const data = await this.application.createBackupFile(intent, true); if (!data) { return; } diff --git a/package.json b/package.json index 5c935ecb0..ffa7e9b3e 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@reach/alert-dialog": "^0.13.0", "@reach/dialog": "^0.13.0", "@standardnotes/sncrypto-web": "^1.2.10", - "@standardnotes/snjs": "^2.0.57", + "@standardnotes/snjs": "^2.0.61", "mobx": "^6.1.6", "preact": "^10.5.12" } diff --git a/yarn.lock b/yarn.lock index c5287e1bd..bfe148027 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1845,10 +1845,10 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.57": - version "2.0.57" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.57.tgz#758d30d9074aa463ca2b642783d929a10a1a1c9f" - integrity sha512-s2FP024TziZnt0nJ10Tbja3IQ2KOITA67EGchadAN+vapXEicTDX2MSCPzlvk2D1M494zu15vWwQX1ryeHvHHA== +"@standardnotes/snjs@^2.0.61": + version "2.0.61" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.61.tgz#82608ef48830a80afbc9468ed2d308e59e4e9a08" + integrity sha512-MVnzT7cX7oIak9g/xlOJKfWCfBygw8kXtuVHSofdxPhYIPIr1MwK4xkkqho/ZShVfPQEESyj3RaEsOIzKuuL4w== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" From a22a95e9285ec379e551e65a23e73a4f96a73c45 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Wed, 3 Mar 2021 11:03:41 +0100 Subject: [PATCH 51/55] fix: remove white corner dots in dark theme lock screens --- app/assets/stylesheets/_reach-sub.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/_reach-sub.scss b/app/assets/stylesheets/_reach-sub.scss index 346817713..fcb0da138 100644 --- a/app/assets/stylesheets/_reach-sub.scss +++ b/app/assets/stylesheets/_reach-sub.scss @@ -28,6 +28,7 @@ flex-basis: 0; min-width: 400px; max-width: 600px; + background: none; } [data-reach-dialog-content] .sk-modal-content, From 9541886a2c1ea5f9e668677bcbd0cfa538c3d546 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Wed, 3 Mar 2021 14:30:24 +0100 Subject: [PATCH 52/55] fix: download backup later in the change password process --- app/assets/javascripts/directives/views/passwordWizard.ts | 3 ++- app/assets/javascripts/services/bridge.ts | 2 +- app/assets/javascripts/ui_models/application.ts | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/directives/views/passwordWizard.ts b/app/assets/javascripts/directives/views/passwordWizard.ts index 934ebb1fe..4f0dfe8ee 100644 --- a/app/assets/javascripts/directives/views/passwordWizard.ts +++ b/app/assets/javascripts/directives/views/passwordWizard.ts @@ -173,12 +173,13 @@ class PasswordWizardCtrl extends PureViewCtrl implements PasswordW } async processPasswordChange() { + await this.application.downloadBackup(); await this.setState({ lockContinue: true, processing: true }); await this.setFormDataState({ - status: "Processing encryption keys..." + status: "Processing encryption keys…" }); const newPassword = this.props.securityUpdate ? this.state.formData.currentPassword diff --git a/app/assets/javascripts/services/bridge.ts b/app/assets/javascripts/services/bridge.ts index 3466cf1fd..d68ab7916 100644 --- a/app/assets/javascripts/services/bridge.ts +++ b/app/assets/javascripts/services/bridge.ts @@ -18,5 +18,5 @@ export interface Bridge { onMajorDataChange(): void; onInitialDataLoad(): void; onSearch(text?: string): void; - downloadBackup(): void; + downloadBackup(): Promise; } diff --git a/app/assets/javascripts/ui_models/application.ts b/app/assets/javascripts/ui_models/application.ts index 2bc8b2c66..9fa8d2caa 100644 --- a/app/assets/javascripts/ui_models/application.ts +++ b/app/assets/javascripts/ui_models/application.ts @@ -147,7 +147,6 @@ export class WebApplication extends SNApplication { } presentPasswordWizard(type: PasswordWizardType) { - this.bridge.downloadBackup(); const scope = this.scope!.$new(true) as PasswordWizardScope; scope.type = type; scope.application = this; @@ -157,6 +156,10 @@ export class WebApplication extends SNApplication { this.applicationElement.append(el); } + downloadBackup(): Promise { + return this.bridge.downloadBackup(); + } + authenticationInProgress() { return this.currentAuthenticationElement != null; } From 7f7b849ab8c5b474bbc1ee614799361e2974c79f Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Wed, 3 Mar 2021 14:30:38 +0100 Subject: [PATCH 53/55] feat: decrease editor font size --- app/assets/stylesheets/_stylekit-sub.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/_stylekit-sub.scss b/app/assets/stylesheets/_stylekit-sub.scss index 2a500e677..7515853e5 100644 --- a/app/assets/stylesheets/_stylekit-sub.scss +++ b/app/assets/stylesheets/_stylekit-sub.scss @@ -1,3 +1,7 @@ +:root { + --sn-stylekit-font-size-editor: 1.154rem; +} + .sn-component { .sk-notification { &.unpadded { From d6f7779a76c158157d2e2f96f4910c4afeaf9188 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Wed, 3 Mar 2021 14:52:29 +0100 Subject: [PATCH 54/55] fix: compile error --- app/assets/javascripts/services/bridge.ts | 2 +- app/assets/javascripts/ui_models/application.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/services/bridge.ts b/app/assets/javascripts/services/bridge.ts index d68ab7916..7b0da9931 100644 --- a/app/assets/javascripts/services/bridge.ts +++ b/app/assets/javascripts/services/bridge.ts @@ -18,5 +18,5 @@ export interface Bridge { onMajorDataChange(): void; onInitialDataLoad(): void; onSearch(text?: string): void; - downloadBackup(): Promise; + downloadBackup(): void | Promise; } diff --git a/app/assets/javascripts/ui_models/application.ts b/app/assets/javascripts/ui_models/application.ts index 9fa8d2caa..8cfa78000 100644 --- a/app/assets/javascripts/ui_models/application.ts +++ b/app/assets/javascripts/ui_models/application.ts @@ -156,7 +156,7 @@ export class WebApplication extends SNApplication { this.applicationElement.append(el); } - downloadBackup(): Promise { + downloadBackup(): void | Promise { return this.bridge.downloadBackup(); } From 9c7bb08d0ef095cb931d751670a2d5760ce89c7d Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Wed, 3 Mar 2021 14:52:43 +0100 Subject: [PATCH 55/55] chore(version): 3.6.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e7212c5b2..9c97e8fa5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "standard-notes-web", - "version": "3.6.0", + "version": "3.6.1", "license": "AGPL-3.0-or-later", "repository": { "type": "git",