fix: clear missing active vault paths
This commit is contained in:
@@ -87,6 +87,38 @@ describe('useOnboarding', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('clears the persisted active vault when the saved path no longer exists', async () => {
|
||||
localStorage.setItem('laputa_welcome_dismissed', '1')
|
||||
|
||||
mockInvokeFn.mockImplementation(async (cmd: string) => {
|
||||
if (cmd === 'get_default_vault_path') return '/mock/Documents/Getting Started'
|
||||
if (cmd === 'check_vault_exists') return false
|
||||
if (cmd === 'load_vault_list') {
|
||||
return {
|
||||
vaults: [{ label: 'Old Vault', path: '/vault/deleted' }],
|
||||
active_vault: '/vault/deleted',
|
||||
hidden_defaults: [],
|
||||
}
|
||||
}
|
||||
if (cmd === 'save_vault_list') return null
|
||||
return null
|
||||
})
|
||||
|
||||
const { result } = renderHook(() => useOnboarding('/vault/deleted'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.state.status).toBe('vault-missing')
|
||||
})
|
||||
|
||||
expect(mockInvokeFn).toHaveBeenCalledWith('save_vault_list', {
|
||||
list: {
|
||||
vaults: [{ label: 'Old Vault', path: '/vault/deleted' }],
|
||||
active_vault: null,
|
||||
hidden_defaults: [],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('handleCreateVault creates vault and transitions to ready', async () => {
|
||||
mockInvokeFn.mockImplementation(async (cmd: string) => {
|
||||
if (cmd === 'get_default_vault_path') return '/mock/Documents/Getting Started'
|
||||
|
||||
@@ -15,6 +15,12 @@ function tauriCall<T>(command: string, args: Record<string, unknown>): Promise<T
|
||||
|
||||
const DISMISSED_KEY = 'laputa_welcome_dismissed'
|
||||
|
||||
interface PersistedVaultList {
|
||||
vaults?: Array<{ label: string; path: string }>
|
||||
active_vault?: string | null
|
||||
hidden_defaults?: string[]
|
||||
}
|
||||
|
||||
function wasDismissed(): boolean {
|
||||
try {
|
||||
return localStorage.getItem(DISMISSED_KEY) === '1'
|
||||
@@ -31,6 +37,22 @@ function markDismissed(): void {
|
||||
}
|
||||
}
|
||||
|
||||
async function clearMissingActiveVault(missingPath: string): Promise<void> {
|
||||
try {
|
||||
const list = await tauriCall<PersistedVaultList>('load_vault_list', {})
|
||||
if (!list || list.active_vault !== missingPath) return
|
||||
await tauriCall('save_vault_list', {
|
||||
list: {
|
||||
vaults: list.vaults ?? [],
|
||||
active_vault: null,
|
||||
hidden_defaults: list.hidden_defaults ?? [],
|
||||
},
|
||||
})
|
||||
} catch {
|
||||
// Best effort only — onboarding should still proceed
|
||||
}
|
||||
}
|
||||
|
||||
export function useOnboarding(initialVaultPath: string) {
|
||||
const [state, setState] = useState<OnboardingState>({ status: 'loading' })
|
||||
const [creating, setCreating] = useState(false)
|
||||
@@ -48,7 +70,16 @@ export function useOnboarding(initialVaultPath: string) {
|
||||
|
||||
if (exists) {
|
||||
setState({ status: 'ready', vaultPath: initialVaultPath })
|
||||
} else if (wasDismissed()) {
|
||||
} else {
|
||||
await clearMissingActiveVault(initialVaultPath)
|
||||
if (cancelled) return
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
return
|
||||
}
|
||||
|
||||
if (wasDismissed()) {
|
||||
// User previously dismissed — show vault-missing instead of welcome
|
||||
setState({ status: 'vault-missing', vaultPath: initialVaultPath, defaultPath })
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user