import { TextAttributes } from "@opentui/core" import { useKeyboard } from "@opentui/solid" import type { VcsFileStatus } from "@opencode-ai/sdk/v2" import { createMemo, For } from "solid-js" import { createStore } from "solid-js/store" import { Locale } from "../util/locale" import { useTheme } from "../context/theme" import { useTuiConfig } from "../config" import { useDialog, type DialogContext } from "../ui/dialog" import { getScrollAcceleration } from "../util/scroll" const options = ["no", "yes"] as const export type WorkspaceFileChangesChoice = (typeof options)[number] function statusLabel(status: VcsFileStatus["status"]) { if (status === "added") return "A" if (status === "deleted") return "D" return "M" } function changeCountWidth(file: VcsFileStatus) { // The "plus 2" is for spaces return `${file.additions ? `+${file.additions}` : ""}${file.deletions ? ` -${file.deletions}` : ""}`.length + 2 } export function DialogWorkspaceFileChanges(props: { files: VcsFileStatus[] onSelect: (choice: WorkspaceFileChangesChoice) => void title?: string message?: string }) { const dialog = useDialog() const { theme } = useTheme() const tuiConfig = useTuiConfig() const scrollAcceleration = createMemo(() => getScrollAcceleration(tuiConfig)) const [store, setStore] = createStore({ active: "yes" as WorkspaceFileChangesChoice }) const height = createMemo(() => Math.min(props.files.length, 8)) const fileNameWidth = createMemo(() => 48 - Math.max(Math.max(7, ...props.files.map(changeCountWidth)) - 7, 0)) function confirm() { props.onSelect(store.active) dialog.clear() } useKeyboard((evt) => { if (evt.name === "return") { evt.preventDefault() evt.stopPropagation() confirm() return } if (evt.name === "left") { evt.preventDefault() evt.stopPropagation() const index = options.indexOf(store.active) setStore("active", options[Math.max(index - 1, 0)]) return } if (evt.name === "right") { evt.preventDefault() evt.stopPropagation() const index = options.indexOf(store.active) setStore("active", options[Math.min(index + 1, options.length - 1)]) } }) return ( {props.title ?? "File Changes Found"} dialog.clear()}> esc {props.message ?? "Do you want to move these changes with the session?"} {(item) => ( {statusLabel(item.status)} {Locale.truncateLeft(item.file, fileNameWidth())} {" "} {item.additions ? +{item.additions} : null} {item.deletions ? -{item.deletions} : null} )} {(item) => ( { setStore("active", item) props.onSelect(item) dialog.clear() }} > {item} )} ) } DialogWorkspaceFileChanges.show = ( dialog: DialogContext, files: VcsFileStatus[], options?: { title?: string; message?: string }, ) => { return new Promise((resolve) => { dialog.replace( () => , () => resolve(undefined), ) }) }