|
1 | 1 | import { produce } from 'solid-js/store'; |
2 | 2 | import { openDialog } from '../lib/dialog'; |
| 3 | +import { invoke } from '../lib/ipc'; |
| 4 | +import { IPC } from '../../electron/ipc/channels'; |
3 | 5 | import { store, setStore } from './core'; |
4 | 6 | import { closeTask } from './tasks'; |
5 | 7 | import type { Project } from './types'; |
@@ -36,6 +38,7 @@ export function removeProject(projectId: string): void { |
36 | 38 | if (s.lastProjectId === projectId) { |
37 | 39 | s.lastProjectId = s.projects[0]?.id ?? null; |
38 | 40 | } |
| 41 | + delete s.missingProjectIds[projectId]; |
39 | 42 | }), |
40 | 43 | ); |
41 | 44 | } |
@@ -115,3 +118,46 @@ export async function pickAndAddProject(): Promise<string | null> { |
115 | 118 | const name = segments[segments.length - 1] || path; |
116 | 119 | return addProject(name, path); |
117 | 120 | } |
| 121 | + |
| 122 | +/** Check each project path and record which ones are missing. */ |
| 123 | +export async function validateProjectPaths(): Promise<void> { |
| 124 | + const missing: Record<string, true> = {}; |
| 125 | + for (const project of store.projects) { |
| 126 | + try { |
| 127 | + const exists = await invoke<boolean>(IPC.CheckPathExists, { path: project.path }); |
| 128 | + if (!exists) missing[project.id] = true; |
| 129 | + } catch { |
| 130 | + missing[project.id] = true; |
| 131 | + } |
| 132 | + } |
| 133 | + setStore('missingProjectIds', missing); |
| 134 | +} |
| 135 | + |
| 136 | +/** Let the user pick a new folder for a project whose path is missing. */ |
| 137 | +export async function relinkProject(projectId: string): Promise<boolean> { |
| 138 | + const selected = await openDialog({ directory: true, multiple: false }); |
| 139 | + if (!selected) return false; |
| 140 | + const newPath = selected as string; |
| 141 | + |
| 142 | + setStore( |
| 143 | + produce((s) => { |
| 144 | + const idx = s.projects.findIndex((p) => p.id === projectId); |
| 145 | + if (idx === -1) return; |
| 146 | + s.projects[idx].path = newPath; |
| 147 | + }), |
| 148 | + ); |
| 149 | + |
| 150 | + const exists = await invoke<boolean>(IPC.CheckPathExists, { path: newPath }); |
| 151 | + if (exists) { |
| 152 | + setStore('missingProjectIds', (prev: Record<string, true>) => { |
| 153 | + const next = { ...prev }; |
| 154 | + delete next[projectId]; |
| 155 | + return next; |
| 156 | + }); |
| 157 | + } |
| 158 | + return exists; |
| 159 | +} |
| 160 | + |
| 161 | +export function isProjectMissing(projectId: string): boolean { |
| 162 | + return projectId in store.missingProjectIds; |
| 163 | +} |
0 commit comments