Skip to content

Commit 6bd00cb

Browse files
committed
Merge remote-tracking branch 'origin/main' into pr/14
2 parents 30212c0 + f651e28 commit 6bd00cb

6 files changed

Lines changed: 78 additions & 1 deletion

File tree

src-tauri/capabilities/default.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"permissions": [
77
"core:default",
88
"opener:default",
9-
"dialog:default"
9+
"dialog:default",
10+
"core:window:allow-start-dragging"
1011
]
1112
}

src/App.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ function MainApp() {
104104
connectWorkspace,
105105
markWorkspaceConnected,
106106
updateWorkspaceSettings,
107+
removeWorkspace,
107108
hasLoaded,
108109
refreshWorkspaces,
109110
} = useWorkspaces({ onDebug: addDebugEntry });
@@ -426,6 +427,9 @@ function MainApp() {
426427
onDeleteThread={(workspaceId, threadId) => {
427428
removeThread(workspaceId, threadId);
428429
}}
430+
onDeleteWorkspace={(workspaceId) => {
431+
void removeWorkspace(workspaceId);
432+
}}
429433
/>
430434
);
431435

src/components/Sidebar.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type SidebarProps = {
2424
onToggleWorkspaceCollapse: (workspaceId: string, collapsed: boolean) => void;
2525
onSelectThread: (workspaceId: string, threadId: string) => void;
2626
onDeleteThread: (workspaceId: string, threadId: string) => void;
27+
onDeleteWorkspace: (workspaceId: string) => void;
2728
};
2829

2930
export function Sidebar({
@@ -42,6 +43,7 @@ export function Sidebar({
4243
onToggleWorkspaceCollapse,
4344
onSelectThread,
4445
onDeleteThread,
46+
onDeleteWorkspace,
4547
}: SidebarProps) {
4648
const [expandedWorkspaces, setExpandedWorkspaces] = useState(
4749
new Set<string>(),
@@ -70,6 +72,22 @@ export function Sidebar({
7072
await menu.popup(position, window);
7173
}
7274

75+
async function showWorkspaceMenu(
76+
event: React.MouseEvent,
77+
workspaceId: string,
78+
) {
79+
event.preventDefault();
80+
event.stopPropagation();
81+
const deleteItem = await MenuItem.new({
82+
text: "Delete",
83+
action: () => onDeleteWorkspace(workspaceId),
84+
});
85+
const menu = await Menu.new({ items: [deleteItem] });
86+
const window = getCurrentWindow();
87+
const position = new LogicalPosition(event.clientX, event.clientY);
88+
await menu.popup(position, window);
89+
}
90+
7391
const usagePercent = accountRateLimits?.primary?.usedPercent;
7492
const globalUsagePercent = accountRateLimits?.secondary?.usedPercent;
7593
const credits = accountRateLimits?.credits ?? null;
@@ -152,6 +170,7 @@ export function Sidebar({
152170
role="button"
153171
tabIndex={0}
154172
onClick={() => onSelectWorkspace(entry.id)}
173+
onContextMenu={(event) => showWorkspaceMenu(event, entry.id)}
155174
onKeyDown={(event) => {
156175
if (event.key === "Enter" || event.key === " ") {
157176
event.preventDefault();

src/hooks/useWorkspaces.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { useCallback, useEffect, useMemo, useState } from "react";
22
import type { DebugEntry } from "../types";
33
import type { WorkspaceInfo, WorkspaceSettings } from "../types";
4+
import { ask } from "@tauri-apps/plugin-dialog";
45
import {
56
addWorkspace as addWorkspaceService,
67
connectWorkspace as connectWorkspaceService,
78
listWorkspaces,
89
pickWorkspacePath,
10+
removeWorkspace as removeWorkspaceService,
911
updateWorkspaceSettings as updateWorkspaceSettingsService,
1012
} from "../services/tauri";
1113

@@ -149,6 +151,48 @@ export function useWorkspaces(options: UseWorkspacesOptions = {}) {
149151
}
150152
}
151153

154+
async function removeWorkspace(workspaceId: string) {
155+
const workspace = workspaces.find((entry) => entry.id === workspaceId);
156+
const workspaceName = workspace?.name || "this workspace";
157+
158+
const confirmed = await ask(
159+
`Are you sure you want to delete "${workspaceName}"?\n\nThis will remove the workspace from CodexMonitor.`,
160+
{
161+
title: "Delete Workspace",
162+
kind: "warning",
163+
okLabel: "Delete",
164+
cancelLabel: "Cancel",
165+
},
166+
);
167+
168+
if (!confirmed) {
169+
return;
170+
}
171+
172+
onDebug?.({
173+
id: `${Date.now()}-client-remove-workspace`,
174+
timestamp: Date.now(),
175+
source: "client",
176+
label: "workspace/remove",
177+
payload: { workspaceId },
178+
});
179+
try {
180+
await removeWorkspaceService(workspaceId);
181+
setWorkspaces((prev) => prev.filter((entry) => entry.id !== workspaceId));
182+
setActiveWorkspaceId((prev) => (prev === workspaceId ? null : prev));
183+
await refreshWorkspaces();
184+
} catch (error) {
185+
onDebug?.({
186+
id: `${Date.now()}-client-remove-workspace-error`,
187+
timestamp: Date.now(),
188+
source: "error",
189+
label: "workspace/remove error",
190+
payload: error instanceof Error ? error.message : String(error),
191+
});
192+
throw error;
193+
}
194+
}
195+
152196
return {
153197
workspaces,
154198
activeWorkspace,
@@ -158,6 +202,7 @@ export function useWorkspaces(options: UseWorkspacesOptions = {}) {
158202
connectWorkspace,
159203
markWorkspaceConnected,
160204
updateWorkspaceSettings,
205+
removeWorkspace,
161206
hasLoaded,
162207
refreshWorkspaces,
163208
};

src/services/tauri.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ export async function updateWorkspaceSettings(
2929
return invoke<WorkspaceInfo>("update_workspace_settings", { id, settings });
3030
}
3131

32+
export async function removeWorkspace(id: string): Promise<void> {
33+
return invoke("remove_workspace", { id });
34+
}
35+
3236
export async function connectWorkspace(id: string): Promise<void> {
3337
return invoke("connect_workspace", { id });
3438
}

src/styles/messages.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@
258258
font-family: "SFMono-Regular", "Menlo", "Monaco", monospace;
259259
}
260260

261+
.message .markdown :not(pre) > code {
262+
color: #b08cff;
263+
}
264+
261265
.markdown ul,
262266
.markdown ol {
263267
padding-left: 14px;

0 commit comments

Comments
 (0)