Skip to content

Commit e133653

Browse files
jonathanlabclaude
andauthored
feat: Add Developer menu with clear storage option (#203)
Co-authored-by: Claude <[email protected]>
1 parent 6adfe48 commit e133653

File tree

6 files changed

+55
-19
lines changed

6 files changed

+55
-19
lines changed

apps/array/src/main/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,18 @@ function createWindow(): void {
139139
mainWindow?.webContents.send("new-task");
140140
},
141141
},
142+
{ type: "separator" },
143+
{
144+
label: "Developer",
145+
submenu: [
146+
{
147+
label: "Clear application storage",
148+
click: () => {
149+
mainWindow?.webContents.send("clear-storage");
150+
},
151+
},
152+
],
153+
},
142154
],
143155
},
144156
{

apps/array/src/main/preload.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,8 @@ contextBridge.exposeInMainWorld("electronAPI", {
310310
createVoidIpcListener("new-task", listener),
311311
onResetLayout: (listener: () => void): (() => void) =>
312312
createVoidIpcListener("reset-layout", listener),
313+
onClearStorage: (listener: () => void): (() => void) =>
314+
createVoidIpcListener("clear-storage", listener),
313315
getAppVersion: (): Promise<string> => ipcRenderer.invoke("app:get-version"),
314316
onUpdateReady: (listener: () => void): (() => void) =>
315317
createVoidIpcListener("updates:ready", listener),

apps/array/src/renderer/components/MainLayout.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { TaskInput } from "@features/task-detail/components/TaskInput";
1616
import { TaskList } from "@features/task-list/components/TaskList";
1717
import { useIntegrations } from "@hooks/useIntegrations";
1818
import { Box, Flex } from "@radix-ui/themes";
19+
import { clearApplicationStorage } from "@renderer/lib/clearStorage";
1920
import type { Task } from "@shared/types";
2021
import { useNavigationStore } from "@stores/navigationStore";
2122
import { useCallback, useEffect, useState } from "react";
@@ -50,6 +51,10 @@ export function MainLayout() {
5051
window.location.reload();
5152
}, [clearAllLayouts]);
5253

54+
const handleClearStorage = useCallback(() => {
55+
clearApplicationStorage();
56+
}, []);
57+
5358
useHotkeys("mod+k", () => setCommandMenuOpen((prev) => !prev), {
5459
enabled: !commandMenuOpen,
5560
});
@@ -79,12 +84,22 @@ export function MainLayout() {
7984
handleResetLayout();
8085
});
8186

87+
const unsubscribeClearStorage = window.electronAPI?.onClearStorage(() => {
88+
handleClearStorage();
89+
});
90+
8291
return () => {
8392
unsubscribeSettings?.();
8493
unsubscribeNewTask?.();
8594
unsubscribeResetLayout?.();
95+
unsubscribeClearStorage?.();
8696
};
87-
}, [handleOpenSettings, handleFocusTaskMode, handleResetLayout]);
97+
}, [
98+
handleOpenSettings,
99+
handleFocusTaskMode,
100+
handleResetLayout,
101+
handleClearStorage,
102+
]);
88103

89104
useEffect(() => {
90105
const handleMouseButton = (event: MouseEvent) => {

apps/array/src/renderer/features/settings/components/SettingsView.tsx

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
Switch,
2020
Text,
2121
} from "@radix-ui/themes";
22+
import { clearApplicationStorage } from "@renderer/lib/clearStorage";
2223
import { logger } from "@renderer/lib/logger";
2324
import type { CloudRegion } from "@shared/types/oauth";
2425
import { useSettingsStore as useTerminalLayoutStore } from "@stores/settingsStore";
@@ -302,24 +303,7 @@ export function SettingsView() {
302303
variant="soft"
303304
color="red"
304305
size="1"
305-
onClick={() => {
306-
const confirmed = window.confirm(
307-
"Are you sure you want to clear all application storage?\n\nThis will remove:\n• All registered folders\n• UI state (sidebar preferences, etc.)\n• Task directory mappings\n\nYour files will not be deleted from your computer.",
308-
);
309-
310-
if (confirmed) {
311-
window.electronAPI.folders
312-
.clearAllData()
313-
.then(() => {
314-
localStorage.clear();
315-
window.location.reload();
316-
})
317-
.catch((error: unknown) => {
318-
log.error("Failed to clear storage:", error);
319-
alert("Failed to clear storage. Please try again.");
320-
});
321-
}
322-
}}
306+
onClick={clearApplicationStorage}
323307
style={{ alignSelf: "flex-start" }}
324308
>
325309
Clear all data
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { logger } from "./logger";
2+
3+
const log = logger.scope("clear-storage");
4+
5+
export function clearApplicationStorage(): void {
6+
const confirmed = window.confirm(
7+
"Are you sure you want to clear all application storage?\n\nThis will remove:\n• All registered folders\n• UI state (sidebar preferences, etc.)\n• Task directory mappings\n\nYour files will not be deleted from your computer.",
8+
);
9+
10+
if (confirmed) {
11+
window.electronAPI.folders
12+
.clearAllData()
13+
.then(() => {
14+
localStorage.clear();
15+
window.location.reload();
16+
})
17+
.catch((error: unknown) => {
18+
log.error("Failed to clear storage:", error);
19+
alert("Failed to clear storage. Please try again.");
20+
});
21+
}
22+
}

apps/array/src/renderer/types/electron.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ declare global {
221221
onOpenSettings: (listener: () => void) => () => void;
222222
onNewTask: (listener: () => void) => () => void;
223223
onResetLayout: (listener: () => void) => () => void;
224+
onClearStorage: (listener: () => void) => () => void;
224225
getAppVersion: () => Promise<string>;
225226
onUpdateReady: (listener: () => void) => () => void;
226227
installUpdate: () => Promise<{ installed: boolean }>;

0 commit comments

Comments
 (0)