Provide a button to clear session data (#231)

Fixes #214

---------

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
This commit is contained in:
Will Chen
2025-05-22 16:36:45 -07:00
committed by GitHub
parent 830e4ece15
commit e119a670ec
5 changed files with 60 additions and 1 deletions

View File

@@ -5,6 +5,7 @@ import {
previewPanelKeyAtom, previewPanelKeyAtom,
selectedAppIdAtom, selectedAppIdAtom,
} from "../../atoms/appAtoms"; } from "../../atoms/appAtoms";
import { IpcClient } from "@/ipc/ipc_client";
import { CodeView } from "./CodeView"; import { CodeView } from "./CodeView";
import { PreviewIframe } from "./PreviewIframe"; import { PreviewIframe } from "./PreviewIframe";
@@ -17,6 +18,7 @@ import {
MoreVertical, MoreVertical,
Cog, Cog,
Power, Power,
Trash2,
} from "lucide-react"; } from "lucide-react";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { useEffect, useRef, useState, useCallback } from "react"; import { useEffect, useRef, useState, useCallback } from "react";
@@ -29,6 +31,8 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { showError, showSuccess } from "@/lib/toast";
import { useMutation } from "@tanstack/react-query";
type PreviewMode = "preview" | "code"; type PreviewMode = "preview" | "code";
@@ -37,6 +41,7 @@ interface PreviewHeaderProps {
setPreviewMode: (mode: PreviewMode) => void; setPreviewMode: (mode: PreviewMode) => void;
onRestart: () => void; onRestart: () => void;
onCleanRestart: () => void; onCleanRestart: () => void;
onClearSessionData: () => void;
} }
interface ConsoleHeaderProps { interface ConsoleHeaderProps {
@@ -51,6 +56,7 @@ const PreviewHeader = ({
setPreviewMode, setPreviewMode,
onRestart, onRestart,
onCleanRestart, onCleanRestart,
onClearSessionData,
}: PreviewHeaderProps) => ( }: PreviewHeaderProps) => (
<div className="flex items-center justify-between px-4 py-2 border-b border-border"> <div className="flex items-center justify-between px-4 py-2 border-b border-border">
<div className="relative flex space-x-2 bg-[var(--background-darkest)] rounded-md p-0.5"> <div className="relative flex space-x-2 bg-[var(--background-darkest)] rounded-md p-0.5">
@@ -111,6 +117,15 @@ const PreviewHeader = ({
</span> </span>
</div> </div>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={onClearSessionData}>
<Trash2 size={16} />
<div className="flex flex-col">
<span>Clear Preview Data</span>
<span className="text-xs text-muted-foreground">
Clears cookies and local storage for the app preview
</span>
</div>
</DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
</div> </div>
@@ -146,7 +161,8 @@ export function PreviewPanel() {
const [previewMode, setPreviewMode] = useAtom(previewModeAtom); const [previewMode, setPreviewMode] = useAtom(previewModeAtom);
const selectedAppId = useAtomValue(selectedAppIdAtom); const selectedAppId = useAtomValue(selectedAppIdAtom);
const [isConsoleOpen, setIsConsoleOpen] = useState(false); const [isConsoleOpen, setIsConsoleOpen] = useState(false);
const { runApp, stopApp, restartApp, loading, app } = useRunApp(); const { runApp, stopApp, restartApp, loading, app, refreshAppIframe } =
useRunApp();
const runningAppIdRef = useRef<number | null>(null); const runningAppIdRef = useRef<number | null>(null);
const key = useAtomValue(previewPanelKeyAtom); const key = useAtomValue(previewPanelKeyAtom);
const appOutput = useAtomValue(appOutputAtom); const appOutput = useAtomValue(appOutputAtom);
@@ -163,6 +179,29 @@ export function PreviewPanel() {
restartApp({ removeNodeModules: true }); restartApp({ removeNodeModules: true });
}, [restartApp]); }, [restartApp]);
const useClearSessionData = () => {
return useMutation({
mutationFn: () => {
const ipcClient = IpcClient.getInstance();
return ipcClient.clearSessionData();
},
onSuccess: async () => {
await refreshAppIframe();
showSuccess("Preview data cleared");
// Optionally invalidate relevant queries
},
onError: (error) => {
showError(`Error clearing preview data: ${error}`);
},
});
};
const { mutate: clearSessionData } = useClearSessionData();
const handleClearSessionData = useCallback(() => {
clearSessionData();
}, [selectedAppId, clearSessionData]);
useEffect(() => { useEffect(() => {
const previousAppId = runningAppIdRef.current; const previousAppId = runningAppIdRef.current;
@@ -214,6 +253,7 @@ export function PreviewPanel() {
setPreviewMode={setPreviewMode} setPreviewMode={setPreviewMode}
onRestart={handleRestart} onRestart={handleRestart}
onCleanRestart={handleCleanRestart} onCleanRestart={handleCleanRestart}
onClearSessionData={handleClearSessionData}
/> />
<div className="flex-1 overflow-hidden"> <div className="flex-1 overflow-hidden">
<PanelGroup direction="vertical"> <PanelGroup direction="vertical">

View File

@@ -0,0 +1,12 @@
import { ipcMain, session } from "electron";
export const registerSessionHandlers = () => {
ipcMain.handle("clear-session-data", async (_event) => {
const defaultAppSession = session.defaultSession;
await defaultAppSession.clearStorageData({
storages: ["cookies", "localstorage"],
});
console.info(`[IPC] All session data cleared for default session`);
});
};

View File

@@ -821,4 +821,8 @@ export class IpcClient {
public async renameBranch(params: RenameBranchParams): Promise<void> { public async renameBranch(params: RenameBranchParams): Promise<void> {
await this.ipcRenderer.invoke("rename-branch", params); await this.ipcRenderer.invoke("rename-branch", params);
} }
async clearSessionData(): Promise<void> {
return this.ipcRenderer.invoke("clear-session-data");
}
} }

View File

@@ -17,6 +17,7 @@ import { registerVersionHandlers } from "./handlers/version_handlers";
import { registerLanguageModelHandlers } from "./handlers/language_model_handlers"; import { registerLanguageModelHandlers } from "./handlers/language_model_handlers";
import { registerReleaseNoteHandlers } from "./handlers/release_note_handlers"; import { registerReleaseNoteHandlers } from "./handlers/release_note_handlers";
import { registerImportHandlers } from "./handlers/import_handlers"; import { registerImportHandlers } from "./handlers/import_handlers";
import { registerSessionHandlers } from "./handlers/session_handlers";
export function registerIpcHandlers() { export function registerIpcHandlers() {
// Register all IPC handlers by category // Register all IPC handlers by category
@@ -39,4 +40,5 @@ export function registerIpcHandlers() {
registerLanguageModelHandlers(); registerLanguageModelHandlers();
registerReleaseNoteHandlers(); registerReleaseNoteHandlers();
registerImportHandlers(); registerImportHandlers();
registerSessionHandlers();
} }

View File

@@ -74,6 +74,7 @@ const validInvokeChannels = [
"select-app-folder", "select-app-folder",
"check-app-name", "check-app-name",
"rename-branch", "rename-branch",
"clear-session-data",
] as const; ] as const;
// Add valid receive channels // Add valid receive channels