diff --git a/src/hooks/useAppSave.ts b/src/hooks/useAppSave.ts index 9281866b..8821f8ef 100644 --- a/src/hooks/useAppSave.ts +++ b/src/hooks/useAppSave.ts @@ -452,7 +452,7 @@ interface EditorPersistenceOptions { resolveCurrentPath: (path: string) => string resolvePathBeforeSave: (path: string) => Promise canPersist: boolean - persistenceScope: string + persistenceScope: string | readonly string[] locale: AppLocale } diff --git a/src/hooks/useEditorSave.ts b/src/hooks/useEditorSave.ts index f7dcf911..576098b7 100644 --- a/src/hooks/useEditorSave.ts +++ b/src/hooks/useEditorSave.ts @@ -243,7 +243,7 @@ function usePendingContentScopeReset({ }: { cancelAutoSave: () => void pendingContentRef: MutableRefObject - persistenceScope?: string + persistenceScope?: string | readonly string[] }) { const previousScopeRef = useRef(persistenceScope) diff --git a/src/hooks/useEditorSaveWithLinks.ts b/src/hooks/useEditorSaveWithLinks.ts index 8479dd51..13246cb6 100644 --- a/src/hooks/useEditorSaveWithLinks.ts +++ b/src/hooks/useEditorSaveWithLinks.ts @@ -98,7 +98,7 @@ export function useEditorSaveWithLinks(config: { resolvePath?: (path: string) => string resolvePathBeforeSave?: (path: string) => Promise canPersist?: boolean - persistenceScope?: string + persistenceScope?: string | readonly string[] disabledSaveMessage?: string locale?: AppLocale }) { diff --git a/src/hooks/useVaultLoader.ts b/src/hooks/useVaultLoader.ts index 76dd43ee..75949e0d 100644 --- a/src/hooks/useVaultLoader.ts +++ b/src/hooks/useVaultLoader.ts @@ -60,7 +60,7 @@ async function loadInitialVaultChromeState(options: InitialVaultChromeOptions): async function loadInitialVaultEntriesState(options: Pick< InitialVaultLoadStateOptions, - 'handleVaultAvailable' | 'handleVaultUnavailable' | 'isCurrentVaultPath' | 'path' | 'setEntries' + 'defaultWorkspacePath' | 'handleVaultAvailable' | 'handleVaultUnavailable' | 'isCurrentVaultPath' | 'path' | 'setEntries' | 'vaults' >): Promise { const { handleVaultAvailable, handleVaultUnavailable, isCurrentVaultPath, path, setEntries } = options diff --git a/src/hooks/useVaultSwitcher.ts b/src/hooks/useVaultSwitcher.ts index cad16ce8..993a7846 100644 --- a/src/hooks/useVaultSwitcher.ts +++ b/src/hooks/useVaultSwitcher.ts @@ -551,6 +551,7 @@ function usePersistedVaultState(onSwitchRef: MutableRefObject<() => void>): Pers return { defaultAvailable, defaultPath, + defaultWorkspacePath, extraVaults, hiddenDefaults, lastPersistedSnapshotRef, diff --git a/src/utils/vaultMetadataNormalization.ts b/src/utils/vaultMetadataNormalization.ts index afe134e7..397ce8c0 100644 --- a/src/utils/vaultMetadataNormalization.ts +++ b/src/utils/vaultMetadataNormalization.ts @@ -118,6 +118,27 @@ function normalizeFileKind(value: unknown): VaultEntry['fileKind'] { return undefined } +function normalizeWorkspaceIdentity(value: unknown): WorkspaceIdentity | undefined { + const source = recordFrom(value) + const id = stringFrom(source.id).trim() + const label = stringFrom(source.label).trim() + const alias = stringFrom(source.alias).trim() + const path = stringFrom(source.path).trim() + if (!id || !label || !alias || !path) return undefined + return { + id, + label, + alias, + path, + shortLabel: stringFrom(source.shortLabel).trim() || label.slice(0, 2).toUpperCase(), + color: nullableStringFrom(source.color), + icon: nullableStringFrom(source.icon), + mounted: booleanFrom(source.mounted, true), + available: booleanFrom(source.available, true), + defaultForNewNotes: booleanFrom(source.defaultForNewNotes), + } +} + function normalizeFilterGroup(value: unknown): FilterGroup { const source = recordFrom(value) if (Array.isArray(source.all)) return { all: source.all as FilterNode[] } @@ -146,7 +167,7 @@ function normalizeVaultEntryRecord({ rawEntry, vaultPath, index, workspace }: En path, filename, title, - workspace: workspace ?? (isRecord(source.workspace) ? source.workspace as WorkspaceIdentity : undefined), + workspace: workspace ?? normalizeWorkspaceIdentity(source.workspace), isA: nullableStringFrom(source.isA), aliases: stringArrayFrom(source.aliases), belongsTo: stringArrayFrom(source.belongsTo), diff --git a/src/utils/vaultPathContainment.ts b/src/utils/vaultPathContainment.ts index 0c0e0ee8..2c197ff8 100644 --- a/src/utils/vaultPathContainment.ts +++ b/src/utils/vaultPathContainment.ts @@ -12,7 +12,7 @@ function compareVaultContainmentPath(path: string, vaultPath: string): [string, } export function canWritePathToVault(path: string, vaultPath: string | readonly string[]): boolean { - if (Array.isArray(vaultPath)) { + if (typeof vaultPath !== 'string') { return vaultPath.some((candidate) => canWritePathToVault(path, candidate)) } const trimmedVaultPath = vaultPath.trim() diff --git a/src/utils/workspaces.ts b/src/utils/workspaces.ts index 1a821d3c..2abc68da 100644 --- a/src/utils/workspaces.ts +++ b/src/utils/workspaces.ts @@ -65,7 +65,7 @@ export function workspaceLabelForEntry(entry: Pick): st } export function workspaceDisplayPrefix(entry: Pick): string | null { - const workspace = workspaceForEntry(entry) + const workspace = entry.workspace ?? null return workspace ? `${workspace.label} / ` : null }