diff --git a/packages/app/src/components/dialog-confirm-delete.tsx b/packages/app/src/components/dialog-confirm-delete.tsx new file mode 100644 index 00000000000..df8e5e30237 --- /dev/null +++ b/packages/app/src/components/dialog-confirm-delete.tsx @@ -0,0 +1,40 @@ +import { Button } from "@opencode-ai/ui/button" +import { useDialog } from "@opencode-ai/ui/context/dialog" +import { Dialog } from "@opencode-ai/ui/dialog" + +interface DialogConfirmDeleteProps { + title: string + description?: string + onConfirm: () => void | Promise +} + +export function DialogConfirmDelete(props: DialogConfirmDeleteProps) { + const dialog = useDialog() + + async function handleConfirm() { + await props.onConfirm() + dialog.close() + } + + return ( + +
+ {props.description &&

{props.description}

} +
+ + +
+
+
+ ) +} diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx index 7e4ade52339..5968fbd935f 100644 --- a/packages/app/src/components/session/session-header.tsx +++ b/packages/app/src/components/session/session-header.tsx @@ -1,4 +1,4 @@ -import { createEffect, createMemo, createResource, Show } from "solid-js" +import { createEffect, createMemo, createResource, createSignal, Show } from "solid-js" import { A, useNavigate, useParams } from "@solidjs/router" import { useLayout } from "@/context/layout" import { useCommand } from "@/context/command" @@ -6,6 +6,7 @@ import { useServer } from "@/context/server" import { useDialog } from "@opencode-ai/ui/context/dialog" import { useSync } from "@/context/sync" import { useGlobalSDK } from "@/context/global-sdk" +import { useSDK } from "@/context/sdk" import { getFilename } from "@opencode-ai/util/path" import { base64Decode, base64Encode } from "@opencode-ai/util/encode" import { iife } from "@opencode-ai/util/iife" @@ -17,12 +18,15 @@ import { Select } from "@opencode-ai/ui/select" import { Popover } from "@opencode-ai/ui/popover" import { TextField } from "@opencode-ai/ui/text-field" import { DialogSelectServer } from "@/components/dialog-select-server" +import { DialogConfirmDelete } from "@/components/dialog-confirm-delete" import { SessionLspIndicator } from "@/components/session-lsp-indicator" import { SessionMcpIndicator } from "@/components/session-mcp-indicator" +import { showToast } from "@opencode-ai/ui/toast" import type { Session } from "@opencode-ai/sdk/v2/client" export function SessionHeader() { const globalSDK = useGlobalSDK() + const sdk = useSDK() const layout = useLayout() const params = useParams() const navigate = useNavigate() @@ -37,6 +41,8 @@ export function SessionHeader() { const currentSession = createMemo(() => sessions().find((s) => s.id === params.id)) const shareEnabled = createMemo(() => sync.data.config.share !== "disabled") + const [deleting, setDeleting] = createSignal(false) + function navigateToProject(directory: string) { navigate(`/${base64Encode(directory)}`) } @@ -46,6 +52,34 @@ export function SessionHeader() { navigate(`/${params.dir}/session/${session.id}`) } + function deleteCurrentSession() { + const session = currentSession() + if (!session || deleting()) return + + dialog.show(() => ( + { + setDeleting(true) + try { + await sdk.client.session.delete({ + sessionID: session.id, + directory: projectDirectory(), + }) + showToast({ title: "Session deleted" }) + navigate(`/${params.dir}/session`) + } catch (e) { + console.error("Failed to delete session", e) + showToast({ title: "Failed to delete session", description: String(e) }) + } finally { + setDeleting(false) + } + }} + /> + )) + } + return (