Handle deleted/moved workspace folders (missing state)
Detect when the current workspace folder cannot be opened and show a dedicated "missing" screen that explains the workspace was not found. Catch failures from get_lists during loadConfig, set a missingWorkspace state and switch to the missing screen, and provide forgetMissingWorkspace() to remove the missing workspace from the config and either switch to the next available workspace or fall back to the setup screen. Add UI in App.svelte to present the workspace name, explanation, and a Continue button that invokes forgetting the missing workspace.
This commit is contained in:
parent
753cb1cad5
commit
ac789e8d56
|
|
@ -29,7 +29,25 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
{#if app.screen === "setup"}
|
||||
{#if app.screen === "missing"}
|
||||
<div class="flex h-full items-center justify-center p-6">
|
||||
<div class="w-full max-w-sm rounded-2xl bg-card-light p-8 shadow-lg dark:bg-card-dark">
|
||||
<h1 class="mb-1 text-2xl font-bold">Workspace Not Found</h1>
|
||||
<p class="mb-2 text-sm text-text-secondary-light dark:text-text-secondary-dark">
|
||||
The workspace <strong>{app.missingWorkspace}</strong> could not be opened. Its folder may have been moved or deleted.
|
||||
</p>
|
||||
<p class="mb-6 text-sm text-text-secondary-light dark:text-text-secondary-dark">
|
||||
It will be removed from your workspace list. You can re-add it if the folder becomes available again.
|
||||
</p>
|
||||
<button
|
||||
onclick={() => app.forgetMissingWorkspace()}
|
||||
class="w-full rounded-lg bg-primary py-2.5 text-sm font-medium text-white hover:bg-primary-hover"
|
||||
>
|
||||
Continue
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{:else if app.screen === "setup"}
|
||||
<SetupScreen cancellable={app.hasWorkspace} />
|
||||
{:else}
|
||||
<TasksScreen />
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ let syncing = $state(false);
|
|||
let syncMode = $state<"full" | "push" | "pull">("full");
|
||||
let lastSyncResult = $state<SyncResult | null>(null);
|
||||
let error = $state<string | null>(null);
|
||||
let missingWorkspace = $state<string | null>(null);
|
||||
|
||||
// ── Derived ──────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -70,8 +71,18 @@ async function loadConfig() {
|
|||
try {
|
||||
config = await invoke<AppConfig>("get_config");
|
||||
if (hasWorkspace) {
|
||||
// Try loading lists — if the workspace path is gone, get_lists will fail
|
||||
lists = [];
|
||||
try {
|
||||
lists = await invoke<TaskList[]>("get_lists");
|
||||
} catch {
|
||||
missingWorkspace = config!.current_workspace;
|
||||
screen = "missing";
|
||||
return;
|
||||
}
|
||||
if (lists.length > 0 && !activeListId) activeListId = lists[0].id;
|
||||
if (activeListId) await loadTasks();
|
||||
screen = "tasks";
|
||||
await loadLists();
|
||||
} else {
|
||||
screen = "setup";
|
||||
}
|
||||
|
|
@ -343,6 +354,26 @@ async function addWebdavWorkspace(name: string, webdavUrl: string, webdavPath: s
|
|||
}
|
||||
}
|
||||
|
||||
async function forgetMissingWorkspace() {
|
||||
if (!missingWorkspace) return;
|
||||
await removeWorkspace(missingWorkspace);
|
||||
missingWorkspace = null;
|
||||
config = await invoke<AppConfig>("get_config");
|
||||
if (hasWorkspace) {
|
||||
// Switch to the next available workspace
|
||||
const nextName = Object.keys(config!.workspaces)[0];
|
||||
if (nextName) {
|
||||
await switchWorkspace(nextName);
|
||||
screen = "tasks";
|
||||
return;
|
||||
}
|
||||
}
|
||||
screen = "setup";
|
||||
lists = [];
|
||||
tasks = [];
|
||||
activeListId = null;
|
||||
}
|
||||
|
||||
function setScreen(s: Screen) {
|
||||
screen = s;
|
||||
}
|
||||
|
|
@ -399,6 +430,9 @@ export const app = {
|
|||
get hasWorkspace() {
|
||||
return hasWorkspace;
|
||||
},
|
||||
get missingWorkspace() {
|
||||
return missingWorkspace;
|
||||
},
|
||||
getSubtasks,
|
||||
loadConfig,
|
||||
addWorkspace,
|
||||
|
|
@ -422,6 +456,7 @@ export const app = {
|
|||
setSyncMode,
|
||||
setTheme,
|
||||
addWebdavWorkspace,
|
||||
forgetMissingWorkspace,
|
||||
setScreen,
|
||||
clearError,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,4 +44,4 @@ export interface SyncResult {
|
|||
errors: string[];
|
||||
}
|
||||
|
||||
export type Screen = "setup" | "tasks" | "settings";
|
||||
export type Screen = "setup" | "tasks" | "settings" | "missing";
|
||||
|
|
|
|||
Loading…
Reference in a new issue