diff --git a/src/App.test.tsx b/src/App.test.tsx index ec5257dd..5f503023 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -495,6 +495,24 @@ describe('App', () => { expect(screen.getByTestId('welcome-open-folder')).toHaveTextContent('Choose a different folder') }) + it('shows welcome instead of vault-missing when the missing path was not a persisted active vault', async () => { + localStorage.setItem('tolaria_welcome_dismissed', '1') + mockCommandResults.load_vault_list = { + vaults: [], + active_vault: null, + hidden_defaults: [], + } + mockCommandResults.check_vault_exists = (args?: { path?: string }) => args?.path === '/Users/mock/Documents/Getting Started' + + render() + + await waitFor(() => { + expect(screen.getByText('Welcome to Tolaria')).toBeInTheDocument() + }) + expect(screen.queryByText('Vault not found')).not.toBeInTheDocument() + expect(screen.getByTestId('welcome-open-folder')).toHaveTextContent('Open existing vault') + }) + it('renders sidebar with correct default selection (All Notes)', async () => { render() await waitFor(() => { diff --git a/src/hooks/useOnboarding.test.ts b/src/hooks/useOnboarding.test.ts index 486aeb26..0d93ed96 100644 --- a/src/hooks/useOnboarding.test.ts +++ b/src/hooks/useOnboarding.test.ts @@ -155,6 +155,21 @@ describe('useOnboarding', () => { }) }) + it('shows welcome instead of vault-missing when no persisted active vault matches the missing path', async () => { + localStorage.setItem(APP_STORAGE_KEYS.welcomeDismissed, '1') + mockCommands({ + load_vault_list: { + vaults: [], + active_vault: null, + hidden_defaults: [], + }, + }) + + const { result } = await renderOnboarding('/vault/deleted') + + expect(result.current.state).toEqual({ status: 'welcome', defaultPath: DEFAULT_GETTING_STARTED_PATH }) + }) + it('clears the persisted active vault when the saved path no longer exists', async () => { localStorage.setItem(LEGACY_APP_STORAGE_KEYS.welcomeDismissed, '1') mockCommands({ diff --git a/src/hooks/useOnboarding.ts b/src/hooks/useOnboarding.ts index 3ec6f231..d0a52367 100644 --- a/src/hooks/useOnboarding.ts +++ b/src/hooks/useOnboarding.ts @@ -40,10 +40,10 @@ function markDismissed(): void { } } -async function clearMissingActiveVault(missingPath: string): Promise { +async function clearMissingActiveVault(missingPath: string): Promise { try { const list = await tauriCall('load_vault_list', {}) - if (!list || list.active_vault !== missingPath) return + if (!list || list.active_vault !== missingPath) return false await tauriCall('save_vault_list', { list: { vaults: list.vaults ?? [], @@ -51,8 +51,10 @@ async function clearMissingActiveVault(missingPath: string): Promise { hidden_defaults: list.hidden_defaults ?? [], }, }) + return true } catch { // Best effort only — onboarding should still proceed + return false } } @@ -84,17 +86,14 @@ export function useOnboarding( if (exists) { setState({ status: 'ready', vaultPath: initialVaultPath }) - } else { - await clearMissingActiveVault(initialVaultPath) - if (cancelled) return - } - - if (exists) { return } - if (wasDismissed()) { - // User previously dismissed — show vault-missing instead of welcome + const missingWasPersistedActiveVault = await clearMissingActiveVault(initialVaultPath) + if (cancelled) return + + if (wasDismissed() && missingWasPersistedActiveVault) { + // Only show vault-missing when a previously selected vault path truly disappeared. setState({ status: 'vault-missing', vaultPath: initialVaultPath, defaultPath }) } else { setState({ status: 'welcome', defaultPath })