import { Check, Copy, FileDiff, LoaderCircle, TriangleAlert } from "lucide-react"; import { useId, useState } from "react"; import { Button } from "@/openpress/ui/button"; import { cn } from "@/openpress/core/cn"; import { WorkbenchDialog, WorkbenchDialogAction, WorkbenchDialogBody, WorkbenchDialogStrong, WorkbenchDialogText, } from "../dialog"; import { TOOLBAR_ACTION_CLASS, TOOLBAR_ACTION_LABEL_CLASS } from "../toolbarClasses"; import type { ChangePreview } from "./changePreviewModel"; import type { ChangePreviewStatus } from "./useChangePreview"; const CHANGE_BADGE_CLASS = [ "pointer-events-none absolute right-[4px] top-[4px] grid min-h-[14px] min-w-[14px] place-items-center rounded-full", "bg-[var(--op-workspace-accent)] px-[3px] text-[8px] font-black leading-none text-white", "shadow-[0_0_0_1px_var(--op-workspace-surface)]", ].join(" "); const REFRESH_PROPOSAL_PROMPT = [ "請使用 openpress-collaborate 的 Refresh From Feedback 流程。", "讀取目前 .openpress/review/current.json 與最新文件來源,將現有 feedback 視為輸入,重新評估完整改動,", "並以目前可唯一匹配的 before/after 取代整份 Proposal。不要直接修改文件,也不要複製舊 feedback。", ].join(""); const PROMPT_ROW_CLASS = [ "flex min-w-0 items-center gap-2 rounded-[var(--op-workspace-radius-sm)] border border-[var(--op-workspace-border-muted)]", "bg-[var(--op-workspace-surface-muted)] px-2 py-1.5", ].join(" "); const PROMPT_PREVIEW_CLASS = [ "min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap font-mono text-[10px] leading-5", "text-[var(--op-workspace-text-muted)]", ].join(" "); const PROMPT_COPY_CLASS = [ "inline-flex h-7 shrink-0 cursor-pointer items-center gap-1.5 rounded-[var(--op-workspace-radius-sm)] border", "border-[var(--op-workspace-border)] bg-transparent px-2 text-[10px] font-semibold text-[var(--op-workspace-text-soft)]", "hover:border-[var(--op-workspace-accent-border)] hover:text-[var(--op-workspace-accent)] [&_svg]:h-3 [&_svg]:w-3", ].join(" "); const ATTENTION_ERROR_CLASS = "text-[var(--op-workspace-danger)]"; type PromptCopyStatus = "idle" | "copied" | "failed"; type ProposalClearStatus = "idle" | "clearing" | "failed"; export function ChangePreviewControl({ workspaceMode, preview, status, error, active, onActiveChange, onRefresh, onClear, }: { workspaceMode: boolean; preview: ChangePreview | null; status: ChangePreviewStatus; error: string; active: boolean; onActiveChange: (active: boolean) => void; onRefresh: () => Promise; onClear: () => Promise; }) { const attentionTitleId = useId(); const [attentionOpen, setAttentionOpen] = useState(false); const [copyStatus, setCopyStatus] = useState("idle"); const [clearStatus, setClearStatus] = useState("idle"); if (!workspaceMode) return null; const proposalCount = preview?.proposals.length ?? 0; const exact = preview?.proposals.every((proposal) => proposal.matches === 1) ?? false; const reviewReady = Boolean(preview?.document && exact); const issue = error || preview?.renderError || (!exact ? "Refresh the proposal before reviewing it." : ""); const loading = status === "idle" || status === "loading"; const failed = status === "failed"; const empty = status === "empty"; const needsAttention = !loading && !failed && !empty && Boolean(issue); const expanded = active || loading || failed || needsAttention; const label = loading ? preview ? "更新 Proposal" : "讀取 Proposal" : failed ? "Proposal 錯誤" : empty ? "尚無 Proposal" : needsAttention ? "Proposal 需更新" : "Changes"; const title = loading ? preview ? "正在更新 Change Preview" : "正在讀取 Change Preview" : failed ? `Change Preview 無法讀取:${issue || "未知錯誤"}(點擊重試)` : empty ? "尚無 Proposal。Agent 寫入後可點此重新讀取" : issue ? `Change preview needs attention: ${issue}` : active ? "Close rendered change preview" : `Compare ${proposalCount} proposed changes on the document`; const Icon = loading ? LoaderCircle : failed || needsAttention ? TriangleAlert : FileDiff; return ( <> {attentionOpen ? ( setAttentionOpen(false)} footer={( { setClearStatus("clearing"); try { await onClear(); setAttentionOpen(false); } catch { setClearStatus("failed"); } }} > {clearStatus === "clearing" ? "清除中…" : "清除 Proposal"} )} > Proposal 的原始文字已經和目前文件不同。請交給 Agent 重建,或清除這批 Proposal。
請使用 openpress-collaborate 的 Refresh From Feedback…
系統訊息:{" "}{issue} {clearStatus === "failed" ? ( 無法清除 Proposal,請稍後再試。 ) : null}
) : null} ); }