Skip to content

Commit 38fba16

Browse files
committed
refactor: improve SoC re Projects between renderer and main
1 parent 4b7c372 commit 38fba16

File tree

9 files changed

+206
-161
lines changed

9 files changed

+206
-161
lines changed

src/App.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ function AppInner() {
171171

172172
const { workspaceMetadata, createWorkspace, removeWorkspace, renameWorkspace } =
173173
useWorkspaceManagement({
174-
projects,
175174
selectedWorkspace,
176175
onProjectsUpdate: handleProjectsUpdate,
177176
onSelectedWorkspaceUpdate: setSelectedWorkspace,
@@ -220,12 +219,15 @@ function AppInner() {
220219
};
221220

222221
const handleGetSecrets = useCallback(async (projectPath: string) => {
223-
return await window.api.secrets.get(projectPath);
222+
return await window.api.projects.secrets.get(projectPath);
224223
}, []);
225224

226225
const handleUpdateSecrets = useCallback(
227226
async (projectPath: string, secrets: Array<{ key: string; value: string }>) => {
228-
await window.api.secrets.update(projectPath, secrets);
227+
const result = await window.api.projects.secrets.update(projectPath, secrets);
228+
if (!result.success) {
229+
console.error("Failed to update secrets:", result.error);
230+
}
229231
},
230232
[]
231233
);

src/constants/ipc-constants.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,19 @@
44
*/
55

66
export const IPC_CHANNELS = {
7-
// Config channels
8-
CONFIG_LOAD: "config:load",
9-
CONFIG_SAVE: "config:save",
10-
117
// Dialog channels
128
DIALOG_SELECT_DIR: "dialog:selectDirectory",
139

1410
// Provider channels
1511
PROVIDERS_SET_CONFIG: "providers:setConfig",
1612
PROVIDERS_LIST: "providers:list",
1713

18-
// Secrets channels
19-
SECRETS_GET: "secrets:get",
20-
SECRETS_UPDATE: "secrets:update",
14+
// Project channels
15+
PROJECT_CREATE: "project:create",
16+
PROJECT_REMOVE: "project:remove",
17+
PROJECT_LIST: "project:list",
18+
PROJECT_SECRETS_GET: "project:secrets:get",
19+
PROJECT_SECRETS_UPDATE: "project:secrets:update",
2120

2221
// Workspace channels
2322
WORKSPACE_LIST: "workspace:list",

src/hooks/useProjectManagement.ts

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,53 +13,56 @@ export function useProjectManagement() {
1313

1414
const loadProjects = async () => {
1515
try {
16-
console.log("Loading projects from config...");
17-
const config = await window.api.config.load();
18-
console.log("Received config:", config);
16+
console.log("Loading projects...");
17+
const projectsList = await window.api.projects.list();
18+
console.log("Received projects:", projectsList);
1919

20-
if (config && Array.isArray(config.projects)) {
21-
console.log("Projects array length:", config.projects.length);
22-
const projectsMap = new Map<string, ProjectConfig>(config.projects);
23-
console.log("Created projects map, size:", projectsMap.size);
24-
setProjects(projectsMap);
25-
} else {
26-
console.log("No projects or invalid format");
27-
setProjects(new Map());
28-
}
20+
const projectsMap = new Map<string, ProjectConfig>(projectsList.map((p) => [p.path, p]));
21+
console.log("Created projects map, size:", projectsMap.size);
22+
setProjects(projectsMap);
2923
} catch (error) {
30-
console.error("Failed to load config:", error);
24+
console.error("Failed to load projects:", error);
3125
setProjects(new Map());
3226
}
3327
};
3428

3529
const addProject = async () => {
3630
try {
3731
const selectedPath = await window.api.dialog.selectDirectory();
38-
if (selectedPath && !projects.has(selectedPath)) {
32+
if (!selectedPath) return;
33+
34+
if (projects.has(selectedPath)) {
35+
console.log("Project already exists:", selectedPath);
36+
return;
37+
}
38+
39+
const result = await window.api.projects.create(selectedPath);
40+
if (result.success) {
3941
const newProjects = new Map(projects);
40-
newProjects.set(selectedPath, { path: selectedPath, workspaces: [] });
42+
newProjects.set(selectedPath, result.data);
4143
setProjects(newProjects);
42-
43-
await window.api.config.save({
44-
projects: Array.from(newProjects.entries()),
45-
});
44+
} else {
45+
console.error("Failed to create project:", result.error);
4646
}
4747
} catch (error) {
4848
console.error("Failed to add project:", error);
4949
}
5050
};
5151

5252
const removeProject = async (path: string) => {
53-
const newProjects = new Map(projects);
54-
newProjects.delete(path);
55-
setProjects(newProjects);
56-
5753
try {
58-
await window.api.config.save({
59-
projects: Array.from(newProjects.entries()),
60-
});
54+
const result = await window.api.projects.remove(path);
55+
if (result.success) {
56+
const newProjects = new Map(projects);
57+
newProjects.delete(path);
58+
setProjects(newProjects);
59+
} else {
60+
console.error("Failed to remove project:", result.error);
61+
// Show error to user - they might need to remove workspaces first
62+
alert(result.error);
63+
}
6164
} catch (error) {
62-
console.error("Failed to save config:", error);
65+
console.error("Failed to remove project:", error);
6366
}
6467
};
6568

src/hooks/useWorkspaceManagement.ts

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { WorkspaceSelection } from "@/components/ProjectSidebar";
44
import type { ProjectConfig } from "@/config";
55

66
interface UseWorkspaceManagementProps {
7-
projects: Map<string, ProjectConfig>;
87
selectedWorkspace: WorkspaceSelection | null;
98
onProjectsUpdate: (projects: Map<string, ProjectConfig>) => void;
109
onSelectedWorkspaceUpdate: (workspace: WorkspaceSelection | null) => void;
@@ -14,7 +13,6 @@ interface UseWorkspaceManagementProps {
1413
* Hook to manage workspace operations (create, remove, rename, list)
1514
*/
1615
export function useWorkspaceManagement({
17-
projects,
1816
selectedWorkspace,
1917
onProjectsUpdate,
2018
onSelectedWorkspaceUpdate,
@@ -43,30 +41,21 @@ export function useWorkspaceManagement({
4341
const createWorkspace = async (projectPath: string, branchName: string) => {
4442
const result = await window.api.workspace.create(projectPath, branchName);
4543
if (result.success) {
46-
// Update the project config with the new workspace
47-
const newProjects = new Map(projects);
48-
const projectConfig = newProjects.get(projectPath);
49-
if (projectConfig) {
50-
projectConfig.workspaces.push({
51-
path: result.metadata.workspacePath,
52-
});
53-
onProjectsUpdate(newProjects);
54-
55-
await window.api.config.save({
56-
projects: Array.from(newProjects.entries()),
57-
});
44+
// Backend has already updated the config - reload projects to get updated state
45+
const projectsList = await window.api.projects.list();
46+
const loadedProjects = new Map(projectsList.map((p) => [p.path, p]));
47+
onProjectsUpdate(loadedProjects);
5848

59-
// Reload workspace metadata to get the new workspace ID
60-
await loadWorkspaceMetadata();
49+
// Reload workspace metadata to get the new workspace ID
50+
await loadWorkspaceMetadata();
6151

62-
// Return the new workspace selection
63-
return {
64-
projectPath,
65-
projectName: result.metadata.projectName,
66-
workspacePath: result.metadata.workspacePath,
67-
workspaceId: result.metadata.id,
68-
};
69-
}
52+
// Return the new workspace selection
53+
return {
54+
projectPath,
55+
projectName: result.metadata.projectName,
56+
workspacePath: result.metadata.workspacePath,
57+
workspaceId: result.metadata.id,
58+
};
7059
} else {
7160
throw new Error(result.error);
7261
}
@@ -77,9 +66,9 @@ export function useWorkspaceManagement({
7766
): Promise<{ success: boolean; error?: string }> => {
7867
const result = await window.api.workspace.remove(workspaceId);
7968
if (result.success) {
80-
// Reload config since backend has updated it
81-
const config = await window.api.config.load();
82-
const loadedProjects = new Map(config.projects);
69+
// Backend has already updated the config - reload projects to get updated state
70+
const projectsList = await window.api.projects.list();
71+
const loadedProjects = new Map(projectsList.map((p) => [p.path, p]));
8372
onProjectsUpdate(loadedProjects);
8473

8574
// Reload workspace metadata
@@ -102,9 +91,9 @@ export function useWorkspaceManagement({
10291
): Promise<{ success: boolean; error?: string }> => {
10392
const result = await window.api.workspace.rename(workspaceId, newName);
10493
if (result.success) {
105-
// Reload config since backend has updated it
106-
const config = await window.api.config.load();
107-
const loadedProjects = new Map(config.projects);
94+
// Backend has already updated the config - reload projects to get updated state
95+
const projectsList = await window.api.projects.list();
96+
const loadedProjects = new Map(projectsList.map((p) => [p.path, p]));
10897
onProjectsUpdate(loadedProjects);
10998

11099
// Reload workspace metadata

src/preload.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ import { IPC_CHANNELS, getChatChannel } from "./constants/ipc-constants";
2525

2626
// Build the API implementation using the shared interface
2727
const api: IPCApi = {
28-
config: {
29-
load: () => ipcRenderer.invoke(IPC_CHANNELS.CONFIG_LOAD),
30-
save: (config) => ipcRenderer.invoke(IPC_CHANNELS.CONFIG_SAVE, config),
31-
},
3228
dialog: {
3329
selectDirectory: () => ipcRenderer.invoke(IPC_CHANNELS.DIALOG_SELECT_DIR),
3430
},
@@ -37,10 +33,15 @@ const api: IPCApi = {
3733
ipcRenderer.invoke(IPC_CHANNELS.PROVIDERS_SET_CONFIG, provider, keyPath, value),
3834
list: () => ipcRenderer.invoke(IPC_CHANNELS.PROVIDERS_LIST),
3935
},
40-
secrets: {
41-
get: (projectPath) => ipcRenderer.invoke(IPC_CHANNELS.SECRETS_GET, projectPath),
42-
update: (projectPath, secrets) =>
43-
ipcRenderer.invoke(IPC_CHANNELS.SECRETS_UPDATE, projectPath, secrets),
36+
projects: {
37+
create: (projectPath) => ipcRenderer.invoke(IPC_CHANNELS.PROJECT_CREATE, projectPath),
38+
remove: (projectPath) => ipcRenderer.invoke(IPC_CHANNELS.PROJECT_REMOVE, projectPath),
39+
list: () => ipcRenderer.invoke(IPC_CHANNELS.PROJECT_LIST),
40+
secrets: {
41+
get: (projectPath) => ipcRenderer.invoke(IPC_CHANNELS.PROJECT_SECRETS_GET, projectPath),
42+
update: (projectPath, secrets) =>
43+
ipcRenderer.invoke(IPC_CHANNELS.PROJECT_SECRETS_UPDATE, projectPath, secrets),
44+
},
4445
},
4546
workspace: {
4647
list: () => ipcRenderer.invoke(IPC_CHANNELS.WORKSPACE_LIST),

0 commit comments

Comments
 (0)