diff --git a/docs/long-term-plans/e2e-encryption-device-keys-DRAFT.md b/docs/long-term-plans/e2e-encryption-device-keys-DRAFT.md index 78594f61bd..33f99d8b24 100644 --- a/docs/long-term-plans/e2e-encryption-device-keys-DRAFT.md +++ b/docs/long-term-plans/e2e-encryption-device-keys-DRAFT.md @@ -534,7 +534,7 @@ export class DialogRecoveryPasswordComponent { type: 'tpl', className: 'tpl info-text', hideExpression: (m, v, field) => - field?.parent?.parent?.parent?.model.syncProvider !== LegacySyncProvider.SuperSync, + field?.parent?.parent?.parent?.model.syncProvider !== SyncProviderId.SuperSync, templateOptions: { tag: 'div', text: '🔒 End-to-end encryption enabled automatically' @@ -543,7 +543,7 @@ export class DialogRecoveryPasswordComponent { { type: 'btn', hideExpression: (m, v, field) => - field?.parent?.parent?.parent?.model.syncProvider !== LegacySyncProvider.SuperSync, + field?.parent?.parent?.parent?.model.syncProvider !== SyncProviderId.SuperSync, templateOptions: { text: 'Manage Recovery Password', onClick: async () => { @@ -570,7 +570,7 @@ export class DialogRecoveryPasswordComponent { ```typescript async updateSettingsFromForm(cfg: SyncConfig, isInitialSetup: boolean) { - if (cfg.syncProvider === LegacySyncProvider.SuperSync) { + if (cfg.syncProvider === SyncProviderId.SuperSync) { // Check if user has existing key const hasKey = await this._deviceKey.getMasterKey(); diff --git a/e2e/tests/sync/ENCRYPTION-E2E-STATUS.md b/e2e/tests/sync/ENCRYPTION-E2E-STATUS.md index c2f95236ff..2b00a6fce4 100644 --- a/e2e/tests/sync/ENCRYPTION-E2E-STATUS.md +++ b/e2e/tests/sync/ENCRYPTION-E2E-STATUS.md @@ -154,7 +154,7 @@ ngAfterViewInit(): void { this._subs.add( syncProviderControl.valueChanges .pipe(skip(1)) - .subscribe(async (newProvider: LegacySyncProvider | null) => { + .subscribe(async (newProvider: SyncProviderId | null) => { if (!newProvider) { return; } @@ -178,22 +178,22 @@ ngAfterViewInit(): void { // Create provider-specific config based on provider type let providerSpecificUpdate: Partial = {}; - if (newProvider === LegacySyncProvider.SuperSync && privateCfg) { + if (newProvider === SyncProviderId.SuperSync && privateCfg) { providerSpecificUpdate = { superSync: privateCfg as any, encryptKey: privateCfg.encryptKey || '', }; - } else if (newProvider === LegacySyncProvider.WebDAV && privateCfg) { + } else if (newProvider === SyncProviderId.WebDAV && privateCfg) { providerSpecificUpdate = { webDav: privateCfg as any, encryptKey: privateCfg.encryptKey || '', }; - } else if (newProvider === LegacySyncProvider.LocalFile && privateCfg) { + } else if (newProvider === SyncProviderId.LocalFile && privateCfg) { providerSpecificUpdate = { localFileSync: privateCfg as any, encryptKey: privateCfg.encryptKey || '', }; - } else if (newProvider === LegacySyncProvider.Dropbox && privateCfg) { + } else if (newProvider === SyncProviderId.Dropbox && privateCfg) { providerSpecificUpdate = { encryptKey: privateCfg.encryptKey || '', }; @@ -214,7 +214,7 @@ ngAfterViewInit(): void { }; // For non-SuperSync providers, update encryption from global config - if (newProvider !== LegacySyncProvider.SuperSync) { + if (newProvider !== SyncProviderId.SuperSync) { this._tmpUpdatedCfg = { ...this._tmpUpdatedCfg, isEncryptionEnabled: globalCfg?.isEncryptionEnabled || false, diff --git a/src/app/core/startup/startup.service.ts b/src/app/core/startup/startup.service.ts index 681d8d2dab..194283aede 100644 --- a/src/app/core/startup/startup.service.ts +++ b/src/app/core/startup/startup.service.ts @@ -26,7 +26,7 @@ import { combineLatest } from 'rxjs'; import { Store } from '@ngrx/store'; import { selectSyncConfig } from '../../features/config/store/global-config.reducer'; import { selectEnabledIssueProviders } from '../../features/issue/store/issue-provider.selectors'; -import { LegacySyncProvider } from '../../imex/sync/legacy-sync-provider.model'; +import { SyncProviderId } from '../../op-log/sync-providers/provider.const'; import { GlobalConfigState } from '../../features/config/global-config.model'; import { IPC } from '../../../../electron/shared-with-frontend/ipc-events.const'; import { IpcRendererEvent } from 'electron'; @@ -272,7 +272,7 @@ export class StartupService { map(([syncConfig, enabledIssueProviders]) => { const hasCloudSync = syncConfig.syncProvider !== null && - syncConfig.syncProvider !== LegacySyncProvider.LocalFile; + syncConfig.syncProvider !== SyncProviderId.LocalFile; const hasIssueProviders = enabledIssueProviders.length > 0; return hasCloudSync || hasIssueProviders; }), diff --git a/src/app/features/config/form-cfgs/sync-form.const.ts b/src/app/features/config/form-cfgs/sync-form.const.ts index 332f49226d..01177ef9b2 100644 --- a/src/app/features/config/form-cfgs/sync-form.const.ts +++ b/src/app/features/config/form-cfgs/sync-form.const.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { T } from '../../../t.const'; import { ConfigFormSection, SyncConfig } from '../global-config.model'; -import { LegacySyncProvider } from '../../../imex/sync/legacy-sync-provider.model'; +import { SyncProviderId } from '../../../op-log/sync-providers/provider.const'; import { IS_ANDROID_WEB_VIEW } from '../../../util/is-android-web-view'; import { IS_ELECTRON } from '../../../app.constants'; import { fileSyncDroid, fileSyncElectron } from '../../../op-log/model/model-config'; @@ -64,7 +64,7 @@ const createWebdavFormFields = (options: { }, expressions: { 'props.required': (field: FormlyFieldConfig) => - field?.parent?.parent?.model?.syncProvider === LegacySyncProvider.WebDAV, + field?.parent?.parent?.model?.syncProvider === SyncProviderId.WebDAV, }, }, { @@ -76,7 +76,7 @@ const createWebdavFormFields = (options: { }, expressions: { 'props.required': (field: FormlyFieldConfig) => - field?.parent?.parent?.model?.syncProvider === LegacySyncProvider.WebDAV, + field?.parent?.parent?.model?.syncProvider === SyncProviderId.WebDAV, }, }, { @@ -89,7 +89,7 @@ const createWebdavFormFields = (options: { }, expressions: { 'props.required': (field: FormlyFieldConfig) => - field?.parent?.parent?.model?.syncProvider === LegacySyncProvider.WebDAV, + field?.parent?.parent?.model?.syncProvider === SyncProviderId.WebDAV, }, }, { @@ -101,7 +101,7 @@ const createWebdavFormFields = (options: { }, expressions: { 'props.required': (field: FormlyFieldConfig) => - field?.parent?.parent?.model?.syncProvider === LegacySyncProvider.WebDAV, + field?.parent?.parent?.model?.syncProvider === SyncProviderId.WebDAV, }, }, ]; @@ -127,14 +127,14 @@ export const SYNC_FORM: ConfigFormSection = { label: T.F.SYNC.FORM.L_SYNC_PROVIDER, required: true, options: [ - { label: 'SuperSync (Beta)', value: LegacySyncProvider.SuperSync }, - { label: LegacySyncProvider.Dropbox, value: LegacySyncProvider.Dropbox }, - { label: 'WebDAV (experimental)', value: LegacySyncProvider.WebDAV }, + { label: 'SuperSync (Beta)', value: SyncProviderId.SuperSync }, + { label: SyncProviderId.Dropbox, value: SyncProviderId.Dropbox }, + { label: 'WebDAV (experimental)', value: SyncProviderId.WebDAV }, ...(IS_ELECTRON || IS_ANDROID_WEB_VIEW ? [ { label: 'LocalFile (experimental)', - value: LegacySyncProvider.LocalFile, + value: SyncProviderId.LocalFile, }, ] : []), @@ -143,7 +143,7 @@ export const SYNC_FORM: ConfigFormSection = { }, { hideExpression: (m, v, field) => - field?.parent?.model.syncProvider !== LegacySyncProvider.LocalFile || + field?.parent?.model.syncProvider !== SyncProviderId.LocalFile || IS_ANDROID_WEB_VIEW, resetOnHide: false, key: 'localFileSync', @@ -166,14 +166,14 @@ export const SYNC_FORM: ConfigFormSection = { }, expressions: { 'props.required': (field: FormlyFieldConfig) => - field?.parent?.parent?.model?.syncProvider === LegacySyncProvider.LocalFile, + field?.parent?.parent?.model?.syncProvider === SyncProviderId.LocalFile, }, }, ], }, { hideExpression: (m, v, field) => - field?.parent?.model.syncProvider !== LegacySyncProvider.LocalFile || + field?.parent?.model.syncProvider !== SyncProviderId.LocalFile || !IS_ANDROID_WEB_VIEW, resetOnHide: false, key: 'localFileSync', @@ -197,7 +197,7 @@ export const SYNC_FORM: ConfigFormSection = { }, expressions: { 'props.required': (field: FormlyFieldConfig) => - field?.parent?.parent?.model?.syncProvider === LegacySyncProvider.LocalFile, + field?.parent?.parent?.model?.syncProvider === SyncProviderId.LocalFile, }, }, ], @@ -206,7 +206,7 @@ export const SYNC_FORM: ConfigFormSection = { // WebDAV provider form fields { hideExpression: (m, v, field) => - field?.parent?.model.syncProvider !== LegacySyncProvider.WebDAV, + field?.parent?.model.syncProvider !== SyncProviderId.WebDAV, resetOnHide: false, key: 'webDav', fieldGroup: createWebdavFormFields({ @@ -221,7 +221,7 @@ export const SYNC_FORM: ConfigFormSection = { // Note: No key needed - Dropbox credentials stored privately via SyncCredentialStore { hideExpression: (m, v, field) => - field?.parent?.model.syncProvider !== LegacySyncProvider.Dropbox, + field?.parent?.model.syncProvider !== SyncProviderId.Dropbox, resetOnHide: false, // Custom marker for identifying this field group in config-page.component.ts props: { dropboxAuth: true } as any, @@ -254,7 +254,7 @@ export const SYNC_FORM: ConfigFormSection = { // hideExpression: ((model: DropboxSyncConfig) => !model.accessToken), // Hide for SuperSync (uses fixed interval) and when manual sync only is enabled hideExpression: (m, v, field) => - field?.parent?.model.syncProvider === LegacySyncProvider.SuperSync || + field?.parent?.model.syncProvider === SyncProviderId.SuperSync || field?.parent?.model.isManualSyncOnly === true, resetOnHide: true, templateOptions: { @@ -269,7 +269,7 @@ export const SYNC_FORM: ConfigFormSection = { type: 'checkbox', // Only show for file-based providers (Dropbox, WebDAV, LocalFile) hideExpression: (m, v, field) => - field?.parent?.model.syncProvider === LegacySyncProvider.SuperSync || + field?.parent?.model.syncProvider === SyncProviderId.SuperSync || field?.parent?.model.syncProvider === null, templateOptions: { label: T.F.SYNC.FORM.L_MANUAL_SYNC_ONLY, @@ -300,8 +300,7 @@ export const SYNC_FORM: ConfigFormSection = { btnStyle: 'stroked', onClick: async (field: FormlyFieldConfig) => { const isSuperSync = - field?.parent?.parent?.model?.syncProvider === - LegacySyncProvider.SuperSync; + field?.parent?.parent?.model?.syncProvider === SyncProviderId.SuperSync; const result = isSuperSync ? await openEncryptionPasswordChangeDialog() : await openEncryptionPasswordChangeDialogForFileBased(); @@ -318,8 +317,7 @@ export const SYNC_FORM: ConfigFormSection = { btnStyle: 'stroked', onClick: async (field: FormlyFieldConfig) => { const isSuperSync = - field?.parent?.parent?.model?.syncProvider === - LegacySyncProvider.SuperSync; + field?.parent?.parent?.model?.syncProvider === SyncProviderId.SuperSync; const result = isSuperSync ? await openDisableEncryptionDialog() : await openDisableEncryptionDialogForFileBased(); @@ -348,7 +346,7 @@ export const SYNC_FORM: ConfigFormSection = { { type: 'collapsible', hideExpression: (m, v, field) => - field?.parent?.model.syncProvider === LegacySyncProvider.SuperSync, + field?.parent?.model.syncProvider === SyncProviderId.SuperSync, props: { label: T.G.ADVANCED_CFG }, fieldGroup: [ { @@ -361,7 +359,7 @@ export const SYNC_FORM: ConfigFormSection = { // Enable encryption button for file-based providers (shown when encryption is disabled) { hideExpression: (m: any, v: any, field?: FormlyFieldConfig) => - field?.parent?.parent?.model.syncProvider === LegacySyncProvider.SuperSync || + field?.parent?.parent?.model.syncProvider === SyncProviderId.SuperSync || m.isEncryptionEnabled, type: 'btn', className: 'e2e-file-based-enable-encryption-btn', @@ -388,7 +386,7 @@ export const SYNC_FORM: ConfigFormSection = { fieldGroup: [ { hideExpression: (m, v, field) => - field?.parent?.parent?.model.syncProvider !== LegacySyncProvider.SuperSync, + field?.parent?.parent?.model.syncProvider !== SyncProviderId.SuperSync, type: 'btn', templateOptions: { text: T.F.SYNC.FORM.SUPER_SYNC.BTN_GET_TOKEN, @@ -403,7 +401,7 @@ export const SYNC_FORM: ConfigFormSection = { }, { hideExpression: (m, v, field) => - field?.parent?.parent?.model.syncProvider !== LegacySyncProvider.SuperSync, + field?.parent?.parent?.model.syncProvider !== SyncProviderId.SuperSync, key: 'accessToken', type: 'textarea', className: 'e2e-accessToken', @@ -414,14 +412,14 @@ export const SYNC_FORM: ConfigFormSection = { }, expressions: { 'props.required': (field: FormlyFieldConfig) => - field?.parent?.parent?.model?.syncProvider === LegacySyncProvider.SuperSync, + field?.parent?.parent?.model?.syncProvider === SyncProviderId.SuperSync, }, }, // Advanced settings for SuperSync { type: 'collapsible', hideExpression: (m, v, field) => - field?.parent?.parent?.model.syncProvider !== LegacySyncProvider.SuperSync, + field?.parent?.parent?.model.syncProvider !== SyncProviderId.SuperSync, props: { label: T.G.ADVANCED_CFG }, fieldGroup: [ // Enable encryption button for SuperSync (shown when encryption is disabled) diff --git a/src/app/features/config/global-config.model.ts b/src/app/features/config/global-config.model.ts index 6659733b75..50cbf6b44b 100644 --- a/src/app/features/config/global-config.model.ts +++ b/src/app/features/config/global-config.model.ts @@ -1,7 +1,7 @@ import { FormlyFieldConfig } from '@ngx-formly/core'; import { LanguageCode, DateTimeLocale } from '../../core/locale.constants'; -import { LegacySyncProvider } from '../../imex/sync/legacy-sync-provider.model'; +import { SyncProviderId } from '../../op-log/sync-providers/provider.const'; import { ProjectCfgFormKey } from '../project/project.model'; import { KeyboardConfig } from './keyboard-config.model'; import { TaskReminderOptionId } from '../tasks/task.model'; @@ -162,8 +162,7 @@ export type SyncConfig = Readonly<{ isEnabled: boolean; isEncryptionEnabled?: boolean; isCompressionEnabled?: boolean; - // TODO migrate to SyncProviderId - syncProvider: LegacySyncProvider | null; + syncProvider: SyncProviderId | null; syncInterval: number; isManualSyncOnly?: boolean; diff --git a/src/app/features/config/store/global-config.reducer.spec.ts b/src/app/features/config/store/global-config.reducer.spec.ts index 950f1928f5..a8723d93c8 100644 --- a/src/app/features/config/store/global-config.reducer.spec.ts +++ b/src/app/features/config/store/global-config.reducer.spec.ts @@ -19,7 +19,7 @@ import { } from './global-config.reducer'; import { loadAllData } from '../../../root-store/meta/load-all-data.action'; import { GlobalConfigState } from '../global-config.model'; -import { LegacySyncProvider } from '../../../imex/sync/legacy-sync-provider.model'; +import { SyncProviderId } from '../../../op-log/sync-providers/provider.const'; import { AppDataComplete } from '../../../op-log/model/model-config'; import { DEFAULT_GLOBAL_CONFIG } from '../default-global-config.const'; @@ -98,7 +98,7 @@ describe('GlobalConfigReducer', () => { ...initialGlobalConfigState, sync: { ...initialGlobalConfigState.sync, - syncProvider: LegacySyncProvider.SuperSync, // Snapshot has user's provider + syncProvider: SyncProviderId.SuperSync, // Snapshot has user's provider }, }; @@ -110,7 +110,7 @@ describe('GlobalConfigReducer', () => { ); // Should use snapshot's syncProvider since oldState has null - expect(result.sync.syncProvider).toBe(LegacySyncProvider.SuperSync); + expect(result.sync.syncProvider).toBe(SyncProviderId.SuperSync); }); it('should preserve syncProvider from oldState when loading synced data', () => { @@ -118,7 +118,7 @@ describe('GlobalConfigReducer', () => { ...initialGlobalConfigState, sync: { ...initialGlobalConfigState.sync, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, }, }; @@ -142,7 +142,7 @@ describe('GlobalConfigReducer', () => { ); // syncProvider should be preserved from oldState - expect(result.sync.syncProvider).toBe(LegacySyncProvider.SuperSync); + expect(result.sync.syncProvider).toBe(SyncProviderId.SuperSync); // Other config should be updated from synced data expect(result.misc.isDisableAnimations).toBe(true); }); @@ -152,7 +152,7 @@ describe('GlobalConfigReducer', () => { ...initialGlobalConfigState, sync: { ...initialGlobalConfigState.sync, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, }, }; @@ -160,7 +160,7 @@ describe('GlobalConfigReducer', () => { ...initialGlobalConfigState, sync: { ...initialGlobalConfigState.sync, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, }, }; @@ -172,7 +172,7 @@ describe('GlobalConfigReducer', () => { ); // syncProvider should be preserved from oldState, not overwritten - expect(result.sync.syncProvider).toBe(LegacySyncProvider.WebDAV); + expect(result.sync.syncProvider).toBe(SyncProviderId.WebDAV); }); it('should update other sync config properties while preserving syncProvider', () => { @@ -180,7 +180,7 @@ describe('GlobalConfigReducer', () => { ...initialGlobalConfigState, sync: { ...initialGlobalConfigState.sync, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, syncInterval: 300000, }, }; @@ -203,7 +203,7 @@ describe('GlobalConfigReducer', () => { ); // syncProvider preserved - expect(result.sync.syncProvider).toBe(LegacySyncProvider.SuperSync); + expect(result.sync.syncProvider).toBe(SyncProviderId.SuperSync); // Other sync settings updated expect(result.sync.syncInterval).toBe(600000); expect(result.sync.isCompressionEnabled).toBe(true); @@ -218,7 +218,7 @@ describe('GlobalConfigReducer', () => { ...initialGlobalConfigState, sync: { ...initialGlobalConfigState.sync, - syncProvider: LegacySyncProvider.SuperSync, // Not null = not sync hydration + syncProvider: SyncProviderId.SuperSync, // Not null = not sync hydration isEnabled: true, // User had sync enabled }, }; @@ -240,7 +240,7 @@ describe('GlobalConfigReducer', () => { ...initialGlobalConfigState, sync: { ...initialGlobalConfigState.sync, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, isEnabled: true, // User has sync enabled }, }; @@ -264,7 +264,7 @@ describe('GlobalConfigReducer', () => { // isEnabled should be preserved from oldState, not overwritten by remote's false expect(result.sync.isEnabled).toBe(true); // syncProvider should also be preserved - expect(result.sync.syncProvider).toBe(LegacySyncProvider.SuperSync); + expect(result.sync.syncProvider).toBe(SyncProviderId.SuperSync); }); it('should preserve isEnabled=false from oldState during sync hydration', () => { @@ -273,7 +273,7 @@ describe('GlobalConfigReducer', () => { ...initialGlobalConfigState, sync: { ...initialGlobalConfigState.sync, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, isEnabled: false, // User has sync disabled locally }, }; diff --git a/src/app/imex/sync/dialog-sync-initial-cfg/dialog-sync-initial-cfg.component.ts b/src/app/imex/sync/dialog-sync-initial-cfg/dialog-sync-initial-cfg.component.ts index e3eddf5070..5d61d75fb5 100644 --- a/src/app/imex/sync/dialog-sync-initial-cfg/dialog-sync-initial-cfg.component.ts +++ b/src/app/imex/sync/dialog-sync-initial-cfg/dialog-sync-initial-cfg.component.ts @@ -21,7 +21,7 @@ import { FormlyConfigModule } from '../../../ui/formly-config.module'; import { FormlyModule } from '@ngx-formly/core'; import { FormlyFieldConfig } from '@ngx-formly/core'; import { SyncConfig } from '../../../features/config/global-config.model'; -import { LegacySyncProvider } from '../legacy-sync-provider.model'; +import { SyncProviderId } from '../../../op-log/sync-providers/provider.const'; import { SyncConfigService } from '../sync-config.service'; import { SyncWrapperService } from '../sync-wrapper.service'; import { Subscription } from 'rxjs'; @@ -107,7 +107,7 @@ export class DialogSyncInitialCfgComponent implements AfterViewInit { this._subs.add( syncProviderControl.valueChanges .pipe(skip(1)) - .subscribe(async (newProvider: LegacySyncProvider | null) => { + .subscribe(async (newProvider: SyncProviderId | null) => { if (!newProvider) { return; } @@ -133,24 +133,24 @@ export class DialogSyncInitialCfgComponent implements AfterViewInit { // Create provider-specific config based on provider type let providerSpecificUpdate: Partial = {}; - if (newProvider === LegacySyncProvider.SuperSync && privateCfg) { + if (newProvider === SyncProviderId.SuperSync && privateCfg) { providerSpecificUpdate = { superSync: privateCfg as any, encryptKey: privateCfg.encryptKey || '', // SuperSync stores isEncryptionEnabled in privateCfg, not globalCfg isEncryptionEnabled: (privateCfg as any).isEncryptionEnabled || false, }; - } else if (newProvider === LegacySyncProvider.WebDAV && privateCfg) { + } else if (newProvider === SyncProviderId.WebDAV && privateCfg) { providerSpecificUpdate = { webDav: privateCfg as any, encryptKey: privateCfg.encryptKey || '', }; - } else if (newProvider === LegacySyncProvider.LocalFile && privateCfg) { + } else if (newProvider === SyncProviderId.LocalFile && privateCfg) { providerSpecificUpdate = { localFileSync: privateCfg as any, encryptKey: privateCfg.encryptKey || '', }; - } else if (newProvider === LegacySyncProvider.Dropbox && privateCfg) { + } else if (newProvider === SyncProviderId.Dropbox && privateCfg) { providerSpecificUpdate = { encryptKey: privateCfg.encryptKey || '', }; @@ -172,7 +172,7 @@ export class DialogSyncInitialCfgComponent implements AfterViewInit { }; // For non-SuperSync providers, update encryption from global config - if (newProvider !== LegacySyncProvider.SuperSync) { + if (newProvider !== SyncProviderId.SuperSync) { this._tmpUpdatedCfg = { ...this._tmpUpdatedCfg, isEncryptionEnabled: globalCfg?.isEncryptionEnabled || false, diff --git a/src/app/imex/sync/dropbox/store/dropbox.effects.ts b/src/app/imex/sync/dropbox/store/dropbox.effects.ts index 57f58bb886..5bb1c2c769 100644 --- a/src/app/imex/sync/dropbox/store/dropbox.effects.ts +++ b/src/app/imex/sync/dropbox/store/dropbox.effects.ts @@ -8,7 +8,6 @@ import { updateGlobalConfigSection } from '../../../../features/config/store/glo import { environment } from '../../../../../environments/environment'; import { SyncProviderManager } from '../../../../op-log/sync-providers/provider-manager.service'; import { DropboxPrivateCfg, SyncProviderId } from '../../../../op-log/sync-exports'; -import { LegacySyncProvider } from '../../legacy-sync-provider.model'; import { confirmDialog } from '../../../../util/native-dialogs'; @Injectable() @@ -26,7 +25,7 @@ export class DropboxEffects { ), tap(async ({ sectionCfg }) => { const syncCfg = sectionCfg as SyncConfig; - if (syncCfg.syncProvider !== LegacySyncProvider.Dropbox) { + if (syncCfg.syncProvider !== SyncProviderId.Dropbox) { return; } const provider = this._providerManager.getProviderById(SyncProviderId.Dropbox); diff --git a/src/app/imex/sync/legacy-sync-provider.model.ts b/src/app/imex/sync/legacy-sync-provider.model.ts deleted file mode 100644 index 07f0ed3a02..0000000000 --- a/src/app/imex/sync/legacy-sync-provider.model.ts +++ /dev/null @@ -1,7 +0,0 @@ -// NOTE: do not change!! -export enum LegacySyncProvider { - 'Dropbox' = 'Dropbox', - 'WebDAV' = 'WebDAV', - 'LocalFile' = 'LocalFile', - 'SuperSync' = 'SuperSync', -} diff --git a/src/app/imex/sync/legacy-sync.model.ts b/src/app/imex/sync/legacy-sync.model.ts index 713e571291..485b99c365 100644 --- a/src/app/imex/sync/legacy-sync.model.ts +++ b/src/app/imex/sync/legacy-sync.model.ts @@ -6,7 +6,7 @@ import { TaskRepeatCfgState } from '../../features/task-repeat-cfg/task-repeat-c import { TagState } from '../../features/tag/tag.model'; import { SimpleCounterState } from '../../features/simple-counter/simple-counter.model'; import { ProjectArchive } from '../../features/project/project-archive.model'; -import { LegacySyncProvider } from './legacy-sync-provider.model'; +import { SyncProviderId } from '../../op-log/sync-providers/provider.const'; import { ProjectState } from '../../features/project/project.model'; import { NoteState } from '../../features/note/note.model'; import { LocalSyncMetaForProvider } from './sync.model'; @@ -30,9 +30,9 @@ export interface LegacyAppBaseData { } export interface LocalSyncMetaModel { - [LegacySyncProvider.WebDAV]: LocalSyncMetaForProvider; - [LegacySyncProvider.Dropbox]: LocalSyncMetaForProvider; - [LegacySyncProvider.LocalFile]: LocalSyncMetaForProvider; + [SyncProviderId.WebDAV]: LocalSyncMetaForProvider; + [SyncProviderId.Dropbox]: LocalSyncMetaForProvider; + [SyncProviderId.LocalFile]: LocalSyncMetaForProvider; } // NOTE: [key:string] always refers to projectId diff --git a/src/app/imex/sync/sync-config.service.spec.ts b/src/app/imex/sync/sync-config.service.spec.ts index b0f2c29873..1e1d6a910b 100644 --- a/src/app/imex/sync/sync-config.service.spec.ts +++ b/src/app/imex/sync/sync-config.service.spec.ts @@ -4,8 +4,7 @@ import { SyncProviderManager } from '../../op-log/sync-providers/provider-manage import { GlobalConfigService } from '../../features/config/global-config.service'; import { BehaviorSubject } from 'rxjs'; import { SyncConfig } from '../../features/config/global-config.model'; -import { LegacySyncProvider } from './legacy-sync-provider.model'; -import { SyncProviderId } from '../../op-log/sync-exports'; +import { SyncProviderId } from '../../op-log/sync-providers/provider.const'; import { DEFAULT_GLOBAL_CONFIG } from '../../features/config/default-global-config.const'; import { first } from 'rxjs/operators'; import { WrappedProviderService } from '../../op-log/sync-providers/wrapped-provider.service'; @@ -29,7 +28,7 @@ describe('SyncConfigService', () => { mockSyncConfig$ = new BehaviorSubject({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, isEncryptionEnabled: true, }); @@ -78,7 +77,7 @@ describe('SyncConfigService', () => { const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'secret-key', @@ -95,7 +94,7 @@ describe('SyncConfigService', () => { // Should only pass non-private data to global config expect(globalConfigService.updateSection).toHaveBeenCalledWith('sync', { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, isEncryptionEnabled: true, }); @@ -122,7 +121,7 @@ describe('SyncConfigService', () => { const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'test-key', @@ -152,7 +151,7 @@ describe('SyncConfigService', () => { const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'test-key', @@ -191,7 +190,7 @@ describe('SyncConfigService', () => { const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.Dropbox, + syncProvider: SyncProviderId.Dropbox, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'dropbox-key', @@ -232,7 +231,7 @@ describe('SyncConfigService', () => { // Update settings without changing the provider const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.Dropbox, + syncProvider: SyncProviderId.Dropbox, syncInterval: 600000, // Changed interval isEncryptionEnabled: true, encryptKey: 'existing-key', // Same key @@ -277,7 +276,7 @@ describe('SyncConfigService', () => { // Form only provides baseUrl, accessToken is empty string (reset by Formly) const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, syncInterval: 600000, // Changed interval (unrelated setting) superSync: { baseUrl: existingBaseUrl, @@ -318,7 +317,7 @@ describe('SyncConfigService', () => { const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, syncInterval: 300000, superSync: { baseUrl: 'https://example.com', @@ -360,7 +359,7 @@ describe('SyncConfigService', () => { // Form provides empty password (e.g., from resetOnHide or form state issue) const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 600000, webDav: { baseUrl: 'https://webdav.example.com', @@ -400,7 +399,7 @@ describe('SyncConfigService', () => { // User explicitly disables encryption (false should be respected) const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, syncInterval: 300000, superSync: { baseUrl: 'https://example.com', @@ -440,7 +439,7 @@ describe('SyncConfigService', () => { // Form provides only baseUrl, all other fields empty const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, webDav: { baseUrl: 'https://webdav.example.com', @@ -484,7 +483,7 @@ describe('SyncConfigService', () => { const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, webDav: { baseUrl: 'https://new.example.com', // Updated @@ -527,7 +526,7 @@ describe('SyncConfigService', () => { // Form provides empty path const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, syncInterval: 600000, localFileSync: { syncFolderPath: '', // Empty - should not overwrite @@ -556,7 +555,7 @@ describe('SyncConfigService', () => { const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, isEncryptionEnabled: false, webDav: { @@ -599,7 +598,7 @@ describe('SyncConfigService', () => { const settings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'new-key', @@ -634,7 +633,7 @@ describe('SyncConfigService', () => { const initialSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'my-secret-password', @@ -665,7 +664,7 @@ describe('SyncConfigService', () => { mockSyncConfig$.next({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, isEncryptionEnabled: true, syncInterval: 300000, }); @@ -688,7 +687,7 @@ describe('SyncConfigService', () => { // Step 1: Simulate initial setup - user enables encryption const initialSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'test-password-123', @@ -708,7 +707,7 @@ describe('SyncConfigService', () => { mockSyncConfig$.next({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, isEncryptionEnabled: true, // This is saved correctly syncInterval: 300000, }); @@ -733,7 +732,7 @@ describe('SyncConfigService', () => { mockSyncConfig$.next({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, isEncryptionEnabled: false, // Encryption is disabled syncInterval: 300000, }); @@ -751,7 +750,7 @@ describe('SyncConfigService', () => { // Ensure our fix doesn't break other providers const webDavSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'webdav-password', @@ -793,7 +792,7 @@ describe('SyncConfigService', () => { // Step 1: User enables LocalFile sync with encryption const newSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'test-password-123', @@ -849,7 +848,7 @@ describe('SyncConfigService', () => { mockSyncConfig$.next({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, isEncryptionEnabled: true, syncInterval: 300000, }); @@ -877,7 +876,7 @@ describe('SyncConfigService', () => { mockSyncConfig$.next({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, isEncryptionEnabled: true, syncInterval: 300000, }); @@ -933,7 +932,7 @@ describe('SyncConfigService', () => { mockSyncConfig$.next({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, superSync: { baseUrl: customUrl, }, @@ -1314,7 +1313,7 @@ describe('SyncConfigService', () => { // Simulate form update with NO encryptKey (stale form model) const formSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: '', // Empty - simulating stale form model @@ -1362,7 +1361,7 @@ describe('SyncConfigService', () => { // Simulate form update with OLD password (stale form model from before dialog) const formSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: oldPassword, // Old - simulating stale form model @@ -1409,7 +1408,7 @@ describe('SyncConfigService', () => { const newFormPassword = 'new-webdav-password'; const formSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: newFormPassword, // New password from form @@ -1449,7 +1448,7 @@ describe('SyncConfigService', () => { // Simulate form update with password in settings.encryptKey (legacy path) const formSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: 'settings-level-password', // Password at settings level @@ -1496,7 +1495,7 @@ describe('SyncConfigService', () => { const formSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, syncInterval: 300000, isEncryptionEnabled: false, encryptKey: '', @@ -1550,7 +1549,7 @@ describe('SyncConfigService', () => { // from BEFORE the dialog updated the password const staleFormSettings: SyncConfig = { isEnabled: true, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, syncInterval: 300000, isEncryptionEnabled: true, encryptKey: '', // STALE: Form model didn't have the new password diff --git a/src/app/imex/sync/sync-wrapper.service.spec.ts b/src/app/imex/sync/sync-wrapper.service.spec.ts index c1dbeaa96d..c150839a54 100644 --- a/src/app/imex/sync/sync-wrapper.service.spec.ts +++ b/src/app/imex/sync/sync-wrapper.service.spec.ts @@ -28,7 +28,6 @@ import { MissingRefreshTokenAPIError, } from '../../op-log/core/errors/sync-errors'; import { MAX_LWW_REUPLOAD_RETRIES } from '../../op-log/core/operation-log.const'; -import { LegacySyncProvider } from './legacy-sync-provider.model'; describe('SyncWrapperService', () => { let service: SyncWrapperService; @@ -49,7 +48,7 @@ describe('SyncWrapperService', () => { let configSubject: BehaviorSubject; let mockSyncCapableProvider: any; - const createMockSyncConfig = (provider: LegacySyncProvider | null): { sync: any } => ({ + const createMockSyncConfig = (provider: SyncProviderId | null): { sync: any } => ({ sync: { syncProvider: provider, syncInterval: 60000, @@ -57,9 +56,7 @@ describe('SyncWrapperService', () => { }); beforeEach(() => { - configSubject = new BehaviorSubject( - createMockSyncConfig(LegacySyncProvider.SuperSync), - ); + configSubject = new BehaviorSubject(createMockSyncConfig(SyncProviderId.SuperSync)); mockSyncCapableProvider = { uploadOperations: jasmine.createSpy('uploadOperations'), @@ -228,7 +225,7 @@ describe('SyncWrapperService', () => { describe('_sync() - Provider handling', () => { it('should call _syncVectorClockToPfapi for WebDAV provider', async () => { - configSubject.next(createMockSyncConfig(LegacySyncProvider.WebDAV)); + configSubject.next(createMockSyncConfig(SyncProviderId.WebDAV)); mockOpLogStore.getVectorClockEntry.and.returnValue( Promise.resolve({ clock: { clientA: 5 }, @@ -244,7 +241,7 @@ describe('SyncWrapperService', () => { }); it('should call _syncVectorClockToPfapi for Dropbox provider', async () => { - configSubject.next(createMockSyncConfig(LegacySyncProvider.Dropbox)); + configSubject.next(createMockSyncConfig(SyncProviderId.Dropbox)); mockOpLogStore.getVectorClockEntry.and.returnValue( Promise.resolve({ clock: { clientA: 5 }, @@ -259,7 +256,7 @@ describe('SyncWrapperService', () => { }); it('should NOT call _syncVectorClockToPfapi for SuperSync provider', async () => { - configSubject.next(createMockSyncConfig(LegacySyncProvider.SuperSync)); + configSubject.next(createMockSyncConfig(SyncProviderId.SuperSync)); await service.sync(); @@ -1067,8 +1064,8 @@ describe('SyncWrapperService', () => { }); describe('syncProviderId$', () => { - it('should convert LegacySyncProvider to SyncProviderId', (done) => { - configSubject.next(createMockSyncConfig(LegacySyncProvider.SuperSync)); + it('should emit SyncProviderId from sync config', (done) => { + configSubject.next(createMockSyncConfig(SyncProviderId.SuperSync)); service.syncProviderId$.subscribe((providerId) => { expect(providerId).toBe(SyncProviderId.SuperSync); @@ -1091,9 +1088,7 @@ describe('SyncWrapperService', () => { let isConfirmedSignal: ReturnType>; let signalConfigSubject: BehaviorSubject; - const createSignalMockConfig = ( - provider: LegacySyncProvider | null, - ): { sync: any } => ({ + const createSignalMockConfig = (provider: SyncProviderId | null): { sync: any } => ({ sync: { syncProvider: provider, syncInterval: 60000, @@ -1103,7 +1098,7 @@ describe('SyncWrapperService', () => { const createServiceWithSignal = (initialValue: boolean): SyncWrapperService => { isConfirmedSignal = signal(initialValue); signalConfigSubject = new BehaviorSubject( - createSignalMockConfig(LegacySyncProvider.SuperSync), + createSignalMockConfig(SyncProviderId.SuperSync), ); const signalMockSuperSyncStatusService = { @@ -1143,7 +1138,7 @@ describe('SyncWrapperService', () => { describe('with SuperSync provider', () => { it('should return true when SuperSyncStatusService.isConfirmedInSync is true', (done) => { signalService = createServiceWithSignal(true); - signalConfigSubject.next(createSignalMockConfig(LegacySyncProvider.SuperSync)); + signalConfigSubject.next(createSignalMockConfig(SyncProviderId.SuperSync)); signalService.superSyncIsConfirmedInSync$.subscribe((isConfirmed) => { expect(isConfirmed).toBe(true); @@ -1153,7 +1148,7 @@ describe('SyncWrapperService', () => { it('should return false when SuperSyncStatusService.isConfirmedInSync is false', (done) => { signalService = createServiceWithSignal(false); - signalConfigSubject.next(createSignalMockConfig(LegacySyncProvider.SuperSync)); + signalConfigSubject.next(createSignalMockConfig(SyncProviderId.SuperSync)); signalService.superSyncIsConfirmedInSync$.subscribe((isConfirmed) => { expect(isConfirmed).toBe(false); @@ -1165,7 +1160,7 @@ describe('SyncWrapperService', () => { describe('with file-based providers', () => { it('should return false for WebDAV when status service returns false', (done) => { signalService = createServiceWithSignal(false); - signalConfigSubject.next(createSignalMockConfig(LegacySyncProvider.WebDAV)); + signalConfigSubject.next(createSignalMockConfig(SyncProviderId.WebDAV)); signalService.superSyncIsConfirmedInSync$.subscribe((isConfirmed) => { expect(isConfirmed).toBe(false); @@ -1175,7 +1170,7 @@ describe('SyncWrapperService', () => { it('should return true for WebDAV when status service returns true', (done) => { signalService = createServiceWithSignal(true); - signalConfigSubject.next(createSignalMockConfig(LegacySyncProvider.WebDAV)); + signalConfigSubject.next(createSignalMockConfig(SyncProviderId.WebDAV)); signalService.superSyncIsConfirmedInSync$.subscribe((isConfirmed) => { expect(isConfirmed).toBe(true); @@ -1185,7 +1180,7 @@ describe('SyncWrapperService', () => { it('should return false for Dropbox when status service returns false', (done) => { signalService = createServiceWithSignal(false); - signalConfigSubject.next(createSignalMockConfig(LegacySyncProvider.Dropbox)); + signalConfigSubject.next(createSignalMockConfig(SyncProviderId.Dropbox)); signalService.superSyncIsConfirmedInSync$.subscribe((isConfirmed) => { expect(isConfirmed).toBe(false); @@ -1195,7 +1190,7 @@ describe('SyncWrapperService', () => { it('should return true for Dropbox when status service returns true', (done) => { signalService = createServiceWithSignal(true); - signalConfigSubject.next(createSignalMockConfig(LegacySyncProvider.Dropbox)); + signalConfigSubject.next(createSignalMockConfig(SyncProviderId.Dropbox)); signalService.superSyncIsConfirmedInSync$.subscribe((isConfirmed) => { expect(isConfirmed).toBe(true); @@ -1205,7 +1200,7 @@ describe('SyncWrapperService', () => { it('should return false for LocalFile when status service returns false', (done) => { signalService = createServiceWithSignal(false); - signalConfigSubject.next(createSignalMockConfig(LegacySyncProvider.LocalFile)); + signalConfigSubject.next(createSignalMockConfig(SyncProviderId.LocalFile)); signalService.superSyncIsConfirmedInSync$.subscribe((isConfirmed) => { expect(isConfirmed).toBe(false); @@ -1215,7 +1210,7 @@ describe('SyncWrapperService', () => { it('should return true for LocalFile when status service returns true', (done) => { signalService = createServiceWithSignal(true); - signalConfigSubject.next(createSignalMockConfig(LegacySyncProvider.LocalFile)); + signalConfigSubject.next(createSignalMockConfig(SyncProviderId.LocalFile)); signalService.superSyncIsConfirmedInSync$.subscribe((isConfirmed) => { expect(isConfirmed).toBe(true); diff --git a/src/app/imex/sync/sync-wrapper.service.ts b/src/app/imex/sync/sync-wrapper.service.ts index 5d45208e0f..b18d88eeb1 100644 --- a/src/app/imex/sync/sync-wrapper.service.ts +++ b/src/app/imex/sync/sync-wrapper.service.ts @@ -59,7 +59,6 @@ import { promiseTimeout } from '../../util/promise-timeout'; import { devError } from '../../util/dev-error'; import { alertDialog, confirmDialog } from '../../util/native-dialogs'; import { UserInputWaitStateService } from './user-input-wait-state.service'; -import { LegacySyncProvider } from './legacy-sync-provider.model'; import { SYNC_WAIT_TIMEOUT_MS, SYNC_REINIT_DELAY_MS } from './sync.const'; import { SuperSyncStatusService } from '../../op-log/sync/super-sync-status.service'; import { IS_ELECTRON } from '../../app.constants'; @@ -99,7 +98,7 @@ export class SyncWrapperService { syncInterval$: Observable = this.syncCfg$.pipe( map((cfg) => { if (cfg.isManualSyncOnly) return 0; - return cfg.syncProvider === LegacySyncProvider.SuperSync ? 60000 : cfg.syncInterval; + return cfg.syncProvider === SyncProviderId.SuperSync ? 60000 : cfg.syncInterval; }), ); diff --git a/src/app/imex/sync/sync.model.ts b/src/app/imex/sync/sync.model.ts index f2be6fd570..f872c20a63 100644 --- a/src/app/imex/sync/sync.model.ts +++ b/src/app/imex/sync/sync.model.ts @@ -6,7 +6,7 @@ import { TaskRepeatCfgState } from '../../features/task-repeat-cfg/task-repeat-c import { TagState } from '../../features/tag/tag.model'; import { SimpleCounterState } from '../../features/simple-counter/simple-counter.model'; import { ProjectArchive } from '../../features/project/project-archive.model'; -import { LegacySyncProvider } from './legacy-sync-provider.model'; +import { SyncProviderId } from '../../op-log/sync-providers/provider.const'; import { ProjectState } from '../../features/project/project.model'; import { NoteState } from '../../features/note/note.model'; import { PlannerState } from '../../features/planner/store/planner.reducer'; @@ -60,9 +60,9 @@ export interface LocalSyncMetaForProvider { } export interface LocalSyncMetaModel { - [LegacySyncProvider.WebDAV]: LocalSyncMetaForProvider; - [LegacySyncProvider.Dropbox]: LocalSyncMetaForProvider; - [LegacySyncProvider.LocalFile]: LocalSyncMetaForProvider; + [SyncProviderId.WebDAV]: LocalSyncMetaForProvider; + [SyncProviderId.Dropbox]: LocalSyncMetaForProvider; + [SyncProviderId.LocalFile]: LocalSyncMetaForProvider; } export type AppBaseDataEntityLikeStates = diff --git a/src/app/op-log/persistence/sync-hydration.service.spec.ts b/src/app/op-log/persistence/sync-hydration.service.spec.ts index 27ef28890e..1e73c4a3f0 100644 --- a/src/app/op-log/persistence/sync-hydration.service.spec.ts +++ b/src/app/op-log/persistence/sync-hydration.service.spec.ts @@ -9,7 +9,7 @@ import { VectorClockService } from '../sync/vector-clock.service'; import { ValidateStateService } from '../validation/validate-state.service'; import { loadAllData } from '../../root-store/meta/load-all-data.action'; import { ActionType, OpType } from '../core/operation.types'; -import { LegacySyncProvider } from '../../imex/sync/legacy-sync-provider.model'; +import { SyncProviderId } from '../sync-providers/provider.const'; import { DEFAULT_GLOBAL_CONFIG } from '../../features/config/default-global-config.const'; import { SnackService } from '../../core/snack/snack.service'; @@ -27,7 +27,7 @@ describe('SyncHydrationService', () => { const defaultLocalSyncConfig = { ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, }; beforeEach(() => { @@ -537,7 +537,7 @@ describe('SyncHydrationService', () => { const localSyncConfig = { ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, }; mockStore.select.and.returnValue(of(localSyncConfig)); @@ -548,7 +548,7 @@ describe('SyncHydrationService', () => { sync: { ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: false, // Another client had sync disabled! - syncProvider: LegacySyncProvider.Dropbox, // Different provider too + syncProvider: SyncProviderId.Dropbox, // Different provider too }, }, task: { ids: [], entities: {} }, @@ -568,7 +568,7 @@ describe('SyncHydrationService', () => { // Step 4: Verify the snapshot has PRESERVED local settings (not remote's false) expect(snapshotSync['isEnabled']).toBe(true); // Local value preserved! - expect(snapshotSync['syncProvider']).toBe(LegacySyncProvider.WebDAV); // Local provider preserved! + expect(snapshotSync['syncProvider']).toBe(SyncProviderId.WebDAV); // Local provider preserved! // Step 5: Simulate what happens on reload // The hydrator will call store.dispatch(loadAllData({ appDataComplete: snapshotState })) @@ -581,7 +581,7 @@ describe('SyncHydrationService', () => { // Final verification: The data dispatched to NgRx has correct local settings expect(dispatchedSync['isEnabled']).toBe(true); - expect(dispatchedSync['syncProvider']).toBe(LegacySyncProvider.WebDAV); + expect(dispatchedSync['syncProvider']).toBe(SyncProviderId.WebDAV); }); it('should preserve local isEnabled when remote has it disabled', async () => { @@ -590,7 +590,7 @@ describe('SyncHydrationService', () => { of({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, }), ); @@ -612,7 +612,7 @@ describe('SyncHydrationService', () => { const globalConfig = savedState['globalConfig'] as Record; const sync = globalConfig['sync'] as Record; expect(sync['isEnabled']).toBe(true); - expect(sync['syncProvider']).toBe(LegacySyncProvider.WebDAV); + expect(sync['syncProvider']).toBe(SyncProviderId.WebDAV); }); it('should preserve local isEnabled when remote has it enabled', async () => { @@ -621,7 +621,7 @@ describe('SyncHydrationService', () => { of({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: false, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, }), ); @@ -651,7 +651,7 @@ describe('SyncHydrationService', () => { of({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, }), ); @@ -660,7 +660,7 @@ describe('SyncHydrationService', () => { globalConfig: { sync: { isEnabled: false, - syncProvider: LegacySyncProvider.Dropbox, + syncProvider: SyncProviderId.Dropbox, }, }, }; @@ -677,7 +677,7 @@ describe('SyncHydrationService', () => { unknown >; const sync = globalConfig['sync'] as Record; - expect(sync['syncProvider']).toBe(LegacySyncProvider.WebDAV); + expect(sync['syncProvider']).toBe(SyncProviderId.WebDAV); expect(sync['isEnabled']).toBe(true); }); @@ -686,7 +686,7 @@ describe('SyncHydrationService', () => { of({ ...DEFAULT_GLOBAL_CONFIG.sync, isEnabled: true, - syncProvider: LegacySyncProvider.SuperSync, + syncProvider: SyncProviderId.SuperSync, }), ); @@ -694,7 +694,7 @@ describe('SyncHydrationService', () => { globalConfig: { sync: { isEnabled: false, - syncProvider: LegacySyncProvider.LocalFile, + syncProvider: SyncProviderId.LocalFile, }, }, }; @@ -707,7 +707,7 @@ describe('SyncHydrationService', () => { const savedGlobalConfig = savedState['globalConfig'] as Record; const savedSync = savedGlobalConfig['sync'] as Record; expect(savedSync['isEnabled']).toBe(true); - expect(savedSync['syncProvider']).toBe(LegacySyncProvider.SuperSync); + expect(savedSync['syncProvider']).toBe(SyncProviderId.SuperSync); // Check dispatch const dispatchCall = mockStore.dispatch.calls.mostRecent(); @@ -718,7 +718,7 @@ describe('SyncHydrationService', () => { .globalConfig as Record; const dispatchedSync = dispatchedGlobalConfig['sync'] as Record; expect(dispatchedSync['isEnabled']).toBe(true); - expect(dispatchedSync['syncProvider']).toBe(LegacySyncProvider.SuperSync); + expect(dispatchedSync['syncProvider']).toBe(SyncProviderId.SuperSync); }); }); }); diff --git a/src/app/op-log/sync-providers/provider.const.ts b/src/app/op-log/sync-providers/provider.const.ts index e624c83f04..30681c23c5 100644 --- a/src/app/op-log/sync-providers/provider.const.ts +++ b/src/app/op-log/sync-providers/provider.const.ts @@ -8,9 +8,7 @@ export enum SyncProviderId { /** * Type-safe conversion from string-based sync provider value to SyncProviderId. - * LegacySyncProvider and SyncProviderId have identical string values but are - * separate types for historical reasons. This provides safe conversion with - * runtime validation. + * Validates that a persisted string value is a valid SyncProviderId at runtime. */ export const toSyncProviderId = ( value: string | null | undefined, diff --git a/src/app/pages/config-page/config-page.component.spec.ts b/src/app/pages/config-page/config-page.component.spec.ts index 650d50e95d..a5432d6022 100644 --- a/src/app/pages/config-page/config-page.component.spec.ts +++ b/src/app/pages/config-page/config-page.component.spec.ts @@ -13,7 +13,7 @@ import { SyncWrapperService } from '../../imex/sync/sync-wrapper.service'; import { ShareService } from '../../core/share/share.service'; import { UserProfileService } from '../../features/user-profile/user-profile.service'; import { MatDialog } from '@angular/material/dialog'; -import { LegacySyncProvider } from '../../imex/sync/legacy-sync-provider.model'; +import { SyncProviderId } from '../../op-log/sync-providers/provider.const'; import { TranslateService } from '@ngx-translate/core'; describe('ConfigPageComponent', () => { @@ -93,7 +93,7 @@ describe('ConfigPageComponent', () => { const fullSyncModel = { isEnabled: true, - syncProvider: LegacySyncProvider.WebDAV, + syncProvider: SyncProviderId.WebDAV, syncInterval: 600000, webDav: webDavCfg, }; diff --git a/src/app/pages/config-page/config-page.component.ts b/src/app/pages/config-page/config-page.component.ts index 90e28a517e..1b0443603b 100644 --- a/src/app/pages/config-page/config-page.component.ts +++ b/src/app/pages/config-page/config-page.component.ts @@ -56,8 +56,7 @@ import { UserProfileService } from '../../features/user-profile/user-profile.ser import { MatDialog } from '@angular/material/dialog'; import { DialogDisableProfilesConfirmationComponent } from '../../features/user-profile/dialog-disable-profiles-confirmation/dialog-disable-profiles-confirmation.component'; import { DialogRestorePointComponent } from '../../imex/sync/dialog-restore-point/dialog-restore-point.component'; -import { LegacySyncProvider } from '../../imex/sync/legacy-sync-provider.model'; -import { toSyncProviderId } from '../../op-log/sync-exports'; +import { SyncProviderId } from '../../op-log/sync-providers/provider.const'; import { DialogConfirmComponent } from '../../ui/dialog-confirm/dialog-confirm.component'; import { LS } from '../../core/persistence/storage-keys.const'; import { MatTab, MatTabGroup, MatTabLabel } from '@angular/material/tabs'; @@ -378,7 +377,7 @@ export class ConfigPageComponent implements OnInit, OnDestroy { if ((item as any).props?.dropboxAuth && item.fieldGroup) { // Check if Dropbox is already authenticated const dropboxProvider = this._providerManager.getProviderById( - toSyncProviderId(LegacySyncProvider.Dropbox)!, + SyncProviderId.Dropbox, ); // We need to check auth status asynchronously, so we'll set initial state @@ -419,7 +418,7 @@ export class ConfigPageComponent implements OnInit, OnDestroy { const result = await this._syncWrapperService.configuredAuthForSyncProviderIfNecessary( - toSyncProviderId(LegacySyncProvider.Dropbox)!, + SyncProviderId.Dropbox, true, // force re-authentication even if already configured ); @@ -525,7 +524,7 @@ export class ConfigPageComponent implements OnInit, OnDestroy { }, { hideExpression: (m: Record) => - !m.isEnabled || m.syncProvider !== LegacySyncProvider.SuperSync, + !m.isEnabled || m.syncProvider !== SyncProviderId.SuperSync, type: 'btn', className: 'mt2 block', templateOptions: {