fix(welcome): ask to remove a recent project whose folder is gone (#2131)

Opening a recent project whose folder no longer exists reported the failure as a
notification, which is not shown when the system group's balloons are off, and the
welcome screen has no list to find it in, so the click did nothing. It now opens a
dialog offering to remove the entry. The open failure's kind is also read from the
raw error the trust check rejects with, so a missing folder is no longer reported as
a generic failure.

Co-authored-by: Claude <[email protected]>
Цей коміт міститься в:
l0ng-aiтаClaude authored and GitHub committed 2026-11-08 18:26:38 +08:00
1 джерело 47d547e206
коміт cbe4355b8d
1 file changed
+22 -4
+22 -4
Переглянути файл
@@ -24,6 +24,7 @@ import {
import { tx } from "@/platform/i18n";
import { fuzzyMatch } from "@/ui";
import { notifications } from "@/workbench/contributions";
import { confirm } from "@/workbench/messages";
import { openRemoteProject } from "@/workbench/projectWindow";
interface RecentState {
@@ -115,6 +116,14 @@ export async function removeRecent(path: string) {
notifications().notify({ level: "error", title: "Cannot remove recent project", body: r.error.message });
}
/** An open failure's kind and message, whether it is an `IpcError` or a raw rejected invoke. */
function failure(e: unknown): { kind?: string; message: string } {
if (e instanceof IpcError) return { kind: e.kind, message: e.message };
if (e && typeof e === "object" && "message" in e)
return { kind: (e as { kind?: string }).kind, message: String((e as { message: unknown }).message) };
return { message: e instanceof Error ? e.message : String(e) };
}
/** Opens a project from the recent list; offers to remove entries whose folder is gone. */
export async function openRecent(project: Pick<RecentProject, "path" | "name">): Promise<boolean> {
if (!isTauri()) {
@@ -140,12 +149,21 @@ export async function openRecent(project: Pick<RecentProject, "path" | "name">):
return true;
} catch (e) {
if (isCancelled(e)) return false;
const message = e instanceof Error ? e.message : String(e);
const missing = e instanceof IpcError ? e.kind === "notFound" : /not found|no such/i.test(message);
const { kind, message } = failure(e);
if (kind === "notFound" || (!kind && /not found|no such/i.test(message))) {
// A balloon can be switched off for this group and the welcome screen has no log to open.
const remove = await confirm({
title: tx`Project folder not found: ${project.name}`,
message: project.path,
ok: "Remove from Recent Projects",
});
if (remove) await removeRecent(project.path);
return false;
}
notifications().notify({
level: "error",
title: missing ? `Project folder not found: ${project.name}` : `Cannot open ${project.name}`,
body: missing ? project.path : message,
title: `Cannot open ${project.name}`,
body: message,
key: `welcome.open:${project.path}`,
actions: [{ label: "Remove from Recent Projects", run: () => void removeRecent(project.path) }],
});