From 7e251262d770cfc9d791115b9c18b862c49e4e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Thu, 4 Aug 2022 15:13:30 +0200 Subject: [PATCH] feat(web): extract ui-services package --- ...ommon-npm-1.30.0-a603c54867-833b6e7f3e.zip | Bin 0 -> 33936 bytes package.json | 1 + .../src/Domain/Backups/BackupFile.ts | 9 - .../src/Domain/Backups/BackupFileDecryptor.ts | 2 +- .../Service/Encryption/EncryptionProvider.ts | 2 +- .../Service/Encryption/EncryptionService.ts | 2 +- packages/encryption/src/Domain/index.ts | 1 - .../Abstract/Component/ActionObserver.ts | 4 + .../Component/ComponentEventObserver.ts | 3 + .../Abstract/Component/ComponentMessage.ts | 9 + .../Component/ComponentViewerEvent.ts | 3 + .../Component/IncomingComponentItemPayload.ts | 5 + .../Abstract/Component/KeyboardModifier.ts | 5 + .../Domain/Abstract/Component/MessageData.ts | 31 +++ .../Abstract/Component/PermissionDialog.ts | 10 + .../Domain/Abstract/Contextual/BackupFile.ts | 66 +------ .../BackupFileDecryptedContextualPayload.ts | 12 ++ .../BackupFileEncryptedContextualPayload.ts | 14 ++ .../Domain/Abstract/Contextual/Functions.ts | 39 ++++ .../src/Domain/Abstract/Contextual/index.ts | 10 - .../Item/Mutator/TransactionalMutation.ts | 11 ++ .../Domain/Abstract/Item/Types/ItemStream.ts | 11 ++ .../models/src/Domain/Abstract/Item/index.ts | 4 +- packages/models/src/Domain/index.ts | 23 ++- packages/services/package.json | 4 +- .../Application/AppGroupManagedApplication.ts | 7 + .../Application/ApplicationInterface.ts | 44 +++-- .../src/Domain/Application/DeinitCallback.ts | 2 +- .../Application/WebApplicationInterface.ts | 8 + .../Component/ComponentManagerInterface.ts | 23 +++ .../Domain/Component/ComponentViewerError.ts | 4 + .../Component/ComponentViewerInterface.ts | 29 +++ .../Domain/Device/DesktopManagerInterface.ts | 7 + .../src/Domain/Event/ApplicationEvent.ts | 65 +++++++ .../Domain/Event/ApplicationEventCallback.ts | 3 + .../src/Domain/Event}/WebAppEvent.ts | 0 .../src/Domain/Feature/FeatureStatus.ts | 6 + .../Feature/FeaturesClientInterface.ts} | 4 +- .../src/Domain/Feature/FeaturesEvent.ts | 4 + .../OfflineSubscriptionEntitlements.ts | 4 + .../SetOfflineFeaturesFunctionResponse.ts | 3 + .../src/Domain/Item}/ItemsClientInterface.ts | 13 +- .../Domain/Mutator/MutatorClientInterface.ts | 184 ++++++++++++++++++ packages/services/src/Domain/index.ts | 18 +- packages/snjs/lib/Application/Application.ts | 46 +++-- packages/snjs/lib/Application/Event.ts | 68 +------ .../snjs/lib/Client/ItemGroupController.ts | 4 +- .../Services/AppService/ApplicationService.ts | 14 +- .../ComponentManager/ComponentManager.spec.ts | 14 +- .../ComponentManager/ComponentManager.ts | 38 ++-- .../ComponentManager/ComponentViewer.ts | 38 ++-- .../lib/Services/ComponentManager/Types.ts | 67 +------ .../Services/Features/FeaturesService.spec.ts | 4 +- .../lib/Services/Features/FeaturesService.ts | 57 +++--- packages/snjs/lib/Services/Features/Types.ts | 20 -- packages/snjs/lib/Services/Features/index.ts | 2 - .../snjs/lib/Services/Items/ItemManager.ts | 8 +- .../Services/Items/TransactionalMutation.ts | 8 - packages/snjs/lib/Services/Items/index.ts | 2 - .../Services/Migration/MigrationService.ts | 2 +- .../Mutator/MutatorClientInterface.ts | 183 ----------------- .../lib/Services/Mutator/MutatorService.ts | 145 +++++++------- packages/snjs/lib/Services/Mutator/index.ts | 1 - packages/ui-services/.eslintignore | 3 + packages/ui-services/.eslintrc | 9 + packages/ui-services/.gitignore | 1 + packages/ui-services/jest.config.js | 11 ++ packages/ui-services/linter.tsconfig.json | 4 + packages/ui-services/package.json | 41 ++++ .../src/Alert/Functions.ts} | 35 ---- .../ui-services/src/Alert/WebAlertService.ts | 38 ++++ .../src/Archive}/ArchiveManager.ts | 6 +- .../src/IO}/IOService.ts | 0 .../src/Security}/AutolockService.ts | 0 .../src/Storage}/LocalStorage.ts | 18 -- .../src/Theme}/ThemeManager.ts | 6 +- packages/ui-services/src/index.ts | 7 + packages/ui-services/tsconfig.json | 14 ++ packages/web/package.json | 1 + .../javascripts/Application/Application.ts | 15 +- .../Application/ApplicationGroup.ts | 10 +- .../Device}/DesktopManager.ts | 10 +- .../Components/Abstract/PureComponent.tsx | 2 +- .../Components/AccountMenu/AccountMenu.tsx | 2 +- .../AccountMenu/AdvancedOptions.tsx | 2 +- .../AccountMenu/ConfirmPassword.tsx | 2 +- .../Components/AccountMenu/CreateAccount.tsx | 2 +- .../AccountMenu/GeneralAccountMenu.tsx | 2 +- .../AccountMenu/MenuPaneSelector.tsx | 2 +- .../Components/AccountMenu/SignIn.tsx | 2 +- .../Components/AccountMenu/User.tsx | 2 +- .../WorkspaceSwitcher/WorkspaceMenuItem.tsx | 2 +- .../WorkspaceSwitcherMenu.tsx | 2 +- .../WorkspaceSwitcherOption.tsx | 2 +- .../ApplicationView/ApplicationView.tsx | 5 +- .../AttachedFilesPopover/PopoverFileItem.tsx | 2 +- .../ChallengeModal/ChallengeModal.tsx | 2 +- .../LockscreenWorkspaceSwitcher.tsx | 2 +- .../ChangeEditor/ChangeEditorButton.tsx | 2 +- .../ComponentView/ComponentView.tsx | 6 +- .../ConfirmSignoutModal.tsx | 2 +- .../ContentListView/ContentList.tsx | 2 +- .../ContentListView/ContentListView.tsx | 2 +- .../FilePreview/FilePreviewModal.tsx | 4 +- .../Components/FileView/FileViewProps.tsx | 2 +- .../javascripts/Components/Footer/Footer.tsx | 5 +- .../src/javascripts/Components/Menu/Menu.tsx | 2 +- .../Components/NoteTags/NoteTag.tsx | 2 +- .../Components/NoteTags/NoteTagsContainer.tsx | 2 +- .../Components/NoteView/NoteView.test.ts | 2 +- .../Components/NoteView/NoteView.tsx | 18 +- .../Components/NotesOptions/AddTagOption.tsx | 2 +- .../NotesOptions/ChangeEditorOption.tsx | 2 +- .../NotesOptions/ListedActionsOption.tsx | 2 +- .../Components/NotesOptions/NotesOptions.tsx | 2 +- .../OtherSessionsSignOut.tsx | 2 +- .../Panes/Account/AccountPreferences.tsx | 2 +- .../Panes/Account/Authentication.tsx | 2 +- .../Panes/Account/ClearSessionDataView.tsx | 2 +- .../Preferences/Panes/Account/Credentials.tsx | 2 +- .../Preferences/Panes/Account/SignOutView.tsx | 2 +- .../Account/Subscription/Subscription.tsx | 2 +- .../Preferences/Panes/Backups/Backups.tsx | 2 +- .../CloudBackups/CloudBackupProvider.tsx | 2 +- .../Preferences/Panes/Backups/DataBackups.tsx | 4 +- .../General/Advanced/AdvancedSection.tsx | 2 +- .../General/Advanced/OfflineSubscription.tsx | 2 +- .../Preferences/Panes/General/General.tsx | 2 +- .../Preferences/Panes/Security/Encryption.tsx | 2 +- .../Panes/Security/EncryptionEnabled.tsx | 2 +- .../Panes/Security/ErroredItems.tsx | 2 +- .../Panes/Security/PasscodeLock.tsx | 4 +- .../Preferences/Panes/Security/Security.tsx | 2 +- .../Preferences/PreferencesProps.tsx | 2 +- .../PreferencesViewWrapperProps.tsx | 2 +- .../ProtectedItemOverlay.tsx | 2 +- .../PurchaseFlow/Panes/CreateAccount.tsx | 2 +- .../Components/PurchaseFlow/Panes/SignIn.tsx | 2 +- .../PurchaseFlow/PurchaseFlowView.tsx | 2 +- .../PurchaseFlow/PurchaseFlowWrapperProps.tsx | 2 +- .../Components/SearchBar/SearchBar.tsx | 2 +- .../SessionsModal/SessionsModal.tsx | 2 +- .../TagAutocomplete/AutocompleteTagHint.tsx | 2 +- .../TagAutocomplete/AutocompleteTagInput.tsx | 2 +- .../TagAutocomplete/AutocompleteTagResult.tsx | 2 +- .../Components/Tags/SmartViewsList.tsx | 2 +- .../Components/Tags/SmartViewsSection.tsx | 2 +- .../javascripts/Components/Tags/TagsList.tsx | 2 +- .../Components/Tags/TagsListItem.tsx | 2 +- .../Components/Tags/TagsSection.tsx | 2 +- .../Controllers/FilesController.ts | 2 +- .../ItemList/ItemListController.ts | 2 +- .../Navigation/NavigationController.ts | 2 +- .../Controllers/NoAccountWarningController.ts | 2 +- .../NoteHistory/NoteHistoryController.ts | 2 +- .../Controllers/NotesController.ts | 2 +- .../ViewControllerManager.ts | 36 ++-- .../Hooks/useListKeyboardNavigation.ts | 2 +- .../src/javascripts/Hooks/usePremiumModal.tsx | 2 +- packages/web/tsconfig.json | 3 +- yarn.lock | 47 ++++- 161 files changed, 1105 insertions(+), 824 deletions(-) create mode 100644 .yarn/cache/@standardnotes-common-npm-1.30.0-a603c54867-833b6e7f3e.zip delete mode 100644 packages/encryption/src/Domain/Backups/BackupFile.ts create mode 100644 packages/models/src/Domain/Abstract/Component/ActionObserver.ts create mode 100644 packages/models/src/Domain/Abstract/Component/ComponentEventObserver.ts create mode 100644 packages/models/src/Domain/Abstract/Component/ComponentMessage.ts create mode 100644 packages/models/src/Domain/Abstract/Component/ComponentViewerEvent.ts create mode 100644 packages/models/src/Domain/Abstract/Component/IncomingComponentItemPayload.ts create mode 100644 packages/models/src/Domain/Abstract/Component/KeyboardModifier.ts create mode 100644 packages/models/src/Domain/Abstract/Component/MessageData.ts create mode 100644 packages/models/src/Domain/Abstract/Component/PermissionDialog.ts create mode 100644 packages/models/src/Domain/Abstract/Contextual/BackupFileDecryptedContextualPayload.ts create mode 100644 packages/models/src/Domain/Abstract/Contextual/BackupFileEncryptedContextualPayload.ts create mode 100644 packages/models/src/Domain/Abstract/Contextual/Functions.ts delete mode 100644 packages/models/src/Domain/Abstract/Contextual/index.ts create mode 100644 packages/models/src/Domain/Abstract/Item/Mutator/TransactionalMutation.ts create mode 100644 packages/models/src/Domain/Abstract/Item/Types/ItemStream.ts create mode 100644 packages/services/src/Domain/Application/AppGroupManagedApplication.ts create mode 100644 packages/services/src/Domain/Application/WebApplicationInterface.ts create mode 100644 packages/services/src/Domain/Component/ComponentManagerInterface.ts create mode 100644 packages/services/src/Domain/Component/ComponentViewerError.ts create mode 100644 packages/services/src/Domain/Component/ComponentViewerInterface.ts create mode 100644 packages/services/src/Domain/Device/DesktopManagerInterface.ts create mode 100644 packages/services/src/Domain/Event/ApplicationEvent.ts create mode 100644 packages/services/src/Domain/Event/ApplicationEventCallback.ts rename packages/{web/src/javascripts/Application => services/src/Domain/Event}/WebAppEvent.ts (100%) create mode 100644 packages/services/src/Domain/Feature/FeatureStatus.ts rename packages/{snjs/lib/Services/Features/ClientInterface.ts => services/src/Domain/Feature/FeaturesClientInterface.ts} (89%) create mode 100644 packages/services/src/Domain/Feature/FeaturesEvent.ts create mode 100644 packages/services/src/Domain/Feature/OfflineSubscriptionEntitlements.ts create mode 100644 packages/services/src/Domain/Feature/SetOfflineFeaturesFunctionResponse.ts rename packages/{snjs/lib/Services/Items => services/src/Domain/Item}/ItemsClientInterface.ts (92%) create mode 100644 packages/services/src/Domain/Mutator/MutatorClientInterface.ts delete mode 100644 packages/snjs/lib/Services/Features/Types.ts delete mode 100644 packages/snjs/lib/Services/Items/TransactionalMutation.ts delete mode 100644 packages/snjs/lib/Services/Mutator/MutatorClientInterface.ts create mode 100644 packages/ui-services/.eslintignore create mode 100644 packages/ui-services/.eslintrc create mode 100644 packages/ui-services/.gitignore create mode 100644 packages/ui-services/jest.config.js create mode 100644 packages/ui-services/linter.tsconfig.json create mode 100644 packages/ui-services/package.json rename packages/{web/src/javascripts/Services/AlertService.ts => ui-services/src/Alert/Functions.ts} (62%) create mode 100644 packages/ui-services/src/Alert/WebAlertService.ts rename packages/{web/src/javascripts/Services => ui-services/src/Archive}/ArchiveManager.ts (97%) rename packages/{web/src/javascripts/Services => ui-services/src/IO}/IOService.ts (100%) rename packages/{web/src/javascripts/Services => ui-services/src/Security}/AutolockService.ts (100%) rename packages/{web/src/javascripts/Services => ui-services/src/Storage}/LocalStorage.ts (61%) rename packages/{web/src/javascripts/Services => ui-services/src/Theme}/ThemeManager.ts (98%) create mode 100644 packages/ui-services/src/index.ts create mode 100644 packages/ui-services/tsconfig.json rename packages/web/src/javascripts/{Services => Application/Device}/DesktopManager.ts (94%) rename packages/web/src/javascripts/{Services => Controllers}/ViewControllerManager.ts (82%) diff --git a/.yarn/cache/@standardnotes-common-npm-1.30.0-a603c54867-833b6e7f3e.zip b/.yarn/cache/@standardnotes-common-npm-1.30.0-a603c54867-833b6e7f3e.zip new file mode 100644 index 0000000000000000000000000000000000000000..b2fcc1f63d98994f040b181463e3101fb68c847f GIT binary patch literal 33936 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 void diff --git a/packages/models/src/Domain/Abstract/Component/ComponentEventObserver.ts b/packages/models/src/Domain/Abstract/Component/ComponentEventObserver.ts new file mode 100644 index 000000000..4eef6f3a3 --- /dev/null +++ b/packages/models/src/Domain/Abstract/Component/ComponentEventObserver.ts @@ -0,0 +1,3 @@ +import { ComponentViewerEvent } from './ComponentViewerEvent' + +export type ComponentEventObserver = (event: ComponentViewerEvent) => void diff --git a/packages/models/src/Domain/Abstract/Component/ComponentMessage.ts b/packages/models/src/Domain/Abstract/Component/ComponentMessage.ts new file mode 100644 index 000000000..fb818071d --- /dev/null +++ b/packages/models/src/Domain/Abstract/Component/ComponentMessage.ts @@ -0,0 +1,9 @@ +import { ComponentAction } from '@standardnotes/features' +import { MessageData } from './MessageData' + +export type ComponentMessage = { + action: ComponentAction + sessionKey?: string + componentData?: Record + data: MessageData +} diff --git a/packages/models/src/Domain/Abstract/Component/ComponentViewerEvent.ts b/packages/models/src/Domain/Abstract/Component/ComponentViewerEvent.ts new file mode 100644 index 000000000..b4ec5529c --- /dev/null +++ b/packages/models/src/Domain/Abstract/Component/ComponentViewerEvent.ts @@ -0,0 +1,3 @@ +export enum ComponentViewerEvent { + FeatureStatusUpdated = 'FeatureStatusUpdated', +} diff --git a/packages/models/src/Domain/Abstract/Component/IncomingComponentItemPayload.ts b/packages/models/src/Domain/Abstract/Component/IncomingComponentItemPayload.ts new file mode 100644 index 000000000..ec57a94e0 --- /dev/null +++ b/packages/models/src/Domain/Abstract/Component/IncomingComponentItemPayload.ts @@ -0,0 +1,5 @@ +import { DecryptedTransferPayload } from '../TransferPayload/Interfaces/DecryptedTransferPayload' + +export type IncomingComponentItemPayload = DecryptedTransferPayload & { + clientData: Record +} diff --git a/packages/models/src/Domain/Abstract/Component/KeyboardModifier.ts b/packages/models/src/Domain/Abstract/Component/KeyboardModifier.ts new file mode 100644 index 000000000..3160b4b6e --- /dev/null +++ b/packages/models/src/Domain/Abstract/Component/KeyboardModifier.ts @@ -0,0 +1,5 @@ +export enum KeyboardModifier { + Shift = 'Shift', + Ctrl = 'Control', + Meta = 'Meta', +} diff --git a/packages/models/src/Domain/Abstract/Component/MessageData.ts b/packages/models/src/Domain/Abstract/Component/MessageData.ts new file mode 100644 index 000000000..e18ef5782 --- /dev/null +++ b/packages/models/src/Domain/Abstract/Component/MessageData.ts @@ -0,0 +1,31 @@ +import { ContentType, Uuid } from '@standardnotes/common' +import { ComponentPermission } from '@standardnotes/features' + +import { IncomingComponentItemPayload } from './IncomingComponentItemPayload' +import { KeyboardModifier } from './KeyboardModifier' + +export type MessageData = Partial<{ + /** Related to the stream-item-context action */ + item?: IncomingComponentItemPayload + /** Related to the stream-items action */ + content_types?: ContentType[] + items?: IncomingComponentItemPayload[] + /** Related to the request-permission action */ + permissions?: ComponentPermission[] + /** Related to the component-registered action */ + componentData?: Record + uuid?: Uuid + environment?: string + platform?: string + activeThemeUrls?: string[] + /** Related to set-size action */ + width?: string | number + height?: string | number + type?: string + /** Related to themes action */ + themes?: string[] + /** Related to clear-selection action */ + content_type?: ContentType + /** Related to key-pressed action */ + keyboardModifier?: KeyboardModifier +}> diff --git a/packages/models/src/Domain/Abstract/Component/PermissionDialog.ts b/packages/models/src/Domain/Abstract/Component/PermissionDialog.ts new file mode 100644 index 000000000..e9bedea0e --- /dev/null +++ b/packages/models/src/Domain/Abstract/Component/PermissionDialog.ts @@ -0,0 +1,10 @@ +import { ComponentPermission } from '@standardnotes/features' +import { SNComponent } from '../../Syncable/Component' + +export type PermissionDialog = { + component: SNComponent + permissions: ComponentPermission[] + permissionsString: string + actionBlock: (approved: boolean) => void + callback: (approved: boolean) => void +} diff --git a/packages/models/src/Domain/Abstract/Contextual/BackupFile.ts b/packages/models/src/Domain/Abstract/Contextual/BackupFile.ts index 87b4bc6be..bcf7110dd 100644 --- a/packages/models/src/Domain/Abstract/Contextual/BackupFile.ts +++ b/packages/models/src/Domain/Abstract/Contextual/BackupFile.ts @@ -1,60 +1,10 @@ -import { Uuid } from '@standardnotes/common' -import { ContextPayload } from './ContextPayload' -import { ItemContent } from '../Content/ItemContent' -import { DecryptedTransferPayload, EncryptedTransferPayload } from '../TransferPayload' +import { AnyKeyParamsContent, ProtocolVersion } from '@standardnotes/common' +import { BackupFileDecryptedContextualPayload } from './BackupFileDecryptedContextualPayload' +import { BackupFileEncryptedContextualPayload } from './BackupFileEncryptedContextualPayload' -export interface BackupFileEncryptedContextualPayload extends ContextPayload { - auth_hash?: string - content: string - created_at_timestamp: number - created_at: Date - duplicate_of?: Uuid - enc_item_key: string - items_key_id: string | undefined - updated_at: Date - updated_at_timestamp: number -} - -export interface BackupFileDecryptedContextualPayload extends ContextPayload { - content: C - created_at_timestamp: number - created_at: Date - duplicate_of?: Uuid - updated_at: Date - updated_at_timestamp: number -} - -export function CreateEncryptedBackupFileContextPayload( - fromPayload: EncryptedTransferPayload, -): BackupFileEncryptedContextualPayload { - return { - auth_hash: fromPayload.auth_hash, - content_type: fromPayload.content_type, - content: fromPayload.content, - created_at_timestamp: fromPayload.created_at_timestamp, - created_at: fromPayload.created_at, - deleted: false, - duplicate_of: fromPayload.duplicate_of, - enc_item_key: fromPayload.enc_item_key, - items_key_id: fromPayload.items_key_id, - updated_at_timestamp: fromPayload.updated_at_timestamp, - updated_at: fromPayload.updated_at, - uuid: fromPayload.uuid, - } -} - -export function CreateDecryptedBackupFileContextPayload( - fromPayload: DecryptedTransferPayload, -): BackupFileDecryptedContextualPayload { - return { - content_type: fromPayload.content_type, - content: fromPayload.content, - created_at_timestamp: fromPayload.created_at_timestamp, - created_at: fromPayload.created_at, - deleted: false, - duplicate_of: fromPayload.duplicate_of, - updated_at_timestamp: fromPayload.updated_at_timestamp, - updated_at: fromPayload.updated_at, - uuid: fromPayload.uuid, - } +export type BackupFile = { + version?: ProtocolVersion + keyParams?: AnyKeyParamsContent + auth_params?: AnyKeyParamsContent + items: (BackupFileDecryptedContextualPayload | BackupFileEncryptedContextualPayload)[] } diff --git a/packages/models/src/Domain/Abstract/Contextual/BackupFileDecryptedContextualPayload.ts b/packages/models/src/Domain/Abstract/Contextual/BackupFileDecryptedContextualPayload.ts new file mode 100644 index 000000000..9de4eadde --- /dev/null +++ b/packages/models/src/Domain/Abstract/Contextual/BackupFileDecryptedContextualPayload.ts @@ -0,0 +1,12 @@ +import { Uuid } from '@standardnotes/common' +import { ItemContent } from '../Content/ItemContent' +import { ContextPayload } from './ContextPayload' + +export interface BackupFileDecryptedContextualPayload extends ContextPayload { + content: C + created_at_timestamp: number + created_at: Date + duplicate_of?: Uuid + updated_at: Date + updated_at_timestamp: number +} diff --git a/packages/models/src/Domain/Abstract/Contextual/BackupFileEncryptedContextualPayload.ts b/packages/models/src/Domain/Abstract/Contextual/BackupFileEncryptedContextualPayload.ts new file mode 100644 index 000000000..28ea876f2 --- /dev/null +++ b/packages/models/src/Domain/Abstract/Contextual/BackupFileEncryptedContextualPayload.ts @@ -0,0 +1,14 @@ +import { Uuid } from '@standardnotes/common' +import { ContextPayload } from './ContextPayload' + +export interface BackupFileEncryptedContextualPayload extends ContextPayload { + auth_hash?: string + content: string + created_at_timestamp: number + created_at: Date + duplicate_of?: Uuid + enc_item_key: string + items_key_id: string | undefined + updated_at: Date + updated_at_timestamp: number +} diff --git a/packages/models/src/Domain/Abstract/Contextual/Functions.ts b/packages/models/src/Domain/Abstract/Contextual/Functions.ts new file mode 100644 index 000000000..3fd55da51 --- /dev/null +++ b/packages/models/src/Domain/Abstract/Contextual/Functions.ts @@ -0,0 +1,39 @@ +import { DecryptedTransferPayload, EncryptedTransferPayload } from '../TransferPayload' + +import { BackupFileDecryptedContextualPayload } from './BackupFileDecryptedContextualPayload' +import { BackupFileEncryptedContextualPayload } from './BackupFileEncryptedContextualPayload' + +export function CreateEncryptedBackupFileContextPayload( + fromPayload: EncryptedTransferPayload, +): BackupFileEncryptedContextualPayload { + return { + auth_hash: fromPayload.auth_hash, + content_type: fromPayload.content_type, + content: fromPayload.content, + created_at_timestamp: fromPayload.created_at_timestamp, + created_at: fromPayload.created_at, + deleted: false, + duplicate_of: fromPayload.duplicate_of, + enc_item_key: fromPayload.enc_item_key, + items_key_id: fromPayload.items_key_id, + updated_at_timestamp: fromPayload.updated_at_timestamp, + updated_at: fromPayload.updated_at, + uuid: fromPayload.uuid, + } +} + +export function CreateDecryptedBackupFileContextPayload( + fromPayload: DecryptedTransferPayload, +): BackupFileDecryptedContextualPayload { + return { + content_type: fromPayload.content_type, + content: fromPayload.content, + created_at_timestamp: fromPayload.created_at_timestamp, + created_at: fromPayload.created_at, + deleted: false, + duplicate_of: fromPayload.duplicate_of, + updated_at_timestamp: fromPayload.updated_at_timestamp, + updated_at: fromPayload.updated_at, + uuid: fromPayload.uuid, + } +} diff --git a/packages/models/src/Domain/Abstract/Contextual/index.ts b/packages/models/src/Domain/Abstract/Contextual/index.ts deleted file mode 100644 index b6a0ab3e6..000000000 --- a/packages/models/src/Domain/Abstract/Contextual/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export * from './ComponentCreate' -export * from './ComponentRetrieved' -export * from './BackupFile' -export * from './LocalStorage' -export * from './OfflineSyncPush' -export * from './OfflineSyncSaved' -export * from './ServerSyncPush' -export * from './SessionHistory' -export * from './ServerSyncSaved' -export * from './FilteredServerItem' diff --git a/packages/models/src/Domain/Abstract/Item/Mutator/TransactionalMutation.ts b/packages/models/src/Domain/Abstract/Item/Mutator/TransactionalMutation.ts new file mode 100644 index 000000000..c484fb0bd --- /dev/null +++ b/packages/models/src/Domain/Abstract/Item/Mutator/TransactionalMutation.ts @@ -0,0 +1,11 @@ +import { Uuid } from '@standardnotes/common' + +import { MutationType } from '../Types/MutationType' + +import { ItemMutator } from './ItemMutator' + +export type TransactionalMutation = { + itemUuid: Uuid + mutate: (mutator: ItemMutator) => void + mutationType?: MutationType +} diff --git a/packages/models/src/Domain/Abstract/Item/Types/ItemStream.ts b/packages/models/src/Domain/Abstract/Item/Types/ItemStream.ts new file mode 100644 index 000000000..730f8263d --- /dev/null +++ b/packages/models/src/Domain/Abstract/Item/Types/ItemStream.ts @@ -0,0 +1,11 @@ +import { PayloadEmitSource } from '../../Payload' +import { DecryptedItemInterface } from '../Interfaces/DecryptedItem' +import { DeletedItemInterface } from '../Interfaces/DeletedItem' +import { EncryptedItemInterface } from '../Interfaces/EncryptedItem' + +export type ItemStream = (data: { + changed: I[] + inserted: I[] + removed: (DeletedItemInterface | EncryptedItemInterface)[] + source: PayloadEmitSource +}) => void diff --git a/packages/models/src/Domain/Abstract/Item/index.ts b/packages/models/src/Domain/Abstract/Item/index.ts index 99509324b..68ceeacf8 100644 --- a/packages/models/src/Domain/Abstract/Item/index.ts +++ b/packages/models/src/Domain/Abstract/Item/index.ts @@ -20,10 +20,10 @@ export * from './Interfaces/TypeCheck' export * from './Mutator/DecryptedItemMutator' export * from './Mutator/DeleteMutator' export * from './Mutator/ItemMutator' -export * from './Types/AppDataField' +export * from './Mutator/TransactionalMutation' export * from './Types/AppDataField' export * from './Types/ConflictStrategy' export * from './Types/DefaultAppDomain' -export * from './Types/DefaultAppDomain' +export * from './Types/ItemStream' export * from './Types/MutationType' export * from './Types/SingletonStrategy' diff --git a/packages/models/src/Domain/index.ts b/packages/models/src/Domain/index.ts index a11b7ce49..1b1f49f76 100644 --- a/packages/models/src/Domain/index.ts +++ b/packages/models/src/Domain/index.ts @@ -1,5 +1,26 @@ +export * from './Abstract/Component/ActionObserver' +export * from './Abstract/Component/ComponentViewerEvent' +export * from './Abstract/Component/ComponentMessage' +export * from './Abstract/Component/ComponentEventObserver' +export * from './Abstract/Component/IncomingComponentItemPayload' +export * from './Abstract/Component/KeyboardModifier' +export * from './Abstract/Component/MessageData' +export * from './Abstract/Component/PermissionDialog' export * from './Abstract/Content/ItemContent' -export * from './Abstract/Contextual' +export * from './Abstract/Contextual/BackupFile' +export * from './Abstract/Contextual/BackupFileDecryptedContextualPayload' +export * from './Abstract/Contextual/BackupFileEncryptedContextualPayload' +export * from './Abstract/Contextual/ComponentCreate' +export * from './Abstract/Contextual/ComponentRetrieved' +export * from './Abstract/Contextual/ContextPayload' +export * from './Abstract/Contextual/FilteredServerItem' +export * from './Abstract/Contextual/Functions' +export * from './Abstract/Contextual/LocalStorage' +export * from './Abstract/Contextual/OfflineSyncPush' +export * from './Abstract/Contextual/OfflineSyncSaved' +export * from './Abstract/Contextual/ServerSyncPush' +export * from './Abstract/Contextual/ServerSyncSaved' +export * from './Abstract/Contextual/SessionHistory' export * from './Abstract/Item' export * from './Abstract/Payload' export * from './Abstract/TransferPayload' diff --git a/packages/services/package.json b/packages/services/package.json index 5521fc055..48eb9ec5b 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -24,8 +24,8 @@ }, "dependencies": { "@standardnotes/auth": "^3.19.4", - "@standardnotes/common": "^1.23.1", - "@standardnotes/models": "workspace:*", + "@standardnotes/common": "^1.30.0", + "@standardnotes/models": "workspace:^", "@standardnotes/responses": "workspace:*", "@standardnotes/security": "^1.2.0", "@standardnotes/utils": "workspace:*", diff --git a/packages/services/src/Domain/Application/AppGroupManagedApplication.ts b/packages/services/src/Domain/Application/AppGroupManagedApplication.ts new file mode 100644 index 000000000..6d3167774 --- /dev/null +++ b/packages/services/src/Domain/Application/AppGroupManagedApplication.ts @@ -0,0 +1,7 @@ +import { ApplicationInterface } from './ApplicationInterface' +import { DeinitCallback } from './DeinitCallback' + +export interface AppGroupManagedApplication extends ApplicationInterface { + onDeinit: DeinitCallback + setOnDeinit(onDeinit: DeinitCallback): void +} diff --git a/packages/services/src/Domain/Application/ApplicationInterface.ts b/packages/services/src/Domain/Application/ApplicationInterface.ts index 6f7875484..848173b30 100644 --- a/packages/services/src/Domain/Application/ApplicationInterface.ts +++ b/packages/services/src/Domain/Application/ApplicationInterface.ts @@ -1,22 +1,44 @@ -import { ApplicationIdentifier } from '@standardnotes/common' +import { ApplicationIdentifier, ContentType } from '@standardnotes/common' +import { BackupFile, DecryptedItemInterface, ItemStream, PrefKey, PrefValue } from '@standardnotes/models' + +import { ComponentManagerInterface } from '../Component/ComponentManagerInterface' +import { ApplicationEvent } from '../Event/ApplicationEvent' +import { ApplicationEventCallback } from '../Event/ApplicationEventCallback' +import { FeaturesClientInterface } from '../Feature/FeaturesClientInterface' +import { ItemsClientInterface } from '../Item/ItemsClientInterface' +import { MutatorClientInterface } from '../Mutator/MutatorClientInterface' +import { StorageValueModes } from '../Storage/StorageTypes' -import { DeinitCallback } from './DeinitCallback' import { DeinitMode } from './DeinitMode' import { DeinitSource } from './DeinitSource' import { UserClientInterface } from './UserClientInterface' export interface ApplicationInterface { deinit(mode: DeinitMode, source: DeinitSource): void - getDeinitMode(): DeinitMode - + isStarted(): boolean + isLaunched(): boolean + addEventObserver(callback: ApplicationEventCallback, singleEvent?: ApplicationEvent): () => void + hasProtectionSources(): boolean + createEncryptedBackupFileForAutomatedDesktopBackups(): Promise + createDecryptedBackupFile(): Promise + hasPasscode(): boolean + lock(): Promise + setValue(key: string, value: unknown, mode?: StorageValueModes): void + getValue(key: string, mode?: StorageValueModes): unknown + removeValue(key: string, mode?: StorageValueModes): Promise + isLocked(): Promise + getPreference(key: K): PrefValue[K] | undefined + getPreference(key: K, defaultValue: PrefValue[K]): PrefValue[K] + getPreference(key: K, defaultValue?: PrefValue[K]): PrefValue[K] | undefined + streamItems( + contentType: ContentType | ContentType[], + stream: ItemStream, + ): () => void + get features(): FeaturesClientInterface + get componentManager(): ComponentManagerInterface + get items(): ItemsClientInterface + get mutator(): MutatorClientInterface get user(): UserClientInterface - readonly identifier: ApplicationIdentifier } - -export interface AppGroupManagedApplication extends ApplicationInterface { - onDeinit: DeinitCallback - - setOnDeinit(onDeinit: DeinitCallback): void -} diff --git a/packages/services/src/Domain/Application/DeinitCallback.ts b/packages/services/src/Domain/Application/DeinitCallback.ts index b7a72abc0..82810771e 100644 --- a/packages/services/src/Domain/Application/DeinitCallback.ts +++ b/packages/services/src/Domain/Application/DeinitCallback.ts @@ -1,5 +1,5 @@ import { DeinitSource } from './DeinitSource' import { DeinitMode } from './DeinitMode' -import { AppGroupManagedApplication } from './ApplicationInterface' +import { AppGroupManagedApplication } from './AppGroupManagedApplication' export type DeinitCallback = (application: AppGroupManagedApplication, mode: DeinitMode, source: DeinitSource) => void diff --git a/packages/services/src/Domain/Application/WebApplicationInterface.ts b/packages/services/src/Domain/Application/WebApplicationInterface.ts new file mode 100644 index 000000000..7d2512a72 --- /dev/null +++ b/packages/services/src/Domain/Application/WebApplicationInterface.ts @@ -0,0 +1,8 @@ +import { DesktopManagerInterface } from '../Device/DesktopManagerInterface' +import { WebAppEvent } from '../Event/WebAppEvent' +import { ApplicationInterface } from './ApplicationInterface' + +export interface WebApplicationInterface extends ApplicationInterface { + notifyWebEvent(event: WebAppEvent, data?: unknown): void + getDesktopService(): DesktopManagerInterface | undefined +} diff --git a/packages/services/src/Domain/Component/ComponentManagerInterface.ts b/packages/services/src/Domain/Component/ComponentManagerInterface.ts new file mode 100644 index 000000000..cc6e91b15 --- /dev/null +++ b/packages/services/src/Domain/Component/ComponentManagerInterface.ts @@ -0,0 +1,23 @@ +import { Uuid } from '@standardnotes/common' +import { ComponentArea } from '@standardnotes/features' +import { ActionObserver, PermissionDialog, SNComponent, SNNote } from '@standardnotes/models' + +import { DesktopManagerInterface } from '../Device/DesktopManagerInterface' +import { ComponentViewerInterface } from './ComponentViewerInterface' + +export interface ComponentManagerInterface { + urlForComponent(component: SNComponent): string | undefined + setDesktopManager(desktopManager: DesktopManagerInterface): void + componentsForArea(area: ComponentArea): SNComponent[] + editorForNote(note: SNNote): SNComponent | undefined + doesEditorChangeRequireAlert(from: SNComponent | undefined, to: SNComponent | undefined): boolean + showEditorChangeAlert(): Promise + destroyComponentViewer(viewer: ComponentViewerInterface): void + createComponentViewer( + component: SNComponent, + contextItem?: Uuid, + actionObserver?: ActionObserver, + urlOverride?: string, + ): ComponentViewerInterface + presentPermissionsDialog(_dialog: PermissionDialog): void +} diff --git a/packages/services/src/Domain/Component/ComponentViewerError.ts b/packages/services/src/Domain/Component/ComponentViewerError.ts new file mode 100644 index 000000000..43a03fb61 --- /dev/null +++ b/packages/services/src/Domain/Component/ComponentViewerError.ts @@ -0,0 +1,4 @@ +export enum ComponentViewerError { + OfflineRestricted = 'OfflineRestricted', + MissingUrl = 'MissingUrl', +} diff --git a/packages/services/src/Domain/Component/ComponentViewerInterface.ts b/packages/services/src/Domain/Component/ComponentViewerInterface.ts new file mode 100644 index 000000000..acaee599e --- /dev/null +++ b/packages/services/src/Domain/Component/ComponentViewerInterface.ts @@ -0,0 +1,29 @@ +import { + ActionObserver, + ComponentEventObserver, + ComponentMessage, + DecryptedItemInterface, + SNComponent, +} from '@standardnotes/models' +import { FeatureStatus } from '../Feature/FeatureStatus' +import { ComponentViewerError } from './ComponentViewerError' + +export interface ComponentViewerInterface { + readonly component: SNComponent + readonly url?: string + identifier: string + lockReadonly: boolean + sessionKey?: string + overrideContextItem?: DecryptedItemInterface + get componentUuid(): string + destroy(): void + setReadonly(readonly: boolean): void + getFeatureStatus(): FeatureStatus + shouldRender(): boolean + getError(): ComponentViewerError | undefined + setWindow(window: Window): void + addEventObserver(observer: ComponentEventObserver): () => void + addActionObserver(observer: ActionObserver): () => void + postActiveThemes(): void + handleMessage(message: ComponentMessage): void +} diff --git a/packages/services/src/Domain/Device/DesktopManagerInterface.ts b/packages/services/src/Domain/Device/DesktopManagerInterface.ts new file mode 100644 index 000000000..aa3c81ad8 --- /dev/null +++ b/packages/services/src/Domain/Device/DesktopManagerInterface.ts @@ -0,0 +1,7 @@ +import { SNComponent } from '@standardnotes/models' + +export interface DesktopManagerInterface { + syncComponentsInstallation(components: SNComponent[]): void + registerUpdateObserver(callback: (component: SNComponent) => void): () => void + getExtServerHost(): string +} diff --git a/packages/services/src/Domain/Event/ApplicationEvent.ts b/packages/services/src/Domain/Event/ApplicationEvent.ts new file mode 100644 index 000000000..0c814fe21 --- /dev/null +++ b/packages/services/src/Domain/Event/ApplicationEvent.ts @@ -0,0 +1,65 @@ +export enum ApplicationEvent { + SignedIn = 2, + SignedOut = 3, + + /** When a full, potentially multi-page sync completes */ + CompletedFullSync = 5, + + FailedSync = 6, + HighLatencySync = 7, + EnteredOutOfSync = 8, + ExitedOutOfSync = 9, + + /** + * The application has finished it `prepareForLaunch` state and is now ready for unlock + * Called when the application has initialized and is ready for launch, but before + * the application has been unlocked, if applicable. Use this to do pre-launch + * configuration, but do not attempt to access user data like notes or tags. + */ + Started = 10, + + /** + * The applicaiton is fully unlocked and ready for i/o + * Called when the application has been fully decrypted and unlocked. Use this to + * to begin streaming data like notes and tags. + */ + Launched = 11, + LocalDataLoaded = 12, + + /** + * When the root key or root key wrapper changes. Includes events like account state + * changes (registering, signing in, changing pw, logging out) and passcode state + * changes (adding, removing, changing). + */ + KeyStatusChanged = 13, + + MajorDataChange = 14, + CompletedRestart = 15, + LocalDataIncrementalLoad = 16, + SyncStatusChanged = 17, + WillSync = 18, + InvalidSyncSession = 19, + LocalDatabaseReadError = 20, + LocalDatabaseWriteError = 21, + + /** When a single roundtrip completes with sync, in a potentially multi-page sync request. + * If just a single roundtrip, this event will be triggered, along with CompletedFullSync */ + CompletedIncrementalSync = 22, + + /** + * The application has loaded all pending migrations (but not run any, except for the base one), + * and consumers may now call `hasPendingMigrations` + */ + MigrationsLoaded = 23, + + /** When StorageService is ready to start servicing read/write requests */ + StorageReady = 24, + + PreferencesChanged = 25, + UnprotectedSessionBegan = 26, + UserRolesChanged = 27, + FeaturesUpdated = 28, + UnprotectedSessionExpired = 29, + /** Called when the app first launches and after first sync request made after sign in */ + CompletedInitialSync = 30, +} diff --git a/packages/services/src/Domain/Event/ApplicationEventCallback.ts b/packages/services/src/Domain/Event/ApplicationEventCallback.ts new file mode 100644 index 000000000..eba7e5fdf --- /dev/null +++ b/packages/services/src/Domain/Event/ApplicationEventCallback.ts @@ -0,0 +1,3 @@ +import { ApplicationEvent } from './ApplicationEvent' + +export type ApplicationEventCallback = (event: ApplicationEvent, data?: unknown) => Promise diff --git a/packages/web/src/javascripts/Application/WebAppEvent.ts b/packages/services/src/Domain/Event/WebAppEvent.ts similarity index 100% rename from packages/web/src/javascripts/Application/WebAppEvent.ts rename to packages/services/src/Domain/Event/WebAppEvent.ts diff --git a/packages/services/src/Domain/Feature/FeatureStatus.ts b/packages/services/src/Domain/Feature/FeatureStatus.ts new file mode 100644 index 000000000..5b276d5d0 --- /dev/null +++ b/packages/services/src/Domain/Feature/FeatureStatus.ts @@ -0,0 +1,6 @@ +export enum FeatureStatus { + NoUserSubscription = 'NoUserSubscription', + NotInCurrentPlan = 'NotInCurrentPlan', + InCurrentPlanButExpired = 'InCurrentPlanButExpired', + Entitled = 'Entitled', +} diff --git a/packages/snjs/lib/Services/Features/ClientInterface.ts b/packages/services/src/Domain/Feature/FeaturesClientInterface.ts similarity index 89% rename from packages/snjs/lib/Services/Features/ClientInterface.ts rename to packages/services/src/Domain/Feature/FeaturesClientInterface.ts index 82f223da0..39ddd8bdc 100644 --- a/packages/snjs/lib/Services/Features/ClientInterface.ts +++ b/packages/services/src/Domain/Feature/FeaturesClientInterface.ts @@ -1,8 +1,10 @@ -import { FeatureStatus, SetOfflineFeaturesFunctionResponse } from './Types' import { FeatureDescription, FeatureIdentifier } from '@standardnotes/features' import { SNComponent } from '@standardnotes/models' import { RoleName } from '@standardnotes/common' +import { FeatureStatus } from './FeatureStatus' +import { SetOfflineFeaturesFunctionResponse } from './SetOfflineFeaturesFunctionResponse' + export interface FeaturesClientInterface { downloadExternalFeature(urlOrCode: string): Promise diff --git a/packages/services/src/Domain/Feature/FeaturesEvent.ts b/packages/services/src/Domain/Feature/FeaturesEvent.ts new file mode 100644 index 000000000..75595699a --- /dev/null +++ b/packages/services/src/Domain/Feature/FeaturesEvent.ts @@ -0,0 +1,4 @@ +export enum FeaturesEvent { + UserRolesChanged = 'UserRolesChanged', + FeaturesUpdated = 'FeaturesUpdated', +} diff --git a/packages/services/src/Domain/Feature/OfflineSubscriptionEntitlements.ts b/packages/services/src/Domain/Feature/OfflineSubscriptionEntitlements.ts new file mode 100644 index 000000000..a2ce448e1 --- /dev/null +++ b/packages/services/src/Domain/Feature/OfflineSubscriptionEntitlements.ts @@ -0,0 +1,4 @@ +export type OfflineSubscriptionEntitlements = { + featuresUrl: string + extensionKey: string +} diff --git a/packages/services/src/Domain/Feature/SetOfflineFeaturesFunctionResponse.ts b/packages/services/src/Domain/Feature/SetOfflineFeaturesFunctionResponse.ts new file mode 100644 index 000000000..1dab8a477 --- /dev/null +++ b/packages/services/src/Domain/Feature/SetOfflineFeaturesFunctionResponse.ts @@ -0,0 +1,3 @@ +import { ClientDisplayableError } from '@standardnotes/responses' + +export type SetOfflineFeaturesFunctionResponse = ClientDisplayableError | undefined diff --git a/packages/snjs/lib/Services/Items/ItemsClientInterface.ts b/packages/services/src/Domain/Item/ItemsClientInterface.ts similarity index 92% rename from packages/snjs/lib/Services/Items/ItemsClientInterface.ts rename to packages/services/src/Domain/Item/ItemsClientInterface.ts index b6324f593..c137d6519 100644 --- a/packages/snjs/lib/Services/Items/ItemsClientInterface.ts +++ b/packages/services/src/Domain/Item/ItemsClientInterface.ts @@ -1,5 +1,4 @@ -import { SNItemsKey } from '@standardnotes/encryption' -import { ContentType } from '@standardnotes/common' +import { ContentType, Uuid } from '@standardnotes/common' import { SNNote, FileItem, @@ -14,8 +13,8 @@ import { SNComponent, SNTheme, DisplayOptions, + ItemsKeyInterface, } from '@standardnotes/models' -import { UuidString } from '@Lib/Types' export interface ItemsClientInterface { get invalidItems(): EncryptedItemInterface[] @@ -43,7 +42,7 @@ export interface ItemsClientInterface { getDisplayableTags(): SNTag[] - getDisplayableItemsKeys(): SNItemsKey[] + getDisplayableItemsKeys(): ItemsKeyInterface[] getDisplayableFiles(): FileItem[] @@ -116,14 +115,14 @@ export interface ItemsClientInterface { /** * Finds an item by UUID. */ - findItem(uuid: UuidString): T | undefined + findItem(uuid: Uuid): T | undefined /** * Finds an item by predicate. */ - findItems(uuids: UuidString[]): T[] + findItems(uuids: Uuid[]): T[] - findSureItem(uuid: UuidString): T + findSureItem(uuid: Uuid): T /** * Finds an item by predicate. diff --git a/packages/services/src/Domain/Mutator/MutatorClientInterface.ts b/packages/services/src/Domain/Mutator/MutatorClientInterface.ts new file mode 100644 index 000000000..0a9ebb5be --- /dev/null +++ b/packages/services/src/Domain/Mutator/MutatorClientInterface.ts @@ -0,0 +1,184 @@ +import { ContentType } from '@standardnotes/common' +import { + BackupFile, + DecryptedItemInterface, + DecryptedItemMutator, + EncryptedItemInterface, + FileItem, + ItemContent, + PayloadEmitSource, + SmartView, + SNComponent, + SNNote, + SNTag, + TransactionalMutation, +} from '@standardnotes/models' +import { ClientDisplayableError } from '@standardnotes/responses' + +import { ChallengeReason } from '../Challenge/Types/ChallengeReason' +import { SyncOptions } from '../Sync/SyncOptions' + +export interface MutatorClientInterface { + /** + * Inserts the input item by its payload properties, and marks the item as dirty. + * A sync is not performed after an item is inserted. This must be handled by the caller. + */ + insertItem(item: DecryptedItemInterface): Promise + + /** + * Mutates a pre-existing item, marks it as dirty, and syncs it + */ + changeAndSaveItem( + itemToLookupUuidFor: DecryptedItemInterface, + mutate: (mutator: M) => void, + updateTimestamps?: boolean, + emitSource?: PayloadEmitSource, + syncOptions?: SyncOptions, + ): Promise + + /** + * Mutates pre-existing items, marks them as dirty, and syncs + */ + changeAndSaveItems( + itemsToLookupUuidsFor: DecryptedItemInterface[], + mutate: (mutator: M) => void, + updateTimestamps?: boolean, + emitSource?: PayloadEmitSource, + syncOptions?: SyncOptions, + ): Promise + + /** + * Mutates a pre-existing item and marks it as dirty. Does not sync changes. + */ + changeItem( + itemToLookupUuidFor: DecryptedItemInterface, + mutate: (mutator: M) => void, + updateTimestamps?: boolean, + ): Promise + + /** + * Mutates a pre-existing items and marks them as dirty. Does not sync changes. + */ + changeItems( + itemsToLookupUuidsFor: DecryptedItemInterface[], + mutate: (mutator: M) => void, + updateTimestamps?: boolean, + ): Promise<(DecryptedItemInterface | undefined)[]> + + /** + * Run unique mutations per each item in the array, then only propagate all changes + * once all mutations have been run. This differs from `changeItems` in that changeItems + * runs the same mutation on all items. + */ + runTransactionalMutations( + transactions: TransactionalMutation[], + emitSource?: PayloadEmitSource, + payloadSourceKey?: string, + ): Promise<(DecryptedItemInterface | undefined)[]> + + runTransactionalMutation( + transaction: TransactionalMutation, + emitSource?: PayloadEmitSource, + payloadSourceKey?: string, + ): Promise + + protectItems<_M extends DecryptedItemMutator, I extends DecryptedItemInterface>( + items: I[], + ): Promise + + unprotectItems<_M extends DecryptedItemMutator, I extends DecryptedItemInterface>( + items: I[], + reason: ChallengeReason, + ): Promise + + protectNote(note: SNNote): Promise + + unprotectNote(note: SNNote): Promise + + protectNotes(notes: SNNote[]): Promise + + unprotectNotes(notes: SNNote[]): Promise + + protectFile(file: FileItem): Promise + + unprotectFile(file: FileItem): Promise + + /** + * Takes the values of the input item and emits it onto global state. + */ + mergeItem(item: DecryptedItemInterface, source: PayloadEmitSource): Promise + + /** + * Creates an unmanaged item that can be added later. + */ + createTemplateItem< + C extends ItemContent = ItemContent, + I extends DecryptedItemInterface = DecryptedItemInterface, + >( + contentType: ContentType, + content?: C, + ): I + + /** + * @param isUserModified Whether to change the modified date the user + * sees of the item. + */ + setItemNeedsSync(item: DecryptedItemInterface, isUserModified?: boolean): Promise + + setItemsNeedsSync(items: DecryptedItemInterface[]): Promise<(DecryptedItemInterface | undefined)[]> + + deleteItem(item: DecryptedItemInterface | EncryptedItemInterface): Promise + + deleteItems(items: (DecryptedItemInterface | EncryptedItemInterface)[]): Promise + + emptyTrash(): Promise + + duplicateItem(item: T, additionalContent?: Partial): Promise + + /** + * Migrates any tags containing a '.' character to sa chema-based heirarchy, removing + * the dot from the tag's title. + */ + migrateTagsToFolders(): Promise + + /** + * Establishes a hierarchical relationship between two tags. + */ + setTagParent(parentTag: SNTag, childTag: SNTag): Promise + + /** + * Remove the tag parent. + */ + unsetTagParent(childTag: SNTag): Promise + + findOrCreateTag(title: string): Promise + + /** Creates and returns the tag but does not run sync. Callers must perform sync. */ + createTagOrSmartView(title: string): Promise + + /** + * Activates or deactivates a component, depending on its + * current state, and syncs. + */ + toggleComponent(component: SNComponent): Promise + + toggleTheme(theme: SNComponent): Promise + + /** + * @returns + * .affectedItems: Items that were either created or dirtied by this import + * .errorCount: The number of items that were not imported due to failure to decrypt. + */ + importData( + data: BackupFile, + awaitSync?: boolean, + ): Promise< + | { + affectedItems: DecryptedItemInterface[] + errorCount: number + } + | { + error: ClientDisplayableError + } + > +} diff --git a/packages/services/src/Domain/index.ts b/packages/services/src/Domain/index.ts index 241e7624d..7fe53f1a5 100644 --- a/packages/services/src/Domain/index.ts +++ b/packages/services/src/Domain/index.ts @@ -1,13 +1,19 @@ export * from './Alert/AlertService' export * from './Api/ApiServiceInterface' +export * from './Application/AppGroupManagedApplication' +export * from './Application/ApplicationInterface' export * from './Application/ApplicationStage' export * from './Application/DeinitCallback' export * from './Application/DeinitSource' export * from './Application/DeinitMode' export * from './Application/UserClientInterface' -export * from './Application/ApplicationInterface' +export * from './Application/WebApplicationInterface' export * from './Challenge' +export * from './Component/ComponentManagerInterface' +export * from './Component/ComponentViewerError' +export * from './Component/ComponentViewerInterface' export * from './Device/DesktopDeviceInterface' +export * from './Device/DesktopManagerInterface' export * from './Device/DesktopWebCommunication' export * from './Device/DeviceInterface' export * from './Device/Environments' @@ -16,9 +22,17 @@ export * from './Device/MobileDeviceInterface' export * from './Device/TypeCheck' export * from './Device/WebOrDesktopDeviceInterface' export * from './Diagnostics/ServiceDiagnostics' +export * from './Event/ApplicationEvent' +export * from './Event/ApplicationEventCallback' export * from './Event/EventObserver' export * from './Event/SyncEvent' export * from './Event/SyncEventReceiver' +export * from './Event/WebAppEvent' +export * from './Feature/FeatureStatus' +export * from './Feature/FeaturesClientInterface' +export * from './Feature/FeaturesEvent' +export * from './Feature/OfflineSubscriptionEntitlements' +export * from './Feature/SetOfflineFeaturesFunctionResponse' export * from './Files/FilesApiInterface' export * from './FileSystem/FileSystemApi' export * from './Integrity/IntegrityApiInterface' @@ -32,7 +46,9 @@ export * from './Internal/InternalEventInterface' export * from './Internal/InternalEventPublishStrategy' export * from './Internal/InternalEventType' export * from './Item/ItemManagerInterface' +export * from './Item/ItemsClientInterface' export * from './Item/ItemsServerInterface' +export * from './Mutator/MutatorClientInterface' export * from './Payloads/PayloadManagerInterface' export * from './Preferences/PreferenceServiceInterface' export * from './Service/AbstractService' diff --git a/packages/snjs/lib/Application/Application.ts b/packages/snjs/lib/Application/Application.ts index 5219343a9..1f438f957 100644 --- a/packages/snjs/lib/Application/Application.ts +++ b/packages/snjs/lib/Application/Application.ts @@ -19,9 +19,12 @@ import * as Settings from '@standardnotes/settings' import * as Files from '@standardnotes/files' import { Subscription } from '@standardnotes/security' import { UuidString, ApplicationEventPayload } from '../Types' -import { ApplicationEvent, applicationEventForSyncEvent } from '@Lib/Application/Event' +import { applicationEventForSyncEvent } from '@Lib/Application/Event' import { + ApplicationEvent, + ApplicationEventCallback, ChallengeValidation, + ComponentManagerInterface, DiagnosticInfo, Environment, isDesktopDevice, @@ -36,7 +39,7 @@ import { } from '@standardnotes/services' import { SNLog } from '../Log' import { useBoolean } from '@standardnotes/utils' -import { DecryptedItemInterface, EncryptedItemInterface } from '@standardnotes/models' +import { BackupFile, DecryptedItemInterface, EncryptedItemInterface, ItemStream } from '@standardnotes/models' import { ClientDisplayableError } from '@standardnotes/responses' import { Challenge, ChallengeResponse } from '../Services' import { ApplicationConstructorOptions, FullyResolvedApplicationOptions } from './Options/ApplicationOptions' @@ -49,20 +52,11 @@ type LaunchCallback = { receiveChallenge: (challenge: Challenge) => void } -type ApplicationEventCallback = (event: ApplicationEvent, data?: unknown) => Promise - type ApplicationObserver = { singleEvent?: ApplicationEvent callback: ApplicationEventCallback } -type ItemStream = (data: { - changed: I[] - inserted: I[] - removed: (Models.DeletedItemInterface | Models.EncryptedItemInterface)[] - source: Models.PayloadEmitSource -}) => void - type ObserverRemover = () => void export class SNApplication @@ -97,7 +91,7 @@ export class SNApplication private syncService!: InternalServices.SNSyncService private challengeService!: InternalServices.ChallengeService public singletonManager!: InternalServices.SNSingletonManager - public componentManager!: InternalServices.SNComponentManager + public componentManagerService!: InternalServices.SNComponentManager public protectionService!: InternalServices.SNProtectionService public actionsManager!: InternalServices.SNActionsService public historyManager!: InternalServices.SNHistoryManager @@ -192,11 +186,11 @@ export class SNApplication return this.fileService } - public get features(): InternalServices.FeaturesClientInterface { + public get features(): ExternalServices.FeaturesClientInterface { return this.featuresService } - public get items(): InternalServices.ItemsClientInterface { + public get items(): ExternalServices.ItemsClientInterface { return this.itemManager } @@ -216,7 +210,7 @@ export class SNApplication return this.settingsService } - public get mutator(): InternalServices.MutatorClientInterface { + public get mutator(): ExternalServices.MutatorClientInterface { return this.mutatorService } @@ -232,6 +226,10 @@ export class SNApplication return this.filesBackupService } + public get componentManager(): ComponentManagerInterface { + return this.componentManagerService + } + public computePrivateWorkspaceIdentifier(userphrase: string, name: string): Promise { return Encryption.ComputePrivateWorkspaceIdentifier(this.options.crypto, userphrase, name) } @@ -659,11 +657,11 @@ export class SNApplication return this.listedService.getListedAccountInfo(account, inContextOfItem) } - public async createEncryptedBackupFileForAutomatedDesktopBackups(): Promise { + public async createEncryptedBackupFileForAutomatedDesktopBackups(): Promise { return this.protocolService.createEncryptedBackupFile() } - public async createEncryptedBackupFile(): Promise { + public async createEncryptedBackupFile(): Promise { if (!(await this.protectionService.authorizeBackupCreation())) { return } @@ -671,7 +669,7 @@ export class SNApplication return this.protocolService.createEncryptedBackupFile() } - public async createDecryptedBackupFile(): Promise { + public async createDecryptedBackupFile(): Promise { if (!(await this.protectionService.authorizeBackupCreation())) { return } @@ -1070,7 +1068,7 @@ export class SNApplication ;(this.syncService as unknown) = undefined ;(this.challengeService as unknown) = undefined ;(this.singletonManager as unknown) = undefined - ;(this.componentManager as unknown) = undefined + ;(this.componentManagerService as unknown) = undefined ;(this.protectionService as unknown) = undefined ;(this.actionsManager as unknown) = undefined ;(this.historyManager as unknown) = undefined @@ -1161,11 +1159,11 @@ export class SNApplication this.serviceObservers.push( this.featuresService.addEventObserver((event) => { switch (event) { - case InternalServices.FeaturesEvent.UserRolesChanged: { + case ExternalServices.FeaturesEvent.UserRolesChanged: { void this.notifyEvent(ApplicationEvent.UserRolesChanged) break } - case InternalServices.FeaturesEvent.FeaturesUpdated: { + case ExternalServices.FeaturesEvent.FeaturesUpdated: { void this.notifyEvent(ApplicationEvent.FeaturesUpdated) break } @@ -1268,7 +1266,7 @@ export class SNApplication const MaybeSwappedComponentManager = this.getClass( InternalServices.SNComponentManager, ) - this.componentManager = new MaybeSwappedComponentManager( + this.componentManagerService = new MaybeSwappedComponentManager( this.itemManager, this.syncService, this.featuresService, @@ -1278,7 +1276,7 @@ export class SNApplication this.platform, this.internalEventBus, ) - this.services.push(this.componentManager) + this.services.push(this.componentManagerService) } private createHttpManager() { @@ -1533,7 +1531,7 @@ export class SNApplication this.protocolService, this.payloadManager, this.challengeService, - this.componentManager, + this.componentManagerService, this.historyManager, this.internalEventBus, ) diff --git a/packages/snjs/lib/Application/Event.ts b/packages/snjs/lib/Application/Event.ts index 51ad3da19..91ba03516 100644 --- a/packages/snjs/lib/Application/Event.ts +++ b/packages/snjs/lib/Application/Event.ts @@ -1,72 +1,6 @@ -import { SyncEvent } from '@standardnotes/services' +import { ApplicationEvent, SyncEvent } from '@standardnotes/services' export { SyncEvent } -export enum ApplicationEvent { - SignedIn = 2, - SignedOut = 3, - - /** When a full, potentially multi-page sync completes */ - CompletedFullSync = 5, - - FailedSync = 6, - HighLatencySync = 7, - EnteredOutOfSync = 8, - ExitedOutOfSync = 9, - - /** - * The application has finished it `prepareForLaunch` state and is now ready for unlock - * Called when the application has initialized and is ready for launch, but before - * the application has been unlocked, if applicable. Use this to do pre-launch - * configuration, but do not attempt to access user data like notes or tags. - */ - Started = 10, - - /** - * The applicaiton is fully unlocked and ready for i/o - * Called when the application has been fully decrypted and unlocked. Use this to - * to begin streaming data like notes and tags. - */ - Launched = 11, - LocalDataLoaded = 12, - - /** - * When the root key or root key wrapper changes. Includes events like account state - * changes (registering, signing in, changing pw, logging out) and passcode state - * changes (adding, removing, changing). - */ - KeyStatusChanged = 13, - - MajorDataChange = 14, - CompletedRestart = 15, - LocalDataIncrementalLoad = 16, - SyncStatusChanged = 17, - WillSync = 18, - InvalidSyncSession = 19, - LocalDatabaseReadError = 20, - LocalDatabaseWriteError = 21, - - /** When a single roundtrip completes with sync, in a potentially multi-page sync request. - * If just a single roundtrip, this event will be triggered, along with CompletedFullSync */ - CompletedIncrementalSync = 22, - - /** - * The application has loaded all pending migrations (but not run any, except for the base one), - * and consumers may now call `hasPendingMigrations` - */ - MigrationsLoaded = 23, - - /** When StorageService is ready to start servicing read/write requests */ - StorageReady = 24, - - PreferencesChanged = 25, - UnprotectedSessionBegan = 26, - UserRolesChanged = 27, - FeaturesUpdated = 28, - UnprotectedSessionExpired = 29, - /** Called when the app first launches and after first sync request made after sign in */ - CompletedInitialSync = 30, -} - export function applicationEventForSyncEvent(syncEvent: SyncEvent) { return ( { diff --git a/packages/snjs/lib/Client/ItemGroupController.ts b/packages/snjs/lib/Client/ItemGroupController.ts index c97ee80d7..bf382d6ba 100644 --- a/packages/snjs/lib/Client/ItemGroupController.ts +++ b/packages/snjs/lib/Client/ItemGroupController.ts @@ -1,7 +1,9 @@ -import { ApplicationEvent } from '../Application/Event' import { FileItem, PrefKey, SNNote } from '@standardnotes/models' import { removeFromArray } from '@standardnotes/utils' +import { ApplicationEvent } from '@standardnotes/services' + import { SNApplication } from '../Application/Application' + import { NoteViewController } from './NoteViewController' import { FileViewController } from './FileViewController' import { TemplateNoteViewControllerOptions } from './TemplateNoteViewControllerOptions' diff --git a/packages/snjs/lib/Services/AppService/ApplicationService.ts b/packages/snjs/lib/Services/AppService/ApplicationService.ts index d11dd51db..2127f691a 100644 --- a/packages/snjs/lib/Services/AppService/ApplicationService.ts +++ b/packages/snjs/lib/Services/AppService/ApplicationService.ts @@ -1,11 +1,17 @@ -import { ApplicationEvent } from '@Lib/Application/Event' -import { AbstractService, InternalEventBusInterface } from '@standardnotes/services' -import { SNApplication } from '../../Application/Application' +import { + AbstractService, + ApplicationEvent, + ApplicationInterface, + InternalEventBusInterface, +} from '@standardnotes/services' export class ApplicationService extends AbstractService { private unsubApp!: () => void - constructor(protected application: SNApplication, protected override internalEventBus: InternalEventBusInterface) { + constructor( + protected application: ApplicationInterface, + protected override internalEventBus: InternalEventBusInterface, + ) { super(internalEventBus) this.addAppEventObserverAfterSubclassesFinishConstructing() } diff --git a/packages/snjs/lib/Services/ComponentManager/ComponentManager.spec.ts b/packages/snjs/lib/Services/ComponentManager/ComponentManager.spec.ts index faf597bf4..5b134508d 100644 --- a/packages/snjs/lib/Services/ComponentManager/ComponentManager.spec.ts +++ b/packages/snjs/lib/Services/ComponentManager/ComponentManager.spec.ts @@ -10,10 +10,15 @@ import { FindNativeFeature, FeatureIdentifier, } from '@standardnotes/features' -import { DesktopManagerInterface } from '@Lib/Services/ComponentManager/Types' import { ContentType } from '@standardnotes/common' import { GenericItem, SNComponent } from '@standardnotes/models' -import { InternalEventBusInterface, Environment, Platform, AlertService } from '@standardnotes/services' +import { + DesktopManagerInterface, + InternalEventBusInterface, + Environment, + Platform, + AlertService, +} from '@standardnotes/services' import { ItemManager } from '@Lib/Services/Items/ItemManager' import { SNFeaturesService } from '@Lib/Services/Features/FeaturesService' import { SNComponentManager } from './ComponentManager' @@ -34,7 +39,10 @@ describe('featuresService', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function syncComponentsInstallation() {}, // eslint-disable-next-line @typescript-eslint/no-empty-function - registerUpdateObserver() {}, + registerUpdateObserver(_callback: (component: SNComponent) => void) { + // eslint-disable-next-line @typescript-eslint/no-empty-function + return () => {} + }, getExtServerHost() { return desktopExtHost }, diff --git a/packages/snjs/lib/Services/ComponentManager/ComponentManager.ts b/packages/snjs/lib/Services/ComponentManager/ComponentManager.ts index e95e4d084..39d5229fe 100644 --- a/packages/snjs/lib/Services/ComponentManager/ComponentManager.ts +++ b/packages/snjs/lib/Services/ComponentManager/ComponentManager.ts @@ -3,21 +3,28 @@ import { SNPreferencesService } from '../Preferences/PreferencesService' import { SNFeaturesService } from '@Lib/Services/Features/FeaturesService' import { ContentType, DisplayStringForContentType } from '@standardnotes/common' import { ItemManager } from '@Lib/Services/Items/ItemManager' -import { SNNote, SNTheme, SNComponent, ComponentMutator, PayloadEmitSource } from '@standardnotes/models' +import { + ActionObserver, + SNNote, + SNTheme, + SNComponent, + ComponentMutator, + PayloadEmitSource, + PermissionDialog, +} from '@standardnotes/models' import { SNSyncService } from '@Lib/Services/Sync/SyncService' import find from 'lodash/find' import uniq from 'lodash/uniq' import { ComponentArea, ComponentAction, ComponentPermission, FindNativeFeature } from '@standardnotes/features' import { Copy, filterFromArray, removeFromArray, sleep, assert } from '@standardnotes/utils' import { UuidString } from '@Lib/Types/UuidString' -import { - PermissionDialog, - DesktopManagerInterface, - AllowedBatchContentTypes, -} from '@Lib/Services/ComponentManager/Types' -import { ActionObserver, ComponentViewer } from '@Lib/Services/ComponentManager/ComponentViewer' +import { AllowedBatchContentTypes } from '@Lib/Services/ComponentManager/Types' +import { ComponentViewer } from '@Lib/Services/ComponentManager/ComponentViewer' import { AbstractService, + ComponentManagerInterface, + ComponentViewerInterface, + DesktopManagerInterface, InternalEventBusInterface, Environment, Platform, @@ -42,7 +49,7 @@ export enum ComponentManagerEvent { } export type EventData = { - componentViewer?: ComponentViewer + componentViewer?: ComponentViewerInterface } /** @@ -50,9 +57,12 @@ export type EventData = { * and other components. The component manager primarily deals with iframes, and orchestrates * sending and receiving messages to and from frames via the postMessage API. */ -export class SNComponentManager extends AbstractService { +export class SNComponentManager + extends AbstractService + implements ComponentManagerInterface +{ private desktopManager?: DesktopManagerInterface - private viewers: ComponentViewer[] = [] + private viewers: ComponentViewerInterface[] = [] private removeItemObserver!: () => void private permissionDialogs: PermissionDialog[] = [] @@ -137,7 +147,7 @@ export class SNComponentManager extends AbstractService(uuid) } - findComponentViewer(identifier: string): ComponentViewer | undefined { + findComponentViewer(identifier: string): ComponentViewerInterface | undefined { return this.viewers.find((viewer) => viewer.identifier === identifier) } - componentViewerForSessionKey(key: string): ComponentViewer | undefined { + componentViewerForSessionKey(key: string): ComponentViewerInterface | undefined { return this.viewers.find((viewer) => viewer.sessionKey === key) } diff --git a/packages/snjs/lib/Services/ComponentManager/ComponentViewer.ts b/packages/snjs/lib/Services/ComponentManager/ComponentViewer.ts index 0a7a1ad98..637c296b9 100644 --- a/packages/snjs/lib/Services/ComponentManager/ComponentViewer.ts +++ b/packages/snjs/lib/Services/ComponentManager/ComponentViewer.ts @@ -1,8 +1,19 @@ import { SNPreferencesService } from '../Preferences/PreferencesService' -import { FeatureStatus, FeaturesEvent } from '@Lib/Services/Features' -import { Environment, Platform, AlertService } from '@standardnotes/services' +import { + ComponentViewerInterface, + ComponentViewerError, + Environment, + FeatureStatus, + FeaturesEvent, + Platform, + AlertService, +} from '@standardnotes/services' import { SNFeaturesService } from '@Lib/Services' import { + ActionObserver, + ComponentEventObserver, + ComponentViewerEvent, + ComponentMessage, SNComponent, PrefKey, NoteContent, @@ -21,6 +32,8 @@ import { ComponentDataDomain, PayloadEmitSource, PayloadTimestampDefaults, + IncomingComponentItemPayload, + MessageData, } from '@standardnotes/models' import find from 'lodash/find' import uniq from 'lodash/uniq' @@ -28,12 +41,10 @@ import remove from 'lodash/remove' import { SNSyncService } from '@Lib/Services/Sync/SyncService' import { environmentToString, platformToString } from '@Lib/Application/Platforms' import { - ComponentMessage, OutgoingItemMessagePayload, MessageReply, StreamItemsMessageData, AllowedBatchContentTypes, - IncomingComponentItemPayload, DeleteItemsMessageData, MessageReplyData, } from './Types' @@ -53,7 +64,6 @@ import { sureSearchArray, isNotUndefined, } from '@standardnotes/utils' -import { MessageData } from '..' type RunWithPermissionsCallback = ( componentUuid: UuidString, @@ -76,21 +86,9 @@ const ReadwriteActions = [ ComponentAction.SetComponentData, ] -export type ActionObserver = (action: ComponentAction, messageData: MessageData) => void - -export enum ComponentViewerEvent { - FeatureStatusUpdated = 'FeatureStatusUpdated', -} -type EventObserver = (event: ComponentViewerEvent) => void - -export enum ComponentViewerError { - OfflineRestricted = 'OfflineRestricted', - MissingUrl = 'MissingUrl', -} - type Writeable = { -readonly [P in keyof T]: T[P] } -export class ComponentViewer { +export class ComponentViewer implements ComponentViewerInterface { private streamItems?: ContentType[] private streamContextItemOriginalMessage?: ComponentMessage private streamItemsOriginalMessage?: ComponentMessage @@ -101,7 +99,7 @@ export class ComponentViewer { public overrideContextItem?: DecryptedItemInterface private featureStatus: FeatureStatus private removeFeaturesObserver: () => void - private eventObservers: EventObserver[] = [] + private eventObservers: ComponentEventObserver[] = [] private dealloced = false private window?: Window @@ -189,7 +187,7 @@ export class ComponentViewer { ;(this.removeItemObserver as unknown) = undefined } - public addEventObserver(observer: EventObserver): () => void { + public addEventObserver(observer: ComponentEventObserver): () => void { this.eventObservers.push(observer) const thislessChangeObservers = this.eventObservers diff --git a/packages/snjs/lib/Services/ComponentManager/Types.ts b/packages/snjs/lib/Services/ComponentManager/Types.ts index 5a4858310..c0b5f25fa 100644 --- a/packages/snjs/lib/Services/ComponentManager/Types.ts +++ b/packages/snjs/lib/Services/ComponentManager/Types.ts @@ -1,24 +1,8 @@ -import { - ComponentArea, - ComponentAction, - ComponentPermission, - FeatureIdentifier, - LegacyFileSafeIdentifier, -} from '@standardnotes/features' -import { ItemContent, SNComponent, DecryptedTransferPayload } from '@standardnotes/models' +import { ComponentArea, ComponentAction, FeatureIdentifier, LegacyFileSafeIdentifier } from '@standardnotes/features' +import { ComponentMessage, ItemContent, MessageData } from '@standardnotes/models' import { UuidString } from '@Lib/Types/UuidString' import { ContentType } from '@standardnotes/common' -export interface DesktopManagerInterface { - syncComponentsInstallation(components: SNComponent[]): void - registerUpdateObserver(callback: (component: SNComponent) => void): void - getExtServerHost(): string -} - -export type IncomingComponentItemPayload = DecryptedTransferPayload & { - clientData: Record -} - export type OutgoingItemMessagePayload = { uuid: string content_type: ContentType @@ -63,46 +47,6 @@ export type StreamObserver = { contentTypes?: ContentType[] } -export type PermissionDialog = { - component: SNComponent - permissions: ComponentPermission[] - permissionsString: string - actionBlock: (approved: boolean) => void - callback: (approved: boolean) => void -} - -export enum KeyboardModifier { - Shift = 'Shift', - Ctrl = 'Control', - Meta = 'Meta', -} - -export type MessageData = Partial<{ - /** Related to the stream-item-context action */ - item?: IncomingComponentItemPayload - /** Related to the stream-items action */ - content_types?: ContentType[] - items?: IncomingComponentItemPayload[] - /** Related to the request-permission action */ - permissions?: ComponentPermission[] - /** Related to the component-registered action */ - componentData?: Record - uuid?: UuidString - environment?: string - platform?: string - activeThemeUrls?: string[] - /** Related to set-size action */ - width?: string | number - height?: string | number - type?: string - /** Related to themes action */ - themes?: string[] - /** Related to clear-selection action */ - content_type?: ContentType - /** Related to key-pressed action */ - keyboardModifier?: KeyboardModifier -}> - export type MessageReplyData = { approved?: boolean deleted?: boolean @@ -120,13 +64,6 @@ export type DeleteItemsMessageData = MessageData & { items: OutgoingItemMessagePayload[] } -export type ComponentMessage = { - action: ComponentAction - sessionKey?: string - componentData?: Record - data: MessageData -} - export type MessageReply = { action: ComponentAction original: ComponentMessage diff --git a/packages/snjs/lib/Services/Features/FeaturesService.spec.ts b/packages/snjs/lib/Services/Features/FeaturesService.spec.ts index 0d6487b68..844700b0d 100644 --- a/packages/snjs/lib/Services/Features/FeaturesService.spec.ts +++ b/packages/snjs/lib/Services/Features/FeaturesService.spec.ts @@ -10,14 +10,14 @@ import { DiskStorageService, StorageKey, } from '@Lib/index' -import { FeatureStatus, SNFeaturesService } from '@Lib/Services/Features' +import { SNFeaturesService } from '@Lib/Services/Features' import { ContentType, RoleName } from '@standardnotes/common' import { FeatureDescription, FeatureIdentifier, GetFeatures } from '@standardnotes/features' import { SNWebSocketsService } from '../Api/WebsocketsService' import { SNSettingsService } from '../Settings' import { PureCryptoInterface } from '@standardnotes/sncrypto-common' import { convertTimestampToMilliseconds } from '@standardnotes/utils' -import { InternalEventBusInterface } from '@standardnotes/services' +import { FeatureStatus, InternalEventBusInterface } from '@standardnotes/services' describe('featuresService', () => { let storageService: DiskStorageService diff --git a/packages/snjs/lib/Services/Features/FeaturesService.ts b/packages/snjs/lib/Services/Features/FeaturesService.ts index 52e325567..0851538d7 100644 --- a/packages/snjs/lib/Services/Features/FeaturesService.ts +++ b/packages/snjs/lib/Services/Features/FeaturesService.ts @@ -10,7 +10,6 @@ import { } from '@standardnotes/utils' import { ClientDisplayableError, UserFeaturesResponse } from '@standardnotes/responses' import { ContentType, RoleName } from '@standardnotes/common' -import { FeaturesClientInterface } from './ClientInterface' import { FillItemContent, PayloadEmitSource } from '@standardnotes/models' import { ItemManager } from '../Items/ItemManager' import { LEGACY_PROD_EXT_ORIGIN, PROD_OFFLINE_FEATURES_URL } from '../../Hosts' @@ -27,20 +26,30 @@ import { UuidString } from '@Lib/Types/UuidString' import * as FeaturesImports from '@standardnotes/features' import * as Messages from '@Lib/Services/Api/Messages' import * as Models from '@standardnotes/models' -import * as Services from '@standardnotes/services' import { + AbstractService, + AlertService, + ApiServiceEvent, + ApplicationStage, + ButtonType, + DiagnosticInfo, + FeaturesClientInterface, FeaturesEvent, FeatureStatus, + InternalEventBusInterface, + InternalEventHandlerInterface, + InternalEventInterface, + MetaReceivedData, OfflineSubscriptionEntitlements, SetOfflineFeaturesFunctionResponse, -} from './Types' -import { DiagnosticInfo } from '@standardnotes/services' + StorageKey, +} from '@standardnotes/services' type GetOfflineSubscriptionDetailsResponse = OfflineSubscriptionEntitlements | ClientDisplayableError export class SNFeaturesService - extends Services.AbstractService - implements FeaturesClientInterface, Services.InternalEventHandlerInterface + extends AbstractService + implements FeaturesClientInterface, InternalEventHandlerInterface { private deinited = false private roles: RoleName[] = [] @@ -60,10 +69,10 @@ export class SNFeaturesService private settingsService: SNSettingsService, private userService: UserService, private syncService: SNSyncService, - private alertService: Services.AlertService, + private alertService: AlertService, private sessionManager: SNSessionManager, private crypto: PureCryptoInterface, - protected override internalEventBus: Services.InternalEventBusInterface, + protected override internalEventBus: InternalEventBusInterface, ) { super(internalEventBus) @@ -109,8 +118,8 @@ export class SNFeaturesService }) } - async handleEvent(event: Services.InternalEventInterface): Promise { - if (event.type === Services.ApiServiceEvent.MetaReceived) { + async handleEvent(event: InternalEventInterface): Promise { + if (event.type === ApiServiceEvent.MetaReceived) { if (!this.syncService) { this.log('[Features Service] Handling events interrupted. Sync service is not yet initialized.', event) @@ -126,7 +135,7 @@ export class SNFeaturesService return } - const { userUuid, userRoles } = event.payload as Services.MetaReceivedData + const { userUuid, userRoles } = event.payload as MetaReceivedData await this.updateRolesAndFetchFeatures( userUuid, userRoles.map((role) => role.name), @@ -134,9 +143,9 @@ export class SNFeaturesService } } - override async handleApplicationStage(stage: Services.ApplicationStage): Promise { + override async handleApplicationStage(stage: ApplicationStage): Promise { await super.handleApplicationStage(stage) - if (stage === Services.ApplicationStage.FullSyncCompleted_13) { + if (stage === ApplicationStage.FullSyncCompleted_13) { if (!this.hasOnlineSubscription()) { const offlineRepo = this.getOfflineRepo() if (offlineRepo) { @@ -154,7 +163,7 @@ export class SNFeaturesService this.enabledExperimentalFeatures.push(identifier) - void this.storageService.setValue(Services.StorageKey.ExperimentalFeatures, this.enabledExperimentalFeatures) + void this.storageService.setValue(StorageKey.ExperimentalFeatures, this.enabledExperimentalFeatures) void this.mapRemoteNativeFeaturesToItems([feature]) void this.notifyEvent(FeaturesEvent.FeaturesUpdated) @@ -168,7 +177,7 @@ export class SNFeaturesService removeFromArray(this.enabledExperimentalFeatures, identifier) - void this.storageService.setValue(Services.StorageKey.ExperimentalFeatures, this.enabledExperimentalFeatures) + void this.storageService.setValue(StorageKey.ExperimentalFeatures, this.enabledExperimentalFeatures) const component = this.itemManager .getItems([ContentType.Component, ContentType.Theme]) @@ -248,7 +257,7 @@ export class SNFeaturesService await this.itemManager.setItemToBeDeleted(repo) void this.syncService.sync() } - await this.storageService.removeValue(Services.StorageKey.UserFeatures) + await this.storageService.removeValue(StorageKey.UserFeatures) } private parseOfflineEntitlementsCode(code: string): GetOfflineSubscriptionDetailsResponse | ClientDisplayableError { @@ -322,15 +331,11 @@ export class SNFeaturesService } public initializeFromDisk(): void { - this.roles = this.storageService.getValue(Services.StorageKey.UserRoles, undefined, []) + this.roles = this.storageService.getValue(StorageKey.UserRoles, undefined, []) - this.features = this.storageService.getValue(Services.StorageKey.UserFeatures, undefined, []) + this.features = this.storageService.getValue(StorageKey.UserFeatures, undefined, []) - this.enabledExperimentalFeatures = this.storageService.getValue( - Services.StorageKey.ExperimentalFeatures, - undefined, - [], - ) + this.enabledExperimentalFeatures = this.storageService.getValue(StorageKey.ExperimentalFeatures, undefined, []) } public async updateRolesAndFetchFeatures(userUuid: UuidString, roles: RoleName[]): Promise { @@ -361,7 +366,7 @@ export class SNFeaturesService if (!arraysEqual(this.roles, roles)) { void this.notifyEvent(FeaturesEvent.UserRolesChanged) } - await this.storageService.setValue(Services.StorageKey.UserRoles, this.roles) + await this.storageService.setValue(StorageKey.UserRoles, this.roles) } public async didDownloadFeatures(features: FeaturesImports.FeatureDescription[]): Promise { @@ -372,7 +377,7 @@ export class SNFeaturesService this.features = features this.completedSuccessfulFeaturesRetrieval = true void this.notifyEvent(FeaturesEvent.FeaturesUpdated) - void this.storageService.setValue(Services.StorageKey.UserFeatures, this.features) + void this.storageService.setValue(StorageKey.UserFeatures, this.features) await this.mapRemoteNativeFeaturesToItems(features) } @@ -607,7 +612,7 @@ export class SNFeaturesService Messages.API_MESSAGE_UNTRUSTED_EXTENSIONS_WARNING, 'Install extension from an untrusted source?', 'Proceed to install', - Services.ButtonType.Danger, + ButtonType.Danger, 'Cancel', ) if (didConfirm) { diff --git a/packages/snjs/lib/Services/Features/Types.ts b/packages/snjs/lib/Services/Features/Types.ts deleted file mode 100644 index f455af7c3..000000000 --- a/packages/snjs/lib/Services/Features/Types.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ClientDisplayableError } from '@standardnotes/responses' - -export type SetOfflineFeaturesFunctionResponse = ClientDisplayableError | undefined - -export type OfflineSubscriptionEntitlements = { - featuresUrl: string - extensionKey: string -} - -export enum FeaturesEvent { - UserRolesChanged = 'UserRolesChanged', - FeaturesUpdated = 'FeaturesUpdated', -} - -export enum FeatureStatus { - NoUserSubscription = 'NoUserSubscription', - NotInCurrentPlan = 'NotInCurrentPlan', - InCurrentPlanButExpired = 'InCurrentPlanButExpired', - Entitled = 'Entitled', -} diff --git a/packages/snjs/lib/Services/Features/index.ts b/packages/snjs/lib/Services/Features/index.ts index a2c4fe199..8027f7d29 100644 --- a/packages/snjs/lib/Services/Features/index.ts +++ b/packages/snjs/lib/Services/Features/index.ts @@ -1,3 +1 @@ -export * from './ClientInterface' export * from './FeaturesService' -export * from './Types' diff --git a/packages/snjs/lib/Services/Items/ItemManager.ts b/packages/snjs/lib/Services/Items/ItemManager.ts index 656aa8946..67244d619 100644 --- a/packages/snjs/lib/Services/Items/ItemManager.ts +++ b/packages/snjs/lib/Services/Items/ItemManager.ts @@ -3,13 +3,11 @@ import { assert, naturalSort, removeFromArray, UuidGenerator, Uuids } from '@sta import { ItemsKeyMutator, SNItemsKey } from '@standardnotes/encryption' import { PayloadManager } from '../Payloads/PayloadManager' import { TagsToFoldersMigrationApplicator } from '../../Migrations/Applicators/TagsToFolders' -import { TransactionalMutation } from './TransactionalMutation' import { UuidString } from '../../Types/UuidString' import * as Models from '@standardnotes/models' import * as Services from '@standardnotes/services' -import { ItemsClientInterface } from './ItemsClientInterface' import { PayloadManagerChangeData } from '../Payloads' -import { DiagnosticInfo } from '@standardnotes/services' +import { DiagnosticInfo, ItemsClientInterface } from '@standardnotes/services' import { ApplicationDisplayOptions } from '@Lib/Application/Options/OptionalOptions' import { CollectionSort } from '@standardnotes/models' @@ -578,7 +576,7 @@ export class ItemManager * runs the same mutation on all items. */ public async runTransactionalMutations( - transactions: TransactionalMutation[], + transactions: Models.TransactionalMutation[], emitSource = Models.PayloadEmitSource.LocalChanged, payloadSourceKey?: string, ): Promise<(Models.DecryptedItemInterface | undefined)[]> { @@ -607,7 +605,7 @@ export class ItemManager } public async runTransactionalMutation( - transaction: TransactionalMutation, + transaction: Models.TransactionalMutation, emitSource = Models.PayloadEmitSource.LocalChanged, payloadSourceKey?: string, ): Promise { diff --git a/packages/snjs/lib/Services/Items/TransactionalMutation.ts b/packages/snjs/lib/Services/Items/TransactionalMutation.ts deleted file mode 100644 index a4e2eb2dc..000000000 --- a/packages/snjs/lib/Services/Items/TransactionalMutation.ts +++ /dev/null @@ -1,8 +0,0 @@ -import * as Models from '@standardnotes/models' -import { UuidString } from '../../Types/UuidString' - -export type TransactionalMutation = { - itemUuid: UuidString - mutate: (mutator: Models.ItemMutator) => void - mutationType?: Models.MutationType -} diff --git a/packages/snjs/lib/Services/Items/index.ts b/packages/snjs/lib/Services/Items/index.ts index c708e0351..a49df0481 100644 --- a/packages/snjs/lib/Services/Items/index.ts +++ b/packages/snjs/lib/Services/Items/index.ts @@ -1,3 +1 @@ -export * from './ItemsClientInterface' export * from './ItemManager' -export * from './TransactionalMutation' diff --git a/packages/snjs/lib/Services/Migration/MigrationService.ts b/packages/snjs/lib/Services/Migration/MigrationService.ts index 5f680ca5e..a6d5381a3 100644 --- a/packages/snjs/lib/Services/Migration/MigrationService.ts +++ b/packages/snjs/lib/Services/Migration/MigrationService.ts @@ -1,4 +1,3 @@ -import { ApplicationEvent } from '../../Application/Event' import { BaseMigration } from '@Lib/Migrations/Base' import { compareSemVersions } from '@Lib/Version' import { lastElement } from '@standardnotes/utils' @@ -7,6 +6,7 @@ import { MigrationServices } from '../../Migrations/MigrationServices' import { RawStorageKey, namespacedKey, + ApplicationEvent, ApplicationStage, AbstractService, DiagnosticInfo, diff --git a/packages/snjs/lib/Services/Mutator/MutatorClientInterface.ts b/packages/snjs/lib/Services/Mutator/MutatorClientInterface.ts deleted file mode 100644 index e099405ff..000000000 --- a/packages/snjs/lib/Services/Mutator/MutatorClientInterface.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { ContentType } from '@standardnotes/common' -import { ChallengeReason, SyncOptions } from '@standardnotes/services' -import { TransactionalMutation } from '../Items' -import * as Models from '@standardnotes/models' -import { ClientDisplayableError } from '@standardnotes/responses' -import { BackupFile } from '@standardnotes/encryption' - -export interface MutatorClientInterface { - /** - * Inserts the input item by its payload properties, and marks the item as dirty. - * A sync is not performed after an item is inserted. This must be handled by the caller. - */ - insertItem(item: Models.DecryptedItemInterface): Promise - - /** - * Mutates a pre-existing item, marks it as dirty, and syncs it - */ - changeAndSaveItem( - itemToLookupUuidFor: Models.DecryptedItemInterface, - mutate: (mutator: M) => void, - updateTimestamps?: boolean, - emitSource?: Models.PayloadEmitSource, - syncOptions?: SyncOptions, - ): Promise - - /** - * Mutates pre-existing items, marks them as dirty, and syncs - */ - changeAndSaveItems( - itemsToLookupUuidsFor: Models.DecryptedItemInterface[], - mutate: (mutator: M) => void, - updateTimestamps?: boolean, - emitSource?: Models.PayloadEmitSource, - syncOptions?: SyncOptions, - ): Promise - - /** - * Mutates a pre-existing item and marks it as dirty. Does not sync changes. - */ - changeItem( - itemToLookupUuidFor: Models.DecryptedItemInterface, - mutate: (mutator: M) => void, - updateTimestamps?: boolean, - ): Promise - - /** - * Mutates a pre-existing items and marks them as dirty. Does not sync changes. - */ - changeItems( - itemsToLookupUuidsFor: Models.DecryptedItemInterface[], - mutate: (mutator: M) => void, - updateTimestamps?: boolean, - ): Promise<(Models.DecryptedItemInterface | undefined)[]> - - /** - * Run unique mutations per each item in the array, then only propagate all changes - * once all mutations have been run. This differs from `changeItems` in that changeItems - * runs the same mutation on all items. - */ - runTransactionalMutations( - transactions: TransactionalMutation[], - emitSource?: Models.PayloadEmitSource, - payloadSourceKey?: string, - ): Promise<(Models.DecryptedItemInterface | undefined)[]> - - runTransactionalMutation( - transaction: TransactionalMutation, - emitSource?: Models.PayloadEmitSource, - payloadSourceKey?: string, - ): Promise - - protectItems< - _M extends Models.DecryptedItemMutator, - I extends Models.DecryptedItemInterface, - >( - items: I[], - ): Promise - - unprotectItems< - _M extends Models.DecryptedItemMutator, - I extends Models.DecryptedItemInterface, - >( - items: I[], - reason: ChallengeReason, - ): Promise - - protectNote(note: Models.SNNote): Promise - - unprotectNote(note: Models.SNNote): Promise - - protectNotes(notes: Models.SNNote[]): Promise - - unprotectNotes(notes: Models.SNNote[]): Promise - - protectFile(file: Models.FileItem): Promise - - unprotectFile(file: Models.FileItem): Promise - - /** - * Takes the values of the input item and emits it onto global state. - */ - mergeItem( - item: Models.DecryptedItemInterface, - source: Models.PayloadEmitSource, - ): Promise - - /** - * Creates an unmanaged item that can be added later. - */ - createTemplateItem< - C extends Models.ItemContent = Models.ItemContent, - I extends Models.DecryptedItemInterface = Models.DecryptedItemInterface, - >( - contentType: ContentType, - content?: C, - ): I - - /** - * @param isUserModified Whether to change the modified date the user - * sees of the item. - */ - setItemNeedsSync( - item: Models.DecryptedItemInterface, - isUserModified?: boolean, - ): Promise - - setItemsNeedsSync(items: Models.DecryptedItemInterface[]): Promise<(Models.DecryptedItemInterface | undefined)[]> - - deleteItem(item: Models.DecryptedItemInterface | Models.EncryptedItemInterface): Promise - - deleteItems(items: (Models.DecryptedItemInterface | Models.EncryptedItemInterface)[]): Promise - - emptyTrash(): Promise - - duplicateItem(item: T, additionalContent?: Partial): Promise - - /** - * Migrates any tags containing a '.' character to sa chema-based heirarchy, removing - * the dot from the tag's title. - */ - migrateTagsToFolders(): Promise - - /** - * Establishes a hierarchical relationship between two tags. - */ - setTagParent(parentTag: Models.SNTag, childTag: Models.SNTag): Promise - - /** - * Remove the tag parent. - */ - unsetTagParent(childTag: Models.SNTag): Promise - - findOrCreateTag(title: string): Promise - - /** Creates and returns the tag but does not run sync. Callers must perform sync. */ - createTagOrSmartView(title: string): Promise - - /** - * Activates or deactivates a component, depending on its - * current state, and syncs. - */ - toggleComponent(component: Models.SNComponent): Promise - - toggleTheme(theme: Models.SNComponent): Promise - - /** - * @returns - * .affectedItems: Items that were either created or dirtied by this import - * .errorCount: The number of items that were not imported due to failure to decrypt. - */ - importData( - data: BackupFile, - awaitSync?: boolean, - ): Promise< - | { - affectedItems: Models.DecryptedItemInterface[] - errorCount: number - } - | { - error: ClientDisplayableError - } - > -} diff --git a/packages/snjs/lib/Services/Mutator/MutatorService.ts b/packages/snjs/lib/Services/Mutator/MutatorService.ts index 55ba1c274..2153df6bb 100644 --- a/packages/snjs/lib/Services/Mutator/MutatorService.ts +++ b/packages/snjs/lib/Services/Mutator/MutatorService.ts @@ -6,25 +6,42 @@ import { ChallengeValidation, ChallengePrompt, ChallengeReason, + MutatorClientInterface, } from '@standardnotes/services' -import { BackupFile, EncryptionProvider } from '@standardnotes/encryption' +import { EncryptionProvider } from '@standardnotes/encryption' import { ClientDisplayableError } from '@standardnotes/responses' import { ContentType, ProtocolVersion, compareVersions } from '@standardnotes/common' -import { ItemManager, TransactionalMutation } from '../Items' -import { MutatorClientInterface } from './MutatorClientInterface' +import { ItemManager } from '../Items' import { PayloadManager } from '../Payloads/PayloadManager' import { SNComponentManager } from '../ComponentManager/ComponentManager' import { SNProtectionService } from '../Protection/ProtectionService' import { SNSyncService } from '../Sync' import { Strings } from '../../Strings' import { TagsToFoldersMigrationApplicator } from '@Lib/Migrations/Applicators/TagsToFolders' -import * as Models from '@standardnotes/models' import { Challenge, ChallengeService } from '../Challenge' import { + BackupFile, + BackupFileDecryptedContextualPayload, + ComponentContent, + CopyPayloadWithContentOverride, CreateDecryptedBackupFileContextPayload, + CreateDecryptedMutatorForItem, CreateEncryptedBackupFileContextPayload, + DecryptedItemInterface, + DecryptedItemMutator, + DecryptedPayloadInterface, + EncryptedItemInterface, + FileItem, isDecryptedPayload, isEncryptedTransferPayload, + ItemContent, + MutationType, + PayloadEmitSource, + SmartView, + SNComponent, + SNNote, + SNTag, + TransactionalMutation, } from '@standardnotes/models' export class MutatorService extends AbstractService implements MutatorClientInterface { @@ -54,106 +71,101 @@ export class MutatorService extends AbstractService implements MutatorClientInte ;(this.historyService as unknown) = undefined } - public async insertItem(item: Models.DecryptedItemInterface): Promise { - const mutator = Models.CreateDecryptedMutatorForItem(item, Models.MutationType.UpdateUserTimestamps) + public async insertItem(item: DecryptedItemInterface): Promise { + const mutator = CreateDecryptedMutatorForItem(item, MutationType.UpdateUserTimestamps) const dirtiedPayload = mutator.getResult() - const insertedItem = await this.itemManager.emitItemFromPayload( - dirtiedPayload, - Models.PayloadEmitSource.LocalInserted, - ) + const insertedItem = await this.itemManager.emitItemFromPayload(dirtiedPayload, PayloadEmitSource.LocalInserted) return insertedItem } - public async changeAndSaveItem( - itemToLookupUuidFor: Models.DecryptedItemInterface, + public async changeAndSaveItem( + itemToLookupUuidFor: DecryptedItemInterface, mutate: (mutator: M) => void, updateTimestamps = true, - emitSource?: Models.PayloadEmitSource, + emitSource?: PayloadEmitSource, syncOptions?: SyncOptions, - ): Promise { + ): Promise { await this.itemManager.changeItems( [itemToLookupUuidFor], mutate, - updateTimestamps ? Models.MutationType.UpdateUserTimestamps : Models.MutationType.NoUpdateUserTimestamps, + updateTimestamps ? MutationType.UpdateUserTimestamps : MutationType.NoUpdateUserTimestamps, emitSource, ) await this.syncService.sync(syncOptions) return this.itemManager.findItem(itemToLookupUuidFor.uuid) } - public async changeAndSaveItems( - itemsToLookupUuidsFor: Models.DecryptedItemInterface[], + public async changeAndSaveItems( + itemsToLookupUuidsFor: DecryptedItemInterface[], mutate: (mutator: M) => void, updateTimestamps = true, - emitSource?: Models.PayloadEmitSource, + emitSource?: PayloadEmitSource, syncOptions?: SyncOptions, ): Promise { await this.itemManager.changeItems( itemsToLookupUuidsFor, mutate, - updateTimestamps ? Models.MutationType.UpdateUserTimestamps : Models.MutationType.NoUpdateUserTimestamps, + updateTimestamps ? MutationType.UpdateUserTimestamps : MutationType.NoUpdateUserTimestamps, emitSource, ) await this.syncService.sync(syncOptions) } - public async changeItem( - itemToLookupUuidFor: Models.DecryptedItemInterface, + public async changeItem( + itemToLookupUuidFor: DecryptedItemInterface, mutate: (mutator: M) => void, updateTimestamps = true, - ): Promise { + ): Promise { await this.itemManager.changeItems( [itemToLookupUuidFor], mutate, - updateTimestamps ? Models.MutationType.UpdateUserTimestamps : Models.MutationType.NoUpdateUserTimestamps, + updateTimestamps ? MutationType.UpdateUserTimestamps : MutationType.NoUpdateUserTimestamps, ) return this.itemManager.findItem(itemToLookupUuidFor.uuid) } - public async changeItems( - itemsToLookupUuidsFor: Models.DecryptedItemInterface[], + public async changeItems( + itemsToLookupUuidsFor: DecryptedItemInterface[], mutate: (mutator: M) => void, updateTimestamps = true, - ): Promise<(Models.DecryptedItemInterface | undefined)[]> { + ): Promise<(DecryptedItemInterface | undefined)[]> { return this.itemManager.changeItems( itemsToLookupUuidsFor, mutate, - updateTimestamps ? Models.MutationType.UpdateUserTimestamps : Models.MutationType.NoUpdateUserTimestamps, + updateTimestamps ? MutationType.UpdateUserTimestamps : MutationType.NoUpdateUserTimestamps, ) } public async runTransactionalMutations( transactions: TransactionalMutation[], - emitSource = Models.PayloadEmitSource.LocalChanged, + emitSource = PayloadEmitSource.LocalChanged, payloadSourceKey?: string, - ): Promise<(Models.DecryptedItemInterface | undefined)[]> { + ): Promise<(DecryptedItemInterface | undefined)[]> { return this.itemManager.runTransactionalMutations(transactions, emitSource, payloadSourceKey) } public async runTransactionalMutation( transaction: TransactionalMutation, - emitSource = Models.PayloadEmitSource.LocalChanged, + emitSource = PayloadEmitSource.LocalChanged, payloadSourceKey?: string, - ): Promise { + ): Promise { return this.itemManager.runTransactionalMutation(transaction, emitSource, payloadSourceKey) } - async protectItems( - items: I[], - ): Promise { + async protectItems(items: I[]): Promise { const protectedItems = await this.itemManager.changeItems( items, (mutator) => { mutator.protected = true }, - Models.MutationType.NoUpdateUserTimestamps, + MutationType.NoUpdateUserTimestamps, ) void this.syncService.sync() return protectedItems } - async unprotectItems( + async unprotectItems( items: I[], reason: ChallengeReason, ): Promise { @@ -166,74 +178,69 @@ export class MutatorService extends AbstractService implements MutatorClientInte (mutator) => { mutator.protected = false }, - Models.MutationType.NoUpdateUserTimestamps, + MutationType.NoUpdateUserTimestamps, ) void this.syncService.sync() return unprotectedItems } - public async protectNote(note: Models.SNNote): Promise { + public async protectNote(note: SNNote): Promise { const result = await this.protectItems([note]) return result[0] } - public async unprotectNote(note: Models.SNNote): Promise { + public async unprotectNote(note: SNNote): Promise { const result = await this.unprotectItems([note], ChallengeReason.UnprotectNote) return result ? result[0] : undefined } - public async protectNotes(notes: Models.SNNote[]): Promise { + public async protectNotes(notes: SNNote[]): Promise { return this.protectItems(notes) } - public async unprotectNotes(notes: Models.SNNote[]): Promise { + public async unprotectNotes(notes: SNNote[]): Promise { const results = await this.unprotectItems(notes, ChallengeReason.UnprotectNote) return results || [] } - async protectFile(file: Models.FileItem): Promise { + async protectFile(file: FileItem): Promise { const result = await this.protectItems([file]) return result[0] } - async unprotectFile(file: Models.FileItem): Promise { + async unprotectFile(file: FileItem): Promise { const result = await this.unprotectItems([file], ChallengeReason.UnprotectFile) return result ? result[0] : undefined } - public async mergeItem( - item: Models.DecryptedItemInterface, - source: Models.PayloadEmitSource, - ): Promise { + public async mergeItem(item: DecryptedItemInterface, source: PayloadEmitSource): Promise { return this.itemManager.emitItemFromPayload(item.payloadRepresentation(), source) } public createTemplateItem< - C extends Models.ItemContent = Models.ItemContent, - I extends Models.DecryptedItemInterface = Models.DecryptedItemInterface, + C extends ItemContent = ItemContent, + I extends DecryptedItemInterface = DecryptedItemInterface, >(contentType: ContentType, content?: C): I { return this.itemManager.createTemplateItem(contentType, content) } public async setItemNeedsSync( - item: Models.DecryptedItemInterface, + item: DecryptedItemInterface, updateTimestamps = false, - ): Promise { + ): Promise { return this.itemManager.setItemDirty(item, updateTimestamps) } - public async setItemsNeedsSync( - items: Models.DecryptedItemInterface[], - ): Promise<(Models.DecryptedItemInterface | undefined)[]> { + public async setItemsNeedsSync(items: DecryptedItemInterface[]): Promise<(DecryptedItemInterface | undefined)[]> { return this.itemManager.setItemsDirty(items) } - public async deleteItem(item: Models.DecryptedItemInterface | Models.EncryptedItemInterface): Promise { + public async deleteItem(item: DecryptedItemInterface | EncryptedItemInterface): Promise { return this.deleteItems([item]) } - public async deleteItems(items: (Models.DecryptedItemInterface | Models.EncryptedItemInterface)[]): Promise { + public async deleteItems(items: (DecryptedItemInterface | EncryptedItemInterface)[]): Promise { await this.itemManager.setItemsToBeDeleted(items) await this.syncService.sync() } @@ -243,7 +250,7 @@ export class MutatorService extends AbstractService implements MutatorClientInte await this.syncService.sync() } - public duplicateItem( + public duplicateItem( item: T, additionalContent?: Partial, ): Promise { @@ -257,29 +264,29 @@ export class MutatorService extends AbstractService implements MutatorClientInte return this.syncService.sync() } - public async setTagParent(parentTag: Models.SNTag, childTag: Models.SNTag): Promise { + public async setTagParent(parentTag: SNTag, childTag: SNTag): Promise { await this.itemManager.setTagParent(parentTag, childTag) } - public async unsetTagParent(childTag: Models.SNTag): Promise { + public async unsetTagParent(childTag: SNTag): Promise { await this.itemManager.unsetTagParent(childTag) } - public async findOrCreateTag(title: string): Promise { + public async findOrCreateTag(title: string): Promise { return this.itemManager.findOrCreateTagByTitle(title) } /** Creates and returns the tag but does not run sync. Callers must perform sync. */ - public async createTagOrSmartView(title: string): Promise { + public async createTagOrSmartView(title: string): Promise { return this.itemManager.createTagOrSmartView(title) } - public async toggleComponent(component: Models.SNComponent): Promise { + public async toggleComponent(component: SNComponent): Promise { await this.componentManager.toggleComponent(component.uuid) await this.syncService.sync() } - public async toggleTheme(theme: Models.SNComponent): Promise { + public async toggleTheme(theme: SNComponent): Promise { await this.componentManager.toggleTheme(theme.uuid) await this.syncService.sync() } @@ -289,7 +296,7 @@ export class MutatorService extends AbstractService implements MutatorClientInte awaitSync = false, ): Promise< | { - affectedItems: Models.DecryptedItemInterface[] + affectedItems: DecryptedItemInterface[] errorCount: number } | { @@ -342,7 +349,7 @@ export class MutatorService extends AbstractService implements MutatorClientInte if (isEncryptedTransferPayload(item)) { return CreateEncryptedBackupFileContextPayload(item) } else { - return CreateDecryptedBackupFileContextPayload(item as Models.BackupFileDecryptedContextualPayload) + return CreateDecryptedBackupFileContextPayload(item as BackupFileDecryptedContextualPayload) } }) @@ -355,9 +362,9 @@ export class MutatorService extends AbstractService implements MutatorClientInte const validPayloads = decryptedPayloadsOrError.filter(isDecryptedPayload).map((payload) => { /* Don't want to activate any components during import process in * case of exceptions breaking up the import proccess */ - if (payload.content_type === ContentType.Component && (payload.content as Models.ComponentContent).active) { - const typedContent = payload as Models.DecryptedPayloadInterface - return Models.CopyPayloadWithContentOverride(typedContent, { + if (payload.content_type === ContentType.Component && (payload.content as ComponentContent).active) { + const typedContent = payload as DecryptedPayloadInterface + return CopyPayloadWithContentOverride(typedContent, { active: false, }) } else { @@ -376,7 +383,7 @@ export class MutatorService extends AbstractService implements MutatorClientInte await promise } - const affectedItems = this.itemManager.findItems(affectedUuids) as Models.DecryptedItemInterface[] + const affectedItems = this.itemManager.findItems(affectedUuids) as DecryptedItemInterface[] return { affectedItems: affectedItems, diff --git a/packages/snjs/lib/Services/Mutator/index.ts b/packages/snjs/lib/Services/Mutator/index.ts index ae73aaa1c..0ed275311 100644 --- a/packages/snjs/lib/Services/Mutator/index.ts +++ b/packages/snjs/lib/Services/Mutator/index.ts @@ -1,2 +1 @@ -export * from './MutatorClientInterface' export * from './MutatorService' diff --git a/packages/ui-services/.eslintignore b/packages/ui-services/.eslintignore new file mode 100644 index 000000000..5a19e8ace --- /dev/null +++ b/packages/ui-services/.eslintignore @@ -0,0 +1,3 @@ +node_modules +dist +coverage \ No newline at end of file diff --git a/packages/ui-services/.eslintrc b/packages/ui-services/.eslintrc new file mode 100644 index 000000000..42e723b15 --- /dev/null +++ b/packages/ui-services/.eslintrc @@ -0,0 +1,9 @@ +{ + "extends": "../../.eslintrc", + "parserOptions": { + "project": "./linter.tsconfig.json" + }, + "rules": { + "@typescript-eslint/no-explicit-any": ["warn", { "ignoreRestArgs": true }] + } +} diff --git a/packages/ui-services/.gitignore b/packages/ui-services/.gitignore new file mode 100644 index 000000000..1521c8b76 --- /dev/null +++ b/packages/ui-services/.gitignore @@ -0,0 +1 @@ +dist diff --git a/packages/ui-services/jest.config.js b/packages/ui-services/jest.config.js new file mode 100644 index 000000000..ad1ceabb0 --- /dev/null +++ b/packages/ui-services/jest.config.js @@ -0,0 +1,11 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const base = require('../../node_modules/@standardnotes/config/src/jest.json'); + +module.exports = { + ...base, + globals: { + 'ts-jest': { + tsconfig: 'tsconfig.json', + }, + } +}; diff --git a/packages/ui-services/linter.tsconfig.json b/packages/ui-services/linter.tsconfig.json new file mode 100644 index 000000000..c1a7d22c5 --- /dev/null +++ b/packages/ui-services/linter.tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["dist"] +} diff --git a/packages/ui-services/package.json b/packages/ui-services/package.json new file mode 100644 index 000000000..4fae95890 --- /dev/null +++ b/packages/ui-services/package.json @@ -0,0 +1,41 @@ +{ + "name": "@standardnotes/ui-services", + "version": "1.0.0", + "engines": { + "node": ">=16.0.0 <17.0.0" + }, + "description": "UI Services for Standard Notes clients", + "main": "dist/index.js", + "author": "Standard Notes", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "private": true, + "license": "AGPL-3.0-or-later", + "scripts": { + "clean": "rm -fr dist", + "prestart": "yarn clean", + "start": "tsc -p tsconfig.json --watch", + "prebuild": "yarn clean", + "build": "tsc -p tsconfig.json", + "lint": "eslint . --ext .ts", + "test:unit": "jest spec --coverage" + }, + "dependencies": { + "@standardnotes/filepicker": "workspace:^", + "@standardnotes/services": "workspace:^", + "@standardnotes/snjs": "workspace:^", + "@standardnotes/styles": "workspace:^", + "@standardnotes/toast": "workspace:^", + "@standardnotes/utils": "workspace:^" + }, + "devDependencies": { + "@types/jest": "^28.1.5", + "@typescript-eslint/eslint-plugin": "^5.30.0", + "@typescript-eslint/parser": "^5.12.1", + "eslint-plugin-prettier": "*", + "jest": "^28.1.2", + "ts-jest": "^28.0.5" + } +} diff --git a/packages/web/src/javascripts/Services/AlertService.ts b/packages/ui-services/src/Alert/Functions.ts similarity index 62% rename from packages/web/src/javascripts/Services/AlertService.ts rename to packages/ui-services/src/Alert/Functions.ts index 8b06672b2..81c4c2bf7 100644 --- a/packages/web/src/javascripts/Services/AlertService.ts +++ b/packages/ui-services/src/Alert/Functions.ts @@ -1,4 +1,3 @@ -import { AlertService, ButtonType } from '@standardnotes/services' import { sanitizeHtmlString } from '@standardnotes/utils' import { SKAlert } from '@standardnotes/styles' @@ -65,37 +64,3 @@ export function alertDialog({ alert.present() }) } - -export class WebAlertService extends AlertService { - alert(text: string, title?: string, closeButtonText?: string) { - return alertDialog({ text, title, closeButtonText }) - } - - confirm( - text: string, - title?: string, - confirmButtonText?: string, - confirmButtonType?: ButtonType, - cancelButtonText?: string, - ): Promise { - return confirmDialog({ - text, - title, - confirmButtonText, - cancelButtonText, - confirmButtonStyle: confirmButtonType === ButtonType.Danger ? 'danger' : 'info', - }) - } - - blockingDialog(text: string, title?: string) { - const alert = new SKAlert({ - title: title && sanitizeHtmlString(title), - text: sanitizeHtmlString(text), - buttons: [], - }) - alert.present() - return () => { - alert.dismiss() - } - } -} diff --git a/packages/ui-services/src/Alert/WebAlertService.ts b/packages/ui-services/src/Alert/WebAlertService.ts new file mode 100644 index 000000000..0483efc1a --- /dev/null +++ b/packages/ui-services/src/Alert/WebAlertService.ts @@ -0,0 +1,38 @@ +import { AlertService, ButtonType } from '@standardnotes/services' +import { sanitizeHtmlString } from '@standardnotes/utils' +import { SKAlert } from '@standardnotes/styles' +import { alertDialog, confirmDialog } from './Functions' + +export class WebAlertService extends AlertService { + alert(text: string, title?: string, closeButtonText?: string) { + return alertDialog({ text, title, closeButtonText }) + } + + confirm( + text: string, + title?: string, + confirmButtonText?: string, + confirmButtonType?: ButtonType, + cancelButtonText?: string, + ): Promise { + return confirmDialog({ + text, + title, + confirmButtonText, + cancelButtonText, + confirmButtonStyle: confirmButtonType === ButtonType.Danger ? 'danger' : 'info', + }) + } + + blockingDialog(text: string, title?: string) { + const alert = new SKAlert({ + title: title && sanitizeHtmlString(title), + text: sanitizeHtmlString(text), + buttons: [], + }) + alert.present() + return () => { + alert.dismiss() + } + } +} diff --git a/packages/web/src/javascripts/Services/ArchiveManager.ts b/packages/ui-services/src/Archive/ArchiveManager.ts similarity index 97% rename from packages/web/src/javascripts/Services/ArchiveManager.ts rename to packages/ui-services/src/Archive/ArchiveManager.ts index 4f4976498..305dfadd1 100644 --- a/packages/web/src/javascripts/Services/ArchiveManager.ts +++ b/packages/ui-services/src/Archive/ArchiveManager.ts @@ -1,4 +1,3 @@ -import { WebApplication } from '@/Application/Application' import { parseFileName } from '@standardnotes/filepicker' import { BackupFile, @@ -6,6 +5,7 @@ import { BackupFileDecryptedContextualPayload, NoteContent, EncryptedItemInterface, + SNApplication, } from '@standardnotes/snjs' function sanitizeFileName(name: string): string { @@ -27,10 +27,10 @@ type ZippableData = { type ObjectURL = string export class ArchiveManager { - private readonly application: WebApplication + private readonly application: SNApplication private textFile?: string - constructor(application: WebApplication) { + constructor(application: SNApplication) { this.application = application } diff --git a/packages/web/src/javascripts/Services/IOService.ts b/packages/ui-services/src/IO/IOService.ts similarity index 100% rename from packages/web/src/javascripts/Services/IOService.ts rename to packages/ui-services/src/IO/IOService.ts diff --git a/packages/web/src/javascripts/Services/AutolockService.ts b/packages/ui-services/src/Security/AutolockService.ts similarity index 100% rename from packages/web/src/javascripts/Services/AutolockService.ts rename to packages/ui-services/src/Security/AutolockService.ts diff --git a/packages/web/src/javascripts/Services/LocalStorage.ts b/packages/ui-services/src/Storage/LocalStorage.ts similarity index 61% rename from packages/web/src/javascripts/Services/LocalStorage.ts rename to packages/ui-services/src/Storage/LocalStorage.ts index bf7859cf3..d905bc8a0 100644 --- a/packages/web/src/javascripts/Services/LocalStorage.ts +++ b/packages/ui-services/src/Storage/LocalStorage.ts @@ -1,5 +1,3 @@ -import { useCallback, useState } from 'react' - export enum StorageKey { AnonymousUserId = 'AnonymousUserId', ShowBetaWarning = 'ShowBetaWarning', @@ -26,19 +24,3 @@ export const storage = { localStorage.removeItem(key) }, } - -type LocalStorageHookReturnType = [StorageValue[Key] | null, (value: StorageValue[Key]) => void] - -export const useLocalStorageItem = (key: Key): LocalStorageHookReturnType => { - const [value, setValue] = useState(() => storage.get(key)) - - const set = useCallback( - (value: StorageValue[Key]) => { - storage.set(key, value) - setValue(value) - }, - [key], - ) - - return [value, set] -} diff --git a/packages/web/src/javascripts/Services/ThemeManager.ts b/packages/ui-services/src/Theme/ThemeManager.ts similarity index 98% rename from packages/web/src/javascripts/Services/ThemeManager.ts rename to packages/ui-services/src/Theme/ThemeManager.ts index 4002b64d0..bdc2049ff 100644 --- a/packages/web/src/javascripts/Services/ThemeManager.ts +++ b/packages/ui-services/src/Theme/ThemeManager.ts @@ -1,4 +1,3 @@ -import { WebApplication } from '@/Application/Application' import { StorageValueModes, ApplicationService, @@ -13,6 +12,7 @@ import { InternalEventBus, PayloadEmitSource, LocalStorageDecryptedContextualPayload, + WebApplicationInterface, } from '@standardnotes/snjs' import { dismissToast, ToastType, addTimedToast } from '@standardnotes/toast' @@ -26,7 +26,7 @@ export class ThemeManager extends ApplicationService { private unregisterStream!: () => void private lastUseDeviceThemeSettings = false - constructor(application: WebApplication) { + constructor(application: WebApplicationInterface) { super(application, new InternalEventBus()) this.colorSchemeEventHandler = this.colorSchemeEventHandler.bind(this) } @@ -80,7 +80,7 @@ export class ThemeManager extends ApplicationService { } get webApplication() { - return this.application as WebApplication + return this.application as WebApplicationInterface } override deinit() { diff --git a/packages/ui-services/src/index.ts b/packages/ui-services/src/index.ts new file mode 100644 index 000000000..10a482bde --- /dev/null +++ b/packages/ui-services/src/index.ts @@ -0,0 +1,7 @@ +export * from './Alert/Functions' +export * from './Alert/WebAlertService' +export * from './Archive/ArchiveManager' +export * from './IO/IOService' +export * from './Security/AutolockService' +export * from './Storage/LocalStorage' +export * from './Theme/ThemeManager' diff --git a/packages/ui-services/tsconfig.json b/packages/ui-services/tsconfig.json new file mode 100644 index 000000000..e2096ea2c --- /dev/null +++ b/packages/ui-services/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../node_modules/@standardnotes/config/src/tsconfig.json", + "compilerOptions": { + "skipLibCheck": true, + "rootDir": "./src", + "outDir": "./dist", + "jsx": "react-jsx", + }, + "include": [ + "src/**/*" + ], + "references": [], + "exclude": ["**/*.spec.ts", "dist", "node_modules"] +} diff --git a/packages/web/package.json b/packages/web/package.json index f491e22d0..cd2e212cf 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -82,6 +82,7 @@ "@standardnotes/snjs": "workspace:*", "@standardnotes/styles": "workspace:*", "@standardnotes/toast": "workspace:*", + "@standardnotes/ui-services": "workspace:^", "@zip.js/zip.js": "^2.4.10", "mobx": "^6.5.0", "mobx-react-lite": "^3.3.0", diff --git a/packages/web/src/javascripts/Application/Application.ts b/packages/web/src/javascripts/Application/Application.ts index 1de3a3dba..699df2c37 100644 --- a/packages/web/src/javascripts/Application/Application.ts +++ b/packages/web/src/javascripts/Application/Application.ts @@ -1,11 +1,5 @@ import { WebCrypto } from '@/Application/Crypto' -import { WebAlertService } from '@/Services/AlertService' -import { ArchiveManager } from '@/Services/ArchiveManager' -import { AutolockService } from '@/Services/AutolockService' -import { DesktopManager } from '@/Services/DesktopManager' -import { IOService } from '@/Services/IOService' -import { ThemeManager } from '@/Services/ThemeManager' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { WebOrDesktopDevice } from '@/Application/Device/WebOrDesktopDevice' import { DeinitSource, @@ -21,11 +15,14 @@ import { SNTag, ContentType, DecryptedItemInterface, + WebAppEvent, + WebApplicationInterface, } from '@standardnotes/snjs' import { makeObservable, observable } from 'mobx' import { PanelResizedData } from '@/Types/PanelResizedData' -import { WebAppEvent } from './WebAppEvent' import { isDesktopApplication } from '@/Utils' +import { DesktopManager } from './Device/DesktopManager' +import { ArchiveManager, AutolockService, IOService, ThemeManager, WebAlertService } from '@standardnotes/ui-services' type WebServices = { viewControllerManager: ViewControllerManager @@ -38,7 +35,7 @@ type WebServices = { export type WebEventObserver = (event: WebAppEvent, data?: unknown) => void -export class WebApplication extends SNApplication { +export class WebApplication extends SNApplication implements WebApplicationInterface { private webServices!: WebServices private webEventObservers: WebEventObserver[] = [] public itemControllerGroup: ItemGroupController diff --git a/packages/web/src/javascripts/Application/ApplicationGroup.ts b/packages/web/src/javascripts/Application/ApplicationGroup.ts index a5fbca58e..c21569ed1 100644 --- a/packages/web/src/javascripts/Application/ApplicationGroup.ts +++ b/packages/web/src/javascripts/Application/ApplicationGroup.ts @@ -6,14 +6,12 @@ import { InternalEventBus, isDesktopDevice, } from '@standardnotes/snjs' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ArchiveManager, IOService, AutolockService, ThemeManager } from '@standardnotes/ui-services' + +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { getPlatform, isDesktopApplication } from '@/Utils' -import { ArchiveManager } from '@/Services/ArchiveManager' -import { DesktopManager } from '@/Services/DesktopManager' -import { IOService } from '@/Services/IOService' -import { AutolockService } from '@/Services/AutolockService' -import { ThemeManager } from '@/Services/ThemeManager' import { WebOrDesktopDevice } from '@/Application/Device/WebOrDesktopDevice' +import { DesktopManager } from './Device/DesktopManager' const createApplication = ( descriptor: ApplicationDescriptor, diff --git a/packages/web/src/javascripts/Services/DesktopManager.ts b/packages/web/src/javascripts/Application/Device/DesktopManager.ts similarity index 94% rename from packages/web/src/javascripts/Services/DesktopManager.ts rename to packages/web/src/javascripts/Application/Device/DesktopManager.ts index ba0512e5a..2f08f1366 100644 --- a/packages/web/src/javascripts/Services/DesktopManager.ts +++ b/packages/web/src/javascripts/Application/Device/DesktopManager.ts @@ -12,9 +12,9 @@ import { assert, DesktopClientRequiresWebMethods, DesktopDeviceInterface, + WebApplicationInterface, + WebAppEvent, } from '@standardnotes/snjs' -import { WebApplication } from '@/Application/Application' -import { WebAppEvent } from '@/Application/WebAppEvent' export class DesktopManager extends ApplicationService @@ -27,12 +27,12 @@ export class DesktopManager dataLoaded = false lastSearchedText?: string - constructor(application: WebApplication, private device: DesktopDeviceInterface) { + constructor(application: WebApplicationInterface, private device: DesktopDeviceInterface) { super(application, new InternalEventBus()) } get webApplication() { - return this.application as WebApplication + return this.application as WebApplicationInterface } override deinit() { @@ -80,7 +80,7 @@ export class DesktopManager .catch(console.error) } - registerUpdateObserver(callback: (component: SNComponent) => void) { + registerUpdateObserver(callback: (component: SNComponent) => void): () => void { const observer = { callback: callback, } diff --git a/packages/web/src/javascripts/Components/Abstract/PureComponent.tsx b/packages/web/src/javascripts/Components/Abstract/PureComponent.tsx index cddb98807..e9d8fb0bb 100644 --- a/packages/web/src/javascripts/Components/Abstract/PureComponent.tsx +++ b/packages/web/src/javascripts/Components/Abstract/PureComponent.tsx @@ -1,6 +1,6 @@ import { ApplicationEvent } from '@standardnotes/snjs' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { autorun, IReactionDisposer, IReactionPublic } from 'mobx' import { Component } from 'react' diff --git a/packages/web/src/javascripts/Components/AccountMenu/AccountMenu.tsx b/packages/web/src/javascripts/Components/AccountMenu/AccountMenu.tsx index ce43a1ffb..4f44a9659 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/AccountMenu.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/AccountMenu.tsx @@ -1,5 +1,5 @@ import { observer } from 'mobx-react-lite' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { WebApplication } from '@/Application/Application' import { useCallback, FunctionComponent, KeyboardEventHandler } from 'react' import { ApplicationGroup } from '@/Application/ApplicationGroup' diff --git a/packages/web/src/javascripts/Components/AccountMenu/AdvancedOptions.tsx b/packages/web/src/javascripts/Components/AccountMenu/AdvancedOptions.tsx index ec062f624..c1668f3d3 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/AdvancedOptions.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/AdvancedOptions.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { ChangeEventHandler, FunctionComponent, useCallback, useEffect, useState } from 'react' import Checkbox from '@/Components/Checkbox/Checkbox' diff --git a/packages/web/src/javascripts/Components/AccountMenu/ConfirmPassword.tsx b/packages/web/src/javascripts/Components/AccountMenu/ConfirmPassword.tsx index 45043ab1b..ac966c431 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/ConfirmPassword.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/ConfirmPassword.tsx @@ -1,6 +1,6 @@ import { STRING_NON_MATCHING_PASSWORDS } from '@/Constants/Strings' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent, KeyboardEventHandler, useCallback, useEffect, useRef, useState } from 'react' import { AccountMenuPane } from './AccountMenuPane' diff --git a/packages/web/src/javascripts/Components/AccountMenu/CreateAccount.tsx b/packages/web/src/javascripts/Components/AccountMenu/CreateAccount.tsx index f3509965c..f0278bfbb 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/CreateAccount.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/CreateAccount.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent, KeyboardEventHandler, useCallback, useEffect, useRef, useState } from 'react' import { AccountMenuPane } from './AccountMenuPane' diff --git a/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx b/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx index 93df5edf8..fd966798b 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import Icon from '@/Components/Icon/Icon' import { SyncQueueStrategy } from '@standardnotes/snjs' diff --git a/packages/web/src/javascripts/Components/AccountMenu/MenuPaneSelector.tsx b/packages/web/src/javascripts/Components/AccountMenu/MenuPaneSelector.tsx index 4544ac6e2..4f05dd120 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/MenuPaneSelector.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/MenuPaneSelector.tsx @@ -1,6 +1,6 @@ import { WebApplication } from '@/Application/Application' import { ApplicationGroup } from '@/Application/ApplicationGroup' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent, useState } from 'react' import { AccountMenuPane } from './AccountMenuPane' diff --git a/packages/web/src/javascripts/Components/AccountMenu/SignIn.tsx b/packages/web/src/javascripts/Components/AccountMenu/SignIn.tsx index df51d3eac..240bfd3f4 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/SignIn.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/SignIn.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { isDev } from '@/Utils' import { observer } from 'mobx-react-lite' import React, { FunctionComponent, KeyboardEventHandler, useCallback, useEffect, useRef, useState } from 'react' diff --git a/packages/web/src/javascripts/Components/AccountMenu/User.tsx b/packages/web/src/javascripts/Components/AccountMenu/User.tsx index ac7d4b338..0b8a27e90 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/User.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/User.tsx @@ -1,5 +1,5 @@ import { observer } from 'mobx-react-lite' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { WebApplication } from '@/Application/Application' import { User as UserType } from '@standardnotes/snjs' diff --git a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceMenuItem.tsx b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceMenuItem.tsx index cad6d9a8b..99c950674 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceMenuItem.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceMenuItem.tsx @@ -1,7 +1,7 @@ import Icon from '@/Components/Icon/Icon' import MenuItem from '@/Components/Menu/MenuItem' import { MenuItemType } from '@/Components/Menu/MenuItemType' -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import { ApplicationDescriptor } from '@standardnotes/snjs' import { ChangeEventHandler, diff --git a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu.tsx b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu.tsx index e060d4113..574604dd5 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu.tsx @@ -1,5 +1,5 @@ import { ApplicationGroup } from '@/Application/ApplicationGroup' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { ApplicationDescriptor, ApplicationGroupEvent, ButtonType } from '@standardnotes/snjs' import { observer } from 'mobx-react-lite' import { FunctionComponent, useCallback, useEffect, useState } from 'react' diff --git a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherOption.tsx b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherOption.tsx index 0e89ed3fd..80bea1e7d 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherOption.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherOption.tsx @@ -1,6 +1,6 @@ import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants/Constants' import { ApplicationGroup } from '@/Application/ApplicationGroup' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent, useCallback, useRef, useState } from 'react' import Icon from '@/Components/Icon/Icon' diff --git a/packages/web/src/javascripts/Components/ApplicationView/ApplicationView.tsx b/packages/web/src/javascripts/Components/ApplicationView/ApplicationView.tsx index 42a49c447..43f1e2fb5 100644 --- a/packages/web/src/javascripts/Components/ApplicationView/ApplicationView.tsx +++ b/packages/web/src/javascripts/Components/ApplicationView/ApplicationView.tsx @@ -1,10 +1,9 @@ import { ApplicationGroup } from '@/Application/ApplicationGroup' import { getPlatformString, getWindowUrlParams } from '@/Utils' -import { ApplicationEvent, Challenge, removeFromArray } from '@standardnotes/snjs' +import { ApplicationEvent, Challenge, removeFromArray, WebAppEvent } from '@standardnotes/snjs' import { PANEL_NAME_NOTES, PANEL_NAME_NAVIGATION } from '@/Constants/Constants' -import { alertDialog } from '@/Services/AlertService' +import { alertDialog } from '@standardnotes/ui-services' import { WebApplication } from '@/Application/Application' -import { WebAppEvent } from '@/Application/WebAppEvent' import Navigation from '@/Components/Navigation/Navigation' import NoteGroupView from '@/Components/NoteGroupView/NoteGroupView' import Footer from '@/Components/Footer/Footer' diff --git a/packages/web/src/javascripts/Components/AttachedFilesPopover/PopoverFileItem.tsx b/packages/web/src/javascripts/Components/AttachedFilesPopover/PopoverFileItem.tsx index 03d28ca47..65f9eaf04 100644 --- a/packages/web/src/javascripts/Components/AttachedFilesPopover/PopoverFileItem.tsx +++ b/packages/web/src/javascripts/Components/AttachedFilesPopover/PopoverFileItem.tsx @@ -1,5 +1,5 @@ import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants/Constants' -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import { formatSizeToReadableString } from '@standardnotes/filepicker' import { FileItem } from '@standardnotes/snjs' import { diff --git a/packages/web/src/javascripts/Components/ChallengeModal/ChallengeModal.tsx b/packages/web/src/javascripts/Components/ChallengeModal/ChallengeModal.tsx index 20105446c..e8b3356c3 100644 --- a/packages/web/src/javascripts/Components/ChallengeModal/ChallengeModal.tsx +++ b/packages/web/src/javascripts/Components/ChallengeModal/ChallengeModal.tsx @@ -15,7 +15,7 @@ import Icon from '@/Components/Icon/Icon' import ChallengeModalPrompt from './ChallengePrompt' import LockscreenWorkspaceSwitcher from './LockscreenWorkspaceSwitcher' import { ApplicationGroup } from '@/Application/ApplicationGroup' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { ChallengeModalValues } from './ChallengeModalValues' type Props = { diff --git a/packages/web/src/javascripts/Components/ChallengeModal/LockscreenWorkspaceSwitcher.tsx b/packages/web/src/javascripts/Components/ChallengeModal/LockscreenWorkspaceSwitcher.tsx index ff1664291..efd7e0a5e 100644 --- a/packages/web/src/javascripts/Components/ChallengeModal/LockscreenWorkspaceSwitcher.tsx +++ b/packages/web/src/javascripts/Components/ChallengeModal/LockscreenWorkspaceSwitcher.tsx @@ -1,5 +1,5 @@ import { ApplicationGroup } from '@/Application/ApplicationGroup' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { FunctionComponent, useCallback, useRef, useState } from 'react' import WorkspaceSwitcherMenu from '@/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu' import Button from '@/Components/Button/Button' diff --git a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx index 3ad137d03..46ad10a52 100644 --- a/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx +++ b/packages/web/src/javascripts/Components/ChangeEditor/ChangeEditorButton.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent, useCallback, useRef, useState } from 'react' import Icon from '@/Components/Icon/Icon' diff --git a/packages/web/src/javascripts/Components/ComponentView/ComponentView.tsx b/packages/web/src/javascripts/Components/ComponentView/ComponentView.tsx index 40df6f36d..7407c01dd 100644 --- a/packages/web/src/javascripts/Components/ComponentView/ComponentView.tsx +++ b/packages/web/src/javascripts/Components/ComponentView/ComponentView.tsx @@ -3,7 +3,7 @@ import { FeatureStatus, SNComponent, dateToLocalizedString, - ComponentViewer, + ComponentViewerInterface, ComponentViewerEvent, ComponentViewerError, } from '@standardnotes/snjs' @@ -19,8 +19,8 @@ import { openSubscriptionDashboard } from '@/Utils/ManageSubscription' interface IProps { application: WebApplication - componentViewer: ComponentViewer - requestReload?: (viewer: ComponentViewer, force?: boolean) => void + componentViewer: ComponentViewerInterface + requestReload?: (viewer: ComponentViewerInterface, force?: boolean) => void onLoad?: (component: SNComponent) => void } diff --git a/packages/web/src/javascripts/Components/ConfirmSignoutModal/ConfirmSignoutModal.tsx b/packages/web/src/javascripts/Components/ConfirmSignoutModal/ConfirmSignoutModal.tsx index 50b8ace93..9ba529753 100644 --- a/packages/web/src/javascripts/Components/ConfirmSignoutModal/ConfirmSignoutModal.tsx +++ b/packages/web/src/javascripts/Components/ConfirmSignoutModal/ConfirmSignoutModal.tsx @@ -2,7 +2,7 @@ import { FunctionComponent, useEffect, useRef, useState } from 'react' import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog' import { STRING_SIGN_OUT_CONFIRMATION } from '@/Constants/Strings' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { ApplicationGroup } from '@/Application/ApplicationGroup' import { isDesktopApplication } from '@/Utils' diff --git a/packages/web/src/javascripts/Components/ContentListView/ContentList.tsx b/packages/web/src/javascripts/Components/ContentListView/ContentList.tsx index 044964fea..2e4106930 100644 --- a/packages/web/src/javascripts/Components/ContentListView/ContentList.tsx +++ b/packages/web/src/javascripts/Components/ContentListView/ContentList.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import { UuidString } from '@standardnotes/snjs' import { observer } from 'mobx-react-lite' import { FunctionComponent, KeyboardEventHandler, UIEventHandler, useCallback } from 'react' diff --git a/packages/web/src/javascripts/Components/ContentListView/ContentListView.tsx b/packages/web/src/javascripts/Components/ContentListView/ContentListView.tsx index 7af98b13c..febe12a7b 100644 --- a/packages/web/src/javascripts/Components/ContentListView/ContentListView.tsx +++ b/packages/web/src/javascripts/Components/ContentListView/ContentListView.tsx @@ -1,4 +1,4 @@ -import { KeyboardKey, KeyboardModifier } from '@/Services/IOService' +import { KeyboardKey, KeyboardModifier } from '@standardnotes/ui-services' import { WebApplication } from '@/Application/Application' import { PANEL_NAME_NOTES } from '@/Constants/Constants' import { PrefKey, SystemViewId } from '@standardnotes/snjs' diff --git a/packages/web/src/javascripts/Components/FilePreview/FilePreviewModal.tsx b/packages/web/src/javascripts/Components/FilePreview/FilePreviewModal.tsx index 093e09237..cc84b9a6e 100644 --- a/packages/web/src/javascripts/Components/FilePreview/FilePreviewModal.tsx +++ b/packages/web/src/javascripts/Components/FilePreview/FilePreviewModal.tsx @@ -5,8 +5,8 @@ import { getFileIconComponent } from '@/Components/AttachedFilesPopover/getFileI import Icon from '@/Components/Icon/Icon' import FilePreviewInfoPanel from './FilePreviewInfoPanel' import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants/Constants' -import { KeyboardKey } from '@/Services/IOService' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { KeyboardKey } from '@standardnotes/ui-services' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import FilePreview from './FilePreview' diff --git a/packages/web/src/javascripts/Components/FileView/FileViewProps.tsx b/packages/web/src/javascripts/Components/FileView/FileViewProps.tsx index 0cb9a4fb1..9becc9ab3 100644 --- a/packages/web/src/javascripts/Components/FileView/FileViewProps.tsx +++ b/packages/web/src/javascripts/Components/FileView/FileViewProps.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { FileItem } from '@standardnotes/snjs/dist/@types' export type FileViewProps = { diff --git a/packages/web/src/javascripts/Components/Footer/Footer.tsx b/packages/web/src/javascripts/Components/Footer/Footer.tsx index eeddf9ea0..17f38b597 100644 --- a/packages/web/src/javascripts/Components/Footer/Footer.tsx +++ b/packages/web/src/javascripts/Components/Footer/Footer.tsx @@ -1,9 +1,8 @@ import { WebApplication } from '@/Application/Application' -import { WebAppEvent } from '@/Application/WebAppEvent' import { ApplicationGroup } from '@/Application/ApplicationGroup' import { PureComponent } from '@/Components/Abstract/PureComponent' import { destroyAllObjectProperties, preventRefreshing } from '@/Utils' -import { ApplicationEvent, ApplicationDescriptor } from '@standardnotes/snjs' +import { ApplicationEvent, ApplicationDescriptor, WebAppEvent } from '@standardnotes/snjs' import { STRING_NEW_UPDATE_READY, STRING_CONFIRM_APP_QUIT_DURING_UPGRADE, @@ -11,7 +10,7 @@ import { STRING_UPGRADE_ACCOUNT_CONFIRM_TITLE, STRING_UPGRADE_ACCOUNT_CONFIRM_BUTTON, } from '@/Constants/Strings' -import { alertDialog, confirmDialog } from '@/Services/AlertService' +import { alertDialog, confirmDialog } from '@standardnotes/ui-services' import Icon from '@/Components/Icon/Icon' import SyncResolutionMenu from '@/Components/SyncResolutionMenu/SyncResolutionMenu' import { Fragment } from 'react' diff --git a/packages/web/src/javascripts/Components/Menu/Menu.tsx b/packages/web/src/javascripts/Components/Menu/Menu.tsx index e88783c27..cd9606ab6 100644 --- a/packages/web/src/javascripts/Components/Menu/Menu.tsx +++ b/packages/web/src/javascripts/Components/Menu/Menu.tsx @@ -7,7 +7,7 @@ import { useEffect, useRef, } from 'react' -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import { useListKeyboardNavigation } from '@/Hooks/useListKeyboardNavigation' type MenuProps = { diff --git a/packages/web/src/javascripts/Components/NoteTags/NoteTag.tsx b/packages/web/src/javascripts/Components/NoteTags/NoteTag.tsx index 3c791fc12..27d89f864 100644 --- a/packages/web/src/javascripts/Components/NoteTags/NoteTag.tsx +++ b/packages/web/src/javascripts/Components/NoteTags/NoteTag.tsx @@ -8,7 +8,7 @@ import { useRef, useState, } from 'react' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { SNTag } from '@standardnotes/snjs' import { observer } from 'mobx-react-lite' diff --git a/packages/web/src/javascripts/Components/NoteTags/NoteTagsContainer.tsx b/packages/web/src/javascripts/Components/NoteTags/NoteTagsContainer.tsx index dba5d5f6d..a7c8ded1f 100644 --- a/packages/web/src/javascripts/Components/NoteTags/NoteTagsContainer.tsx +++ b/packages/web/src/javascripts/Components/NoteTags/NoteTagsContainer.tsx @@ -1,4 +1,4 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import AutocompleteTagInput from '@/Components/TagAutocomplete/AutocompleteTagInput' import NoteTag from './NoteTag' diff --git a/packages/web/src/javascripts/Components/NoteView/NoteView.test.ts b/packages/web/src/javascripts/Components/NoteView/NoteView.test.ts index c3819bc5a..544200089 100644 --- a/packages/web/src/javascripts/Components/NoteView/NoteView.test.ts +++ b/packages/web/src/javascripts/Components/NoteView/NoteView.test.ts @@ -3,7 +3,7 @@ */ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { NotesController } from '@/Controllers/NotesController' import { ApplicationEvent, diff --git a/packages/web/src/javascripts/Components/NoteView/NoteView.tsx b/packages/web/src/javascripts/Components/NoteView/NoteView.tsx index a26f4b9c1..fa6e3f0c4 100644 --- a/packages/web/src/javascripts/Components/NoteView/NoteView.tsx +++ b/packages/web/src/javascripts/Components/NoteView/NoteView.tsx @@ -8,16 +8,16 @@ import { SNNote, ComponentArea, PrefKey, - ComponentViewer, + ComponentViewerInterface, ProposedSecondsToDeferUILevelSessionExpirationDuringActiveInteraction, NoteViewController, PayloadEmitSource, + WebAppEvent, } from '@standardnotes/snjs' import { debounce, isDesktopApplication } from '@/Utils' import { EditorEventSource } from '../../Types/EditorEventSource' -import { KeyboardModifier, KeyboardKey } from '@/Services/IOService' +import { confirmDialog, KeyboardModifier, KeyboardKey } from '@standardnotes/ui-services' import { STRING_DELETE_PLACEHOLDER_ATTEMPT, STRING_DELETE_LOCKED_ATTEMPT, StringDeleteNote } from '@/Constants/Strings' -import { confirmDialog } from '@/Services/AlertService' import { PureComponent } from '@/Components/Abstract/PureComponent' import ProtectedItemOverlay from '@/Components/ProtectedItemOverlay/ProtectedItemOverlay' import PinNoteButton from '@/Components/PinNoteButton/PinNoteButton' @@ -35,7 +35,6 @@ import { } from './TransactionFunctions' import { reloadFont } from './FontFunctions' import { NoteViewProps } from './NoteViewProps' -import { WebAppEvent } from '@/Application/WebAppEvent' import IndicatorCircle from '../IndicatorCircle/IndicatorCircle' const MINIMUM_STATUS_DURATION = 400 @@ -53,7 +52,7 @@ function sortAlphabetically(array: SNComponent[]): SNComponent[] { type State = { availableStackComponents: SNComponent[] - editorComponentViewer?: ComponentViewer + editorComponentViewer?: ComponentViewerInterface editorComponentViewerDidAlreadyReload?: boolean editorStateDidLoad: boolean editorTitle: string @@ -68,7 +67,7 @@ type State = { showLockedIcon: boolean showProtectedWarning: boolean spellcheck: boolean - stackComponentViewers: ComponentViewer[] + stackComponentViewers: ComponentViewerInterface[] syncTakingTooLong: boolean /** Setting to true then false will allow the main content textarea to be destroyed * then re-initialized. Used when reloading spellcheck status. */ @@ -404,7 +403,10 @@ class NoteView extends PureComponent { return viewer } - public editorComponentViewerRequestsReload = async (viewer: ComponentViewer, force?: boolean): Promise => { + public editorComponentViewerRequestsReload = async ( + viewer: ComponentViewerInterface, + force?: boolean, + ): Promise => { if (this.state.editorComponentViewerDidAlreadyReload && !force) { return } @@ -726,7 +728,7 @@ class NoteView extends PureComponent { return !viewerComponentExistsInEnabledComponents }) - const newViewers: ComponentViewer[] = [] + const newViewers: ComponentViewerInterface[] = [] for (const component of needsNewViewer) { newViewers.push(this.application.componentManager.createComponentViewer(component, this.note.uuid)) } diff --git a/packages/web/src/javascripts/Components/NotesOptions/AddTagOption.tsx b/packages/web/src/javascripts/Components/NotesOptions/AddTagOption.tsx index eff32d6c0..264903255 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/AddTagOption.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/AddTagOption.tsx @@ -4,7 +4,7 @@ import Icon from '@/Components/Icon/Icon' import { NavigationController } from '@/Controllers/Navigation/NavigationController' import { NotesController } from '@/Controllers/NotesController' import { NoteTagsController } from '@/Controllers/NoteTagsController' -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import Popover from '../Popover/Popover' type Props = { diff --git a/packages/web/src/javascripts/Components/NotesOptions/ChangeEditorOption.tsx b/packages/web/src/javascripts/Components/NotesOptions/ChangeEditorOption.tsx index 8fdfbff64..9ed3b0a51 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/ChangeEditorOption.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/ChangeEditorOption.tsx @@ -1,4 +1,4 @@ -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import { WebApplication } from '@/Application/Application' import { SNNote } from '@standardnotes/snjs' import { FunctionComponent, useCallback, useRef, useState } from 'react' diff --git a/packages/web/src/javascripts/Components/NotesOptions/ListedActionsOption.tsx b/packages/web/src/javascripts/Components/NotesOptions/ListedActionsOption.tsx index 0bceef05a..89814d1f0 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/ListedActionsOption.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/ListedActionsOption.tsx @@ -3,7 +3,7 @@ import { SNNote } from '@standardnotes/snjs' import { FunctionComponent, useCallback, useRef, useState } from 'react' import Icon from '@/Components/Icon/Icon' import ListedActionsMenu from './ListedActionsMenu' -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import Popover from '../Popover/Popover' type Props = { diff --git a/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx b/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx index 5e39547c0..263ba395e 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx @@ -3,7 +3,7 @@ import Switch from '@/Components/Switch/Switch' import { observer } from 'mobx-react-lite' import { useState, useEffect, useMemo, useCallback, FunctionComponent } from 'react' import { SNApplication, SNComponent, SNNote } from '@standardnotes/snjs' -import { KeyboardModifier } from '@/Services/IOService' +import { KeyboardModifier } from '@standardnotes/ui-services' import ChangeEditorOption from './ChangeEditorOption' import { BYTES_IN_ONE_MEGABYTE } from '@/Constants/Constants' import ListedActionsOption from './ListedActionsOption' diff --git a/packages/web/src/javascripts/Components/OtherSessionsSignOut/OtherSessionsSignOut.tsx b/packages/web/src/javascripts/Components/OtherSessionsSignOut/OtherSessionsSignOut.tsx index e8efb6a68..92a0df490 100644 --- a/packages/web/src/javascripts/Components/OtherSessionsSignOut/OtherSessionsSignOut.tsx +++ b/packages/web/src/javascripts/Components/OtherSessionsSignOut/OtherSessionsSignOut.tsx @@ -1,7 +1,7 @@ import { useCallback, useRef } from 'react' import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import Button from '@/Components/Button/Button' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Account/AccountPreferences.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Account/AccountPreferences.tsx index 05236cb13..efdfbf2b7 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Account/AccountPreferences.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Account/AccountPreferences.tsx @@ -1,6 +1,6 @@ import { observer } from 'mobx-react-lite' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import Authentication from './Authentication' import Credentials from './Credentials' import Sync from './Sync' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Authentication.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Authentication.tsx index f4dd3788c..7318018e2 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Authentication.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Authentication.tsx @@ -1,7 +1,7 @@ import Button from '@/Components/Button/Button' import { Text, Title } from '@/Components/Preferences/PreferencesComponents/Content' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent } from 'react' import { AccountIllustration } from '@standardnotes/icons' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Account/ClearSessionDataView.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Account/ClearSessionDataView.tsx index 1af25f80b..0de8e3167 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Account/ClearSessionDataView.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Account/ClearSessionDataView.tsx @@ -1,5 +1,5 @@ import Button from '@/Components/Button/Button' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent } from 'react' import { Title, Text } from '../../PreferencesComponents/Content' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Credentials.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Credentials.tsx index 0388915bc..a3f7a9322 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Credentials.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Credentials.tsx @@ -6,7 +6,7 @@ import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator' import { dateToLocalizedString } from '@standardnotes/snjs' import { useCallback, useState, FunctionComponent } from 'react' import ChangeEmail from '@/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmail' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import PasswordWizard from '@/Components/PasswordWizard/PasswordWizard' import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup' import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Account/SignOutView.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Account/SignOutView.tsx index f2eeaa904..dcba67bf8 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Account/SignOutView.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Account/SignOutView.tsx @@ -2,7 +2,7 @@ import Button from '@/Components/Button/Button' import OtherSessionsSignOutContainer from '@/Components/OtherSessionsSignOut/OtherSessionsSignOut' import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent } from 'react' import { Subtitle, Title, Text } from '../../PreferencesComponents/Content' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Subscription/Subscription.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Subscription/Subscription.tsx index 1ff1c6173..6d7ffdf67 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Subscription/Subscription.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Subscription/Subscription.tsx @@ -4,7 +4,7 @@ import SubscriptionInformation from './SubscriptionInformation' import NoSubscription from './NoSubscription' import { observer } from 'mobx-react-lite' import { FunctionComponent } from 'react' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup' import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Backups/Backups.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Backups/Backups.tsx index 96faa910c..d494c826f 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Backups/Backups.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Backups/Backups.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { FunctionComponent } from 'react' import PreferencesPane from '@/Components/Preferences/PreferencesComponents/PreferencesPane' import CloudLink from './CloudBackups/CloudBackups' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackupProvider.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackupProvider.tsx index 3cd83c8bb..6d7eec50c 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackupProvider.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackupProvider.tsx @@ -19,7 +19,7 @@ import { WebApplication } from '@/Application/Application' import Button from '@/Components/Button/Button' import { isDev, openInNewTab } from '@/Utils' import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content' -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' type Props = { application: WebApplication diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Backups/DataBackups.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Backups/DataBackups.tsx index a387b2562..6b0f2356c 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Backups/DataBackups.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Backups/DataBackups.tsx @@ -1,5 +1,5 @@ import { isDesktopApplication } from '@/Utils' -import { alertDialog } from '@/Services/AlertService' +import { alertDialog } from '@standardnotes/ui-services' import { STRING_IMPORT_SUCCESS, STRING_INVALID_IMPORT_FILE, @@ -13,7 +13,7 @@ import { import { BackupFile } from '@standardnotes/snjs' import { ChangeEventHandler, MouseEventHandler, useCallback, useEffect, useRef, useState } from 'react' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { Title, Text, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content' import Button from '@/Components/Button/Button' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/General/Advanced/AdvancedSection.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/General/Advanced/AdvancedSection.tsx index ed9ff7836..042e75227 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/General/Advanced/AdvancedSection.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/General/Advanced/AdvancedSection.tsx @@ -2,7 +2,7 @@ import { FunctionComponent } from 'react' import OfflineSubscription from '@/Components/Preferences/Panes/General/Advanced/OfflineSubscription' import { WebApplication } from '@/Application/Application' import { observer } from 'mobx-react-lite' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import PackagesPreferencesSection from '@/Components/Preferences/Panes/General/Advanced/Packages/Section' import { PackageProvider } from '@/Components/Preferences/Panes/General/Advanced/Packages/Provider/PackageProvider' import AccordionItem from '@/Components/Shared/AccordionItem' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/General/Advanced/OfflineSubscription.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/General/Advanced/OfflineSubscription.tsx index 5ec34156f..4c967475b 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/General/Advanced/OfflineSubscription.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/General/Advanced/OfflineSubscription.tsx @@ -3,7 +3,7 @@ import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content import DecoratedInput from '@/Components/Input/DecoratedInput' import Button from '@/Components/Button/Button' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { STRING_REMOVE_OFFLINE_KEY_CONFIRMATION } from '@/Constants/Strings' import { ButtonType, ClientDisplayableError } from '@standardnotes/snjs' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/General/General.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/General/General.tsx index a06824b6e..db3e8a94a 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/General/General.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/General/General.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { FunctionComponent } from 'react' import { PackageProvider } from '@/Components/Preferences/Panes/General/Advanced/Packages/Provider/PackageProvider' import { observer } from 'mobx-react-lite' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/Encryption.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/Encryption.tsx index e9b1799e2..c4afb78f2 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/Encryption.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Security/Encryption.tsx @@ -1,5 +1,5 @@ import { STRING_E2E_ENABLED, STRING_ENC_NOT_ENABLED, STRING_LOCAL_ENC_ENABLED } from '@/Constants/Strings' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent } from 'react' import { Title, Text } from '../../PreferencesComponents/Content' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/EncryptionEnabled.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/EncryptionEnabled.tsx index efc3ca991..76c333b8f 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/EncryptionEnabled.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Security/EncryptionEnabled.tsx @@ -1,5 +1,5 @@ import Icon from '@/Components/Icon/Icon' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent } from 'react' import EncryptionStatusItem from './EncryptionStatusItem' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/ErroredItems.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/ErroredItems.tsx index 595a2e5ef..84665d7c4 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/ErroredItems.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Security/ErroredItems.tsx @@ -1,4 +1,4 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { Fragment, FunctionComponent, useState } from 'react' import { Text, Title, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/PasscodeLock.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/PasscodeLock.tsx index d6dff012f..06ff37bac 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/PasscodeLock.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Security/PasscodeLock.tsx @@ -10,11 +10,11 @@ import { } from '@/Constants/Strings' import { WebApplication } from '@/Application/Application' import { preventRefreshing } from '@/Utils' -import { alertDialog } from '@/Services/AlertService' +import { alertDialog } from '@standardnotes/ui-services' import { FormEvent, useCallback, useEffect, useRef, useState } from 'react' import { ApplicationEvent } from '@standardnotes/snjs' import { observer } from 'mobx-react-lite' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { Title, Text } from '@/Components/Preferences/PreferencesComponents/Content' import Button from '@/Components/Button/Button' import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/Security.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/Security.tsx index 0b01c8d23..ca37da458 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/Security.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Security/Security.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { FunctionComponent } from 'react' import TwoFactorAuthWrapper from './TwoFactorAuth/TwoFactorAuthWrapper' import { MfaProps } from './TwoFactorAuth/MfaProps' diff --git a/packages/web/src/javascripts/Components/Preferences/PreferencesProps.tsx b/packages/web/src/javascripts/Components/Preferences/PreferencesProps.tsx index 856b8e933..432b06992 100644 --- a/packages/web/src/javascripts/Components/Preferences/PreferencesProps.tsx +++ b/packages/web/src/javascripts/Components/Preferences/PreferencesProps.tsx @@ -1,6 +1,6 @@ import { WebApplication } from '@/Application/Application' import { MfaProps } from './Panes/Security/TwoFactorAuth/MfaProps' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' export interface PreferencesProps extends MfaProps { application: WebApplication diff --git a/packages/web/src/javascripts/Components/Preferences/PreferencesViewWrapperProps.tsx b/packages/web/src/javascripts/Components/Preferences/PreferencesViewWrapperProps.tsx index a7dd58638..7d9c44f77 100644 --- a/packages/web/src/javascripts/Components/Preferences/PreferencesViewWrapperProps.tsx +++ b/packages/web/src/javascripts/Components/Preferences/PreferencesViewWrapperProps.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' export interface PreferencesViewWrapperProps { viewControllerManager: ViewControllerManager diff --git a/packages/web/src/javascripts/Components/ProtectedItemOverlay/ProtectedItemOverlay.tsx b/packages/web/src/javascripts/Components/ProtectedItemOverlay/ProtectedItemOverlay.tsx index 63216aeaf..3e4cd564d 100644 --- a/packages/web/src/javascripts/Components/ProtectedItemOverlay/ProtectedItemOverlay.tsx +++ b/packages/web/src/javascripts/Components/ProtectedItemOverlay/ProtectedItemOverlay.tsx @@ -1,4 +1,4 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import Button from '@/Components/Button/Button' type Props = { diff --git a/packages/web/src/javascripts/Components/PurchaseFlow/Panes/CreateAccount.tsx b/packages/web/src/javascripts/Components/PurchaseFlow/Panes/CreateAccount.tsx index 8ff3356f4..b545673d8 100644 --- a/packages/web/src/javascripts/Components/PurchaseFlow/Panes/CreateAccount.tsx +++ b/packages/web/src/javascripts/Components/PurchaseFlow/Panes/CreateAccount.tsx @@ -1,6 +1,6 @@ import Button from '@/Components/Button/Button' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { PurchaseFlowPane } from '@/Controllers/PurchaseFlow/PurchaseFlowPane' import { observer } from 'mobx-react-lite' import { ChangeEventHandler, FunctionComponent, useEffect, useRef, useState } from 'react' diff --git a/packages/web/src/javascripts/Components/PurchaseFlow/Panes/SignIn.tsx b/packages/web/src/javascripts/Components/PurchaseFlow/Panes/SignIn.tsx index d263be3fa..6fb8ff0c6 100644 --- a/packages/web/src/javascripts/Components/PurchaseFlow/Panes/SignIn.tsx +++ b/packages/web/src/javascripts/Components/PurchaseFlow/Panes/SignIn.tsx @@ -1,6 +1,6 @@ import Button from '@/Components/Button/Button' import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { PurchaseFlowPane } from '@/Controllers/PurchaseFlow/PurchaseFlowPane' import { observer } from 'mobx-react-lite' import { ChangeEventHandler, FunctionComponent, useEffect, useRef, useState } from 'react' diff --git a/packages/web/src/javascripts/Components/PurchaseFlow/PurchaseFlowView.tsx b/packages/web/src/javascripts/Components/PurchaseFlow/PurchaseFlowView.tsx index 46fcd3ed1..fccf16066 100644 --- a/packages/web/src/javascripts/Components/PurchaseFlow/PurchaseFlowView.tsx +++ b/packages/web/src/javascripts/Components/PurchaseFlow/PurchaseFlowView.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { PurchaseFlowPane } from '@/Controllers/PurchaseFlow/PurchaseFlowPane' import { observer } from 'mobx-react-lite' import { FunctionComponent } from 'react' diff --git a/packages/web/src/javascripts/Components/PurchaseFlow/PurchaseFlowWrapperProps.tsx b/packages/web/src/javascripts/Components/PurchaseFlow/PurchaseFlowWrapperProps.tsx index 08330e0f5..9947bc014 100644 --- a/packages/web/src/javascripts/Components/PurchaseFlow/PurchaseFlowWrapperProps.tsx +++ b/packages/web/src/javascripts/Components/PurchaseFlow/PurchaseFlowWrapperProps.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' export type PurchaseFlowWrapperProps = { viewControllerManager: ViewControllerManager diff --git a/packages/web/src/javascripts/Components/SearchBar/SearchBar.tsx b/packages/web/src/javascripts/Components/SearchBar/SearchBar.tsx index 0ecd8f853..04a9ee035 100644 --- a/packages/web/src/javascripts/Components/SearchBar/SearchBar.tsx +++ b/packages/web/src/javascripts/Components/SearchBar/SearchBar.tsx @@ -1,5 +1,5 @@ import { ItemListController } from '@/Controllers/ItemList/ItemListController' -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import { useState, useCallback, KeyboardEventHandler, useRef } from 'react' import SearchOptions from '@/Components/SearchOptions/SearchOptions' import { SearchOptionsController } from '@/Controllers/SearchOptionsController' diff --git a/packages/web/src/javascripts/Components/SessionsModal/SessionsModal.tsx b/packages/web/src/javascripts/Components/SessionsModal/SessionsModal.tsx index 47218f9f8..ee7d12228 100644 --- a/packages/web/src/javascripts/Components/SessionsModal/SessionsModal.tsx +++ b/packages/web/src/javascripts/Components/SessionsModal/SessionsModal.tsx @@ -1,4 +1,4 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { SNApplication, SessionStrings, UuidString, isNullOrUndefined, RemoteSession } from '@standardnotes/snjs' import { FunctionComponent, useState, useEffect, useRef, useMemo } from 'react' import { Alert } from '@reach/alert' diff --git a/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagHint.tsx b/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagHint.tsx index 7e9ca8c68..dae670cbd 100644 --- a/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagHint.tsx +++ b/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagHint.tsx @@ -1,4 +1,4 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { useRef, useEffect, useCallback, FocusEventHandler, KeyboardEventHandler } from 'react' import Icon from '@/Components/Icon/Icon' diff --git a/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagInput.tsx b/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagInput.tsx index d0cd43c94..23864de41 100644 --- a/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagInput.tsx +++ b/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagInput.tsx @@ -9,7 +9,7 @@ import { } from 'react' import { Disclosure, DisclosurePanel } from '@reach/disclosure' import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import AutocompleteTagResult from './AutocompleteTagResult' import AutocompleteTagHint from './AutocompleteTagHint' import { observer } from 'mobx-react-lite' diff --git a/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagResult.tsx b/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagResult.tsx index e9d1c4618..8f1cc3405 100644 --- a/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagResult.tsx +++ b/packages/web/src/javascripts/Components/TagAutocomplete/AutocompleteTagResult.tsx @@ -1,4 +1,4 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { splitQueryInString } from '@/Utils/StringUtils' import { SNTag } from '@standardnotes/snjs' import { observer } from 'mobx-react-lite' diff --git a/packages/web/src/javascripts/Components/Tags/SmartViewsList.tsx b/packages/web/src/javascripts/Components/Tags/SmartViewsList.tsx index d5a13fa26..71454537f 100644 --- a/packages/web/src/javascripts/Components/Tags/SmartViewsList.tsx +++ b/packages/web/src/javascripts/Components/Tags/SmartViewsList.tsx @@ -1,4 +1,4 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent } from 'react' import SmartViewsListItem from './SmartViewsListItem' diff --git a/packages/web/src/javascripts/Components/Tags/SmartViewsSection.tsx b/packages/web/src/javascripts/Components/Tags/SmartViewsSection.tsx index 2ac055c7e..f2f48399b 100644 --- a/packages/web/src/javascripts/Components/Tags/SmartViewsSection.tsx +++ b/packages/web/src/javascripts/Components/Tags/SmartViewsSection.tsx @@ -1,4 +1,4 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent } from 'react' import SmartViewsList from './SmartViewsList' diff --git a/packages/web/src/javascripts/Components/Tags/TagsList.tsx b/packages/web/src/javascripts/Components/Tags/TagsList.tsx index 704a066e7..74e72159f 100644 --- a/packages/web/src/javascripts/Components/Tags/TagsList.tsx +++ b/packages/web/src/javascripts/Components/Tags/TagsList.tsx @@ -1,4 +1,4 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { SNTag } from '@standardnotes/snjs' import { observer } from 'mobx-react-lite' import { FunctionComponent, useCallback } from 'react' diff --git a/packages/web/src/javascripts/Components/Tags/TagsListItem.tsx b/packages/web/src/javascripts/Components/Tags/TagsListItem.tsx index 6df65b0c0..811d270a6 100644 --- a/packages/web/src/javascripts/Components/Tags/TagsListItem.tsx +++ b/packages/web/src/javascripts/Components/Tags/TagsListItem.tsx @@ -1,7 +1,7 @@ import Icon from '@/Components/Icon/Icon' import { TAG_FOLDERS_FEATURE_NAME } from '@/Constants/Constants' import { usePremiumModal } from '@/Hooks/usePremiumModal' -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import { FeaturesController } from '@/Controllers/FeaturesController' import { NavigationController } from '@/Controllers/Navigation/NavigationController' import '@reach/tooltip/styles.css' diff --git a/packages/web/src/javascripts/Components/Tags/TagsSection.tsx b/packages/web/src/javascripts/Components/Tags/TagsSection.tsx index 916daade1..f804afd00 100644 --- a/packages/web/src/javascripts/Components/Tags/TagsSection.tsx +++ b/packages/web/src/javascripts/Components/Tags/TagsSection.tsx @@ -1,5 +1,5 @@ import TagsList from '@/Components/Tags/TagsList' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { ApplicationEvent } from '@/__mocks__/@standardnotes/snjs' import { observer } from 'mobx-react-lite' import { FunctionComponent, useCallback, useEffect, useState } from 'react' diff --git a/packages/web/src/javascripts/Controllers/FilesController.ts b/packages/web/src/javascripts/Controllers/FilesController.ts index 4c3a3636b..cf989e1ff 100644 --- a/packages/web/src/javascripts/Controllers/FilesController.ts +++ b/packages/web/src/javascripts/Controllers/FilesController.ts @@ -4,7 +4,7 @@ import { PopoverFileItemActionType, } from '@/Components/AttachedFilesPopover/PopoverFileItemAction' import { BYTES_IN_ONE_MEGABYTE } from '@/Constants/Constants' -import { confirmDialog } from '@/Services/AlertService' +import { confirmDialog } from '@standardnotes/ui-services' import { Strings, StringUtils } from '@/Constants/Strings' import { concatenateUint8Arrays } from '@/Utils/ConcatenateUint8Arrays' import { diff --git a/packages/web/src/javascripts/Controllers/ItemList/ItemListController.ts b/packages/web/src/javascripts/Controllers/ItemList/ItemListController.ts index 10128b4a1..f24cf88e5 100644 --- a/packages/web/src/javascripts/Controllers/ItemList/ItemListController.ts +++ b/packages/web/src/javascripts/Controllers/ItemList/ItemListController.ts @@ -17,6 +17,7 @@ import { InternalEventInterface, FileViewController, FileItem, + WebAppEvent, } from '@standardnotes/snjs' import { action, computed, makeObservable, observable, reaction, runInAction } from 'mobx' import { WebApplication } from '../../Application/Application' @@ -28,7 +29,6 @@ import { SearchOptionsController } from '../SearchOptionsController' import { SelectedItemsController } from '../SelectedItemsController' import { NotesController } from '../NotesController' import { NoteTagsController } from '../NoteTagsController' -import { WebAppEvent } from '@/Application/WebAppEvent' const MinNoteCellHeight = 51.0 const DefaultListNumNotes = 20 diff --git a/packages/web/src/javascripts/Controllers/Navigation/NavigationController.ts b/packages/web/src/javascripts/Controllers/Navigation/NavigationController.ts index da46bd307..793f5266e 100644 --- a/packages/web/src/javascripts/Controllers/Navigation/NavigationController.ts +++ b/packages/web/src/javascripts/Controllers/Navigation/NavigationController.ts @@ -1,4 +1,4 @@ -import { confirmDialog } from '@/Services/AlertService' +import { confirmDialog } from '@standardnotes/ui-services' import { STRING_DELETE_TAG } from '@/Constants/Strings' import { MAX_MENU_SIZE_MULTIPLIER, MENU_MARGIN_FROM_APP_BORDER, SMART_TAGS_FEATURE_NAME } from '@/Constants/Constants' import { diff --git a/packages/web/src/javascripts/Controllers/NoAccountWarningController.ts b/packages/web/src/javascripts/Controllers/NoAccountWarningController.ts index 03559f580..f3a5a9ce0 100644 --- a/packages/web/src/javascripts/Controllers/NoAccountWarningController.ts +++ b/packages/web/src/javascripts/Controllers/NoAccountWarningController.ts @@ -1,4 +1,4 @@ -import { storage, StorageKey } from '@/Services/LocalStorage' +import { storage, StorageKey } from '@standardnotes/ui-services' import { ApplicationEvent, InternalEventBus } from '@standardnotes/snjs' import { runInAction, makeObservable, observable, action } from 'mobx' import { WebApplication } from '../Application/Application' diff --git a/packages/web/src/javascripts/Controllers/NoteHistory/NoteHistoryController.ts b/packages/web/src/javascripts/Controllers/NoteHistory/NoteHistoryController.ts index 227fd0298..b4dbf1214 100644 --- a/packages/web/src/javascripts/Controllers/NoteHistory/NoteHistoryController.ts +++ b/packages/web/src/javascripts/Controllers/NoteHistory/NoteHistoryController.ts @@ -7,7 +7,7 @@ import { sortRevisionListIntoGroups, } from '@/Components/RevisionHistoryModal/utils' import { STRING_RESTORE_LOCKED_ATTEMPT } from '@/Constants/Strings' -import { confirmDialog } from '@/Services/AlertService' +import { confirmDialog } from '@standardnotes/ui-services' import { Action, ActionVerb, diff --git a/packages/web/src/javascripts/Controllers/NotesController.ts b/packages/web/src/javascripts/Controllers/NotesController.ts index c62e92d62..cff4109f5 100644 --- a/packages/web/src/javascripts/Controllers/NotesController.ts +++ b/packages/web/src/javascripts/Controllers/NotesController.ts @@ -1,5 +1,5 @@ import { destroyAllObjectProperties } from '@/Utils' -import { confirmDialog } from '@/Services/AlertService' +import { confirmDialog } from '@standardnotes/ui-services' import { StringEmptyTrash, Strings, StringUtils } from '@/Constants/Strings' import { MENU_MARGIN_FROM_APP_BORDER } from '@/Constants/Constants' import { SNNote, NoteMutator, ContentType, SNTag, TagMutator, InternalEventBus } from '@standardnotes/snjs' diff --git a/packages/web/src/javascripts/Services/ViewControllerManager.ts b/packages/web/src/javascripts/Controllers/ViewControllerManager.ts similarity index 82% rename from packages/web/src/javascripts/Services/ViewControllerManager.ts rename to packages/web/src/javascripts/Controllers/ViewControllerManager.ts index 02788692d..cfda20dac 100644 --- a/packages/web/src/javascripts/Services/ViewControllerManager.ts +++ b/packages/web/src/javascripts/Controllers/ViewControllerManager.ts @@ -1,26 +1,26 @@ -import { storage, StorageKey } from '@/Services/LocalStorage' +import { storage, StorageKey } from '@standardnotes/ui-services' import { WebApplication } from '@/Application/Application' import { AccountMenuController } from '@/Controllers/AccountMenu/AccountMenuController' import { destroyAllObjectProperties } from '@/Utils' import { ApplicationEvent, DeinitSource, WebOrDesktopDeviceInterface, InternalEventBus } from '@standardnotes/snjs' import { action, makeObservable, observable } from 'mobx' -import { ActionsMenuController } from '../Controllers/ActionsMenuController' -import { FeaturesController } from '../Controllers/FeaturesController' -import { FilesController } from '../Controllers/FilesController' -import { NotesController } from '../Controllers/NotesController' -import { ItemListController } from '../Controllers/ItemList/ItemListController' -import { NoteTagsController } from '../Controllers/NoteTagsController' -import { NoAccountWarningController } from '../Controllers/NoAccountWarningController' -import { PreferencesController } from '../Controllers/PreferencesController' -import { PurchaseFlowController } from '../Controllers/PurchaseFlow/PurchaseFlowController' -import { QuickSettingsController } from '../Controllers/QuickSettingsController' -import { SearchOptionsController } from '../Controllers/SearchOptionsController' -import { SubscriptionController } from '../Controllers/Subscription/SubscriptionController' -import { SyncStatusController } from '../Controllers/SyncStatusController' -import { NavigationController } from '../Controllers/Navigation/NavigationController' -import { FilePreviewModalController } from '../Controllers/FilePreviewModalController' -import { SelectedItemsController } from '../Controllers/SelectedItemsController' -import { HistoryModalController } from '../Controllers/NoteHistory/HistoryModalController' +import { ActionsMenuController } from './ActionsMenuController' +import { FeaturesController } from './FeaturesController' +import { FilesController } from './FilesController' +import { NotesController } from './NotesController' +import { ItemListController } from './ItemList/ItemListController' +import { NoteTagsController } from './NoteTagsController' +import { NoAccountWarningController } from './NoAccountWarningController' +import { PreferencesController } from './PreferencesController' +import { PurchaseFlowController } from './PurchaseFlow/PurchaseFlowController' +import { QuickSettingsController } from './QuickSettingsController' +import { SearchOptionsController } from './SearchOptionsController' +import { SubscriptionController } from './Subscription/SubscriptionController' +import { SyncStatusController } from './SyncStatusController' +import { NavigationController } from './Navigation/NavigationController' +import { FilePreviewModalController } from './FilePreviewModalController' +import { SelectedItemsController } from './SelectedItemsController' +import { HistoryModalController } from './NoteHistory/HistoryModalController' export class ViewControllerManager { readonly enableUnfinishedFeatures: boolean = window?.enabledUnfinishedFeatures diff --git a/packages/web/src/javascripts/Hooks/useListKeyboardNavigation.ts b/packages/web/src/javascripts/Hooks/useListKeyboardNavigation.ts index 8ad795cb3..ccf40f5f8 100644 --- a/packages/web/src/javascripts/Hooks/useListKeyboardNavigation.ts +++ b/packages/web/src/javascripts/Hooks/useListKeyboardNavigation.ts @@ -1,4 +1,4 @@ -import { KeyboardKey } from '@/Services/IOService' +import { KeyboardKey } from '@standardnotes/ui-services' import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants/Constants' import { useCallback, useState, useEffect, RefObject } from 'react' diff --git a/packages/web/src/javascripts/Hooks/usePremiumModal.tsx b/packages/web/src/javascripts/Hooks/usePremiumModal.tsx index c304a9254..2ba419d80 100644 --- a/packages/web/src/javascripts/Hooks/usePremiumModal.tsx +++ b/packages/web/src/javascripts/Hooks/usePremiumModal.tsx @@ -1,5 +1,5 @@ import { WebApplication } from '@/Application/Application' -import { ViewControllerManager } from '@/Services/ViewControllerManager' +import { ViewControllerManager } from '@/Controllers/ViewControllerManager' import { observer } from 'mobx-react-lite' import { FunctionComponent, createContext, useCallback, useContext, ReactNode } from 'react' import PremiumFeaturesModal from '@/Components/PremiumFeaturesModal/PremiumFeaturesModal' diff --git a/packages/web/tsconfig.json b/packages/web/tsconfig.json index f61c886c0..acde4c547 100644 --- a/packages/web/tsconfig.json +++ b/packages/web/tsconfig.json @@ -19,8 +19,7 @@ "typeRoots": ["./src/javascripts/Types/External", "../../node_modules/@types", "node_modules/@types"], "paths": { "@/*": ["./src/javascripts/*"], - "@Controllers/*": ["src/javascripts/Controllers/*"], - "@Services/*": ["src/javascripts/Services/*"] + "@Controllers/*": ["src/javascripts/Controllers/*"] } }, "exclude": ["node_modules", "dist", "coverage"] diff --git a/yarn.lock b/yarn.lock index 05accc694..41337a1a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6388,6 +6388,15 @@ __metadata: languageName: node linkType: hard +"@standardnotes/common@npm:^1.30.0": + version: 1.30.0 + resolution: "@standardnotes/common@npm:1.30.0" + dependencies: + reflect-metadata: ^0.1.13 + checksum: 833b6e7f3ee4cfbf306769d7387073073204a3dd5cd9adaf11bb10914338a4b16420e5ef196d28974427b491d7630d887a7a9e3dcbfb070f30c491437213b329 + languageName: node + linkType: hard + "@standardnotes/component-relay@npm:2.2.0": version: 2.2.0 resolution: "@standardnotes/component-relay@npm:2.2.0" @@ -6626,7 +6635,7 @@ __metadata: languageName: unknown linkType: soft -"@standardnotes/filepicker@workspace:*, @standardnotes/filepicker@workspace:packages/filepicker": +"@standardnotes/filepicker@workspace:*, @standardnotes/filepicker@workspace:^, @standardnotes/filepicker@workspace:packages/filepicker": version: 0.0.0-use.local resolution: "@standardnotes/filepicker@workspace:packages/filepicker" dependencies: @@ -7033,7 +7042,7 @@ __metadata: languageName: unknown linkType: soft -"@standardnotes/models@workspace:*, @standardnotes/models@workspace:packages/models": +"@standardnotes/models@workspace:*, @standardnotes/models@workspace:^, @standardnotes/models@workspace:packages/models": version: 0.0.0-use.local resolution: "@standardnotes/models@workspace:packages/models" dependencies: @@ -7167,13 +7176,13 @@ __metadata: languageName: node linkType: hard -"@standardnotes/services@workspace:*, @standardnotes/services@workspace:packages/services": +"@standardnotes/services@workspace:*, @standardnotes/services@workspace:^, @standardnotes/services@workspace:packages/services": version: 0.0.0-use.local resolution: "@standardnotes/services@workspace:packages/services" dependencies: "@standardnotes/auth": ^3.19.4 - "@standardnotes/common": ^1.23.1 - "@standardnotes/models": "workspace:*" + "@standardnotes/common": ^1.30.0 + "@standardnotes/models": "workspace:^" "@standardnotes/responses": "workspace:*" "@standardnotes/security": ^1.2.0 "@standardnotes/utils": "workspace:*" @@ -7273,7 +7282,7 @@ __metadata: languageName: unknown linkType: soft -"@standardnotes/snjs@^2.41.1, @standardnotes/snjs@workspace:*, @standardnotes/snjs@workspace:packages/snjs": +"@standardnotes/snjs@^2.41.1, @standardnotes/snjs@workspace:*, @standardnotes/snjs@workspace:^, @standardnotes/snjs@workspace:packages/snjs": version: 0.0.0-use.local resolution: "@standardnotes/snjs@workspace:packages/snjs" dependencies: @@ -7406,7 +7415,7 @@ __metadata: languageName: node linkType: hard -"@standardnotes/styles@workspace:*, @standardnotes/styles@workspace:packages/styles": +"@standardnotes/styles@workspace:*, @standardnotes/styles@workspace:^, @standardnotes/styles@workspace:packages/styles": version: 0.0.0-use.local resolution: "@standardnotes/styles@workspace:packages/styles" dependencies: @@ -7428,7 +7437,7 @@ __metadata: languageName: unknown linkType: soft -"@standardnotes/toast@workspace:*, @standardnotes/toast@workspace:packages/toast": +"@standardnotes/toast@workspace:*, @standardnotes/toast@workspace:^, @standardnotes/toast@workspace:packages/toast": version: 0.0.0-use.local resolution: "@standardnotes/toast@workspace:packages/toast" dependencies: @@ -7446,7 +7455,26 @@ __metadata: languageName: unknown linkType: soft -"@standardnotes/utils@workspace:*, @standardnotes/utils@workspace:packages/utils": +"@standardnotes/ui-services@workspace:^, @standardnotes/ui-services@workspace:packages/ui-services": + version: 0.0.0-use.local + resolution: "@standardnotes/ui-services@workspace:packages/ui-services" + dependencies: + "@standardnotes/filepicker": "workspace:^" + "@standardnotes/services": "workspace:^" + "@standardnotes/snjs": "workspace:^" + "@standardnotes/styles": "workspace:^" + "@standardnotes/toast": "workspace:^" + "@standardnotes/utils": "workspace:^" + "@types/jest": ^28.1.5 + "@typescript-eslint/eslint-plugin": ^5.30.0 + "@typescript-eslint/parser": ^5.12.1 + eslint-plugin-prettier: "*" + jest: ^28.1.2 + ts-jest: ^28.0.5 + languageName: unknown + linkType: soft + +"@standardnotes/utils@workspace:*, @standardnotes/utils@workspace:^, @standardnotes/utils@workspace:packages/utils": version: 0.0.0-use.local resolution: "@standardnotes/utils@workspace:packages/utils" dependencies: @@ -7492,6 +7520,7 @@ __metadata: "@standardnotes/snjs": "workspace:*" "@standardnotes/styles": "workspace:*" "@standardnotes/toast": "workspace:*" + "@standardnotes/ui-services": "workspace:^" "@types/jest": ^28.1.5 "@types/react": ^17.0.42 "@types/react-dom": ^18.0.5