murashit_codex-panel/src/features/turn-diff/render.dom.tsx
2026-07-01 06:43:14 +09:00

87 lines
2.6 KiB
TypeScript

import type { ComponentChild as UiNode } from "preact";
import { shortThreadId } from "../../domain/threads/id";
import { renderUiRoot } from "../../shared/dom/preact-root.dom";
import { IconButton } from "../../shared/obsidian/components.obsidian";
import { UnifiedDiffView } from "../../shared/ui/diff-view";
import type { PersistedTurnDiffViewState, TurnDiffViewState } from "./model";
export interface TurnDiffViewActions {
copyDiff?: () => void;
}
export function renderTurnDiffView(
parent: HTMLElement,
state: TurnDiffViewState | null,
actions: TurnDiffViewActions = {},
metadata: PersistedTurnDiffViewState | null = null,
): void {
parent.addClass("codex-panel-turn-diff");
renderUiRoot(parent, <TurnDiffView state={state} actions={actions} metadata={metadata} />);
}
function TurnDiffView({
state,
actions,
metadata,
}: {
state: TurnDiffViewState | null;
actions: TurnDiffViewActions;
metadata: PersistedTurnDiffViewState | null;
}): UiNode {
if (!state) {
if (metadata) {
return (
<>
<TurnDiffHeader state={metadata} copyDiff={null} />
<div className="codex-panel-turn-diff__empty">Turn diff is no longer available.</div>
</>
);
}
return <div className="codex-panel-turn-diff__empty">No turn diff selected.</div>;
}
return (
<>
<TurnDiffHeader state={state} copyDiff={actions.copyDiff ?? null} />
{state.files.length > 0 ? <ChangedFiles files={state.files} /> : null}
<UnifiedDiffView diff={state.diff} className="codex-panel-turn-diff__diff" />
</>
);
}
function TurnDiffHeader({
state,
copyDiff,
}: {
state: PersistedTurnDiffViewState;
copyDiff: TurnDiffViewActions["copyDiff"] | null;
}): UiNode {
return (
<div className="codex-panel-turn-diff__header">
<div className="codex-panel-turn-diff__title-block">
<div className="codex-panel-turn-diff__title">Turn diff</div>
<div className="codex-panel-turn-diff__meta">
{shortThreadId(state.threadId)} / {shortThreadId(state.turnId)} ·{" "}
{state.files.length === 1 ? "Edited 1 file" : `Edited ${String(state.files.length)} files`}
</div>
</div>
{copyDiff ? (
<IconButton icon="copy" label="Copy diff" className="clickable-icon codex-panel-turn-diff__copy" onClick={copyDiff} />
) : null}
</div>
);
}
function ChangedFiles({ files }: { files: string[] }): UiNode {
return (
<details className="codex-panel-turn-diff__files">
<summary tabIndex={-1}>Changed files</summary>
<ul>
{files.map((file) => (
<li key={file}>{file}</li>
))}
</ul>
</details>
);
}