(props: { api: TuiPluginApi })
| 89 | } |
| 90 | |
| 91 | function DiffViewer(props: { api: TuiPluginApi }) { |
| 92 | const dimensions = useTerminalDimensions() |
| 93 | const themeState = useTheme() |
| 94 | const theme = () => props.api.theme.current |
| 95 | const params = () => |
| 96 | ("params" in props.api.route.current ? props.api.route.current.params : undefined) as |
| 97 | | { |
| 98 | mode?: DiffMode |
| 99 | sessionID?: string |
| 100 | messageID?: string |
| 101 | returnRoute?: TuiRouteCurrent |
| 102 | } |
| 103 | | undefined |
| 104 | const mode = () => params()?.mode ?? "git" |
| 105 | const diffInput = createMemo(() => { |
| 106 | const sessionID = params()?.sessionID |
| 107 | return { |
| 108 | mode: mode(), |
| 109 | sessionID, |
| 110 | messageID: params()?.messageID, |
| 111 | directory: sessionID ? props.api.state.session.get(sessionID)?.directory : undefined, |
| 112 | } |
| 113 | }) |
| 114 | const [diff] = createResource(diffInput, async (input) => { |
| 115 | if (input.mode === "last-turn") { |
| 116 | const sessionID = input.sessionID |
| 117 | if (!sessionID) return [] |
| 118 | const result = await props.api.client.session.diff( |
| 119 | { sessionID, messageID: input.messageID }, |
| 120 | { throwOnError: true }, |
| 121 | ) |
| 122 | return normalizeDiffs(result.data ?? []) |
| 123 | } |
| 124 | |
| 125 | const result = await props.api.client.vcs.diff( |
| 126 | { directory: input.directory, mode: input.mode, context: VCS_DIFF_CONTEXT_LINES }, |
| 127 | { throwOnError: true }, |
| 128 | ) |
| 129 | return normalizeDiffs(result.data ?? []) |
| 130 | }) |
| 131 | const files = createMemo(() => diff() ?? []) |
| 132 | const [focus, setFocus] = createSignal<DiffViewerFocus>("patches") |
| 133 | const [fileTreeEnabled, setFileTreeEnabled] = createSignal( |
| 134 | props.api.kv.get<boolean>(KV_SHOW_FILE_TREE, true) !== false, |
| 135 | ) |
| 136 | const showFileTree = createMemo(() => showDiffViewerFileTree(fileTreeEnabled(), files().length)) |
| 137 | const [singlePatch, setSinglePatch] = createSignal(props.api.kv.get<boolean>(KV_SINGLE_PATCH, false) === true) |
| 138 | const patchPaneWidth = createMemo(() => dimensions().width - (showFileTree() ? 33 : 0) - 4) |
| 139 | const patchLeftBorder = createMemo<BorderSides[]>(() => (showFileTree() ? ["left"] : [])) |
| 140 | const splitAvailable = createMemo(() => patchPaneWidth() >= MIN_SPLIT_WIDTH) |
| 141 | const defaultView = createMemo(() => { |
| 142 | if (props.api.tuiConfig.diff_style === "stacked") return "unified" |
| 143 | return splitAvailable() ? "split" : "unified" |
| 144 | }) |
| 145 | const [viewOverride, setViewOverride] = createSignal<DiffView | undefined>(storedView(props.api.kv.get(KV_VIEW))) |
| 146 | const view = createMemo(() => (splitAvailable() ? (viewOverride() ?? defaultView()) : "unified")) |
| 147 | const fileTree = createMemo(() => buildFileTree(files())) |
| 148 | const [expandedFileNodes, setExpandedFileNodes] = createSignal<ReadonlySet<number>>(new Set()) |
nothing calls this directly
no test coverage detected