chore: cleanup
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { createEffect, createSignal, For, Match, Show, Switch, type JSX } from "solid-js"
|
import { createEffect, createSignal, For, Match, on, onCleanup, Show, Switch, type JSX } from "solid-js"
|
||||||
import { Collapsible } from "./collapsible"
|
import { Collapsible } from "./collapsible"
|
||||||
import type { IconProps } from "./icon"
|
import type { IconProps } from "./icon"
|
||||||
import { TextShimmer } from "./text-shimmer"
|
import { TextShimmer } from "./text-shimmer"
|
||||||
@@ -27,18 +27,52 @@ export interface BasicToolProps {
|
|||||||
hideDetails?: boolean
|
hideDetails?: boolean
|
||||||
defaultOpen?: boolean
|
defaultOpen?: boolean
|
||||||
forceOpen?: boolean
|
forceOpen?: boolean
|
||||||
|
defer?: boolean
|
||||||
locked?: boolean
|
locked?: boolean
|
||||||
onSubtitleClick?: () => void
|
onSubtitleClick?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BasicTool(props: BasicToolProps) {
|
export function BasicTool(props: BasicToolProps) {
|
||||||
const [open, setOpen] = createSignal(props.defaultOpen ?? false)
|
const [open, setOpen] = createSignal(props.defaultOpen ?? false)
|
||||||
|
const [ready, setReady] = createSignal(open())
|
||||||
const pending = () => props.status === "pending" || props.status === "running"
|
const pending = () => props.status === "pending" || props.status === "running"
|
||||||
|
|
||||||
|
let frame: number | undefined
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
if (frame === undefined) return
|
||||||
|
cancelAnimationFrame(frame)
|
||||||
|
frame = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
onCleanup(cancel)
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (props.forceOpen) setOpen(true)
|
if (props.forceOpen) setOpen(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
createEffect(
|
||||||
|
on(
|
||||||
|
open,
|
||||||
|
(value) => {
|
||||||
|
if (!props.defer) return
|
||||||
|
if (!value) {
|
||||||
|
cancel()
|
||||||
|
setReady(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel()
|
||||||
|
frame = requestAnimationFrame(() => {
|
||||||
|
frame = undefined
|
||||||
|
if (!open()) return
|
||||||
|
setReady(true)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ defer: true },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
const handleOpenChange = (value: boolean) => {
|
const handleOpenChange = (value: boolean) => {
|
||||||
if (pending()) return
|
if (pending()) return
|
||||||
if (props.locked && !value) return
|
if (props.locked && !value) return
|
||||||
@@ -114,7 +148,9 @@ export function BasicTool(props: BasicToolProps) {
|
|||||||
</div>
|
</div>
|
||||||
</Collapsible.Trigger>
|
</Collapsible.Trigger>
|
||||||
<Show when={props.children && !props.hideDetails}>
|
<Show when={props.children && !props.hideDetails}>
|
||||||
<Collapsible.Content>{props.children}</Collapsible.Content>
|
<Collapsible.Content>
|
||||||
|
<Show when={!props.defer || ready()}>{props.children}</Show>
|
||||||
|
</Collapsible.Content>
|
||||||
</Show>
|
</Show>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -326,8 +326,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-slot="collapsible-content"]:has([data-component="edit-content"]),
|
[data-slot="collapsible-content"]:has([data-component="edit-content"]),
|
||||||
[data-slot="collapsible-content"]:has([data-component="write-content"]),
|
[data-slot="collapsible-content"]:has([data-component="write-content"]) {
|
||||||
[data-slot="collapsible-content"]:has([data-component="apply-patch-files"]) {
|
|
||||||
border: 1px solid var(--border-weak-base);
|
border: 1px solid var(--border-weak-base);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
@@ -1219,21 +1218,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="apply-patch-files"] {
|
[data-component="accordion"][data-scope="apply-patch"] {
|
||||||
display: flex;
|
[data-slot="apply-patch-trigger-content"] {
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="apply-patch-file"] {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
[data-slot="apply-patch-file-header"] {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
justify-content: space-between;
|
||||||
padding: 8px 12px;
|
width: 100%;
|
||||||
background-color: transparent;
|
min-width: 0;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="apply-patch-file-path"] {
|
||||||
|
font-family: var(--font-family-mono);
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
color: var(--text-weak);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="apply-patch-trigger-actions"] {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-slot="apply-patch-file-action"] {
|
[data-slot="apply-patch-file-action"] {
|
||||||
@@ -1257,26 +1266,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-slot="apply-patch-file-path"] {
|
|
||||||
font-family: var(--font-family-mono);
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
color: var(--text-weak);
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-slot="apply-patch-deletion-count"] {
|
[data-slot="apply-patch-deletion-count"] {
|
||||||
font-family: var(--font-family-mono);
|
font-family: var(--font-family-mono);
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
color: var(--text-critical-base);
|
color: var(--text-critical-base);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="apply-patch-file"] + [data-component="apply-patch-file"] {
|
[data-slot="apply-patch-file-chevron"] {
|
||||||
border-top: 1px solid var(--border-weaker-base);
|
display: inline-flex;
|
||||||
|
color: var(--icon-weaker);
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
transition: transform 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="accordion-item"][data-expanded] [data-slot="apply-patch-file-chevron"] {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="apply-patch-file-diff"] {
|
[data-component="apply-patch-file-diff"] {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import { useDialog } from "../context/dialog"
|
|||||||
import { useI18n } from "../context/i18n"
|
import { useI18n } from "../context/i18n"
|
||||||
import { BasicTool } from "./basic-tool"
|
import { BasicTool } from "./basic-tool"
|
||||||
import { GenericTool } from "./basic-tool"
|
import { GenericTool } from "./basic-tool"
|
||||||
|
import { Accordion } from "./accordion"
|
||||||
import { Button } from "./button"
|
import { Button } from "./button"
|
||||||
import { Card } from "./card"
|
import { Card } from "./card"
|
||||||
import { Collapsible } from "./collapsible"
|
import { Collapsible } from "./collapsible"
|
||||||
@@ -1482,6 +1483,7 @@ ToolRegistry.register({
|
|||||||
<BasicTool
|
<BasicTool
|
||||||
{...props}
|
{...props}
|
||||||
icon="code-lines"
|
icon="code-lines"
|
||||||
|
defer
|
||||||
trigger={
|
trigger={
|
||||||
<div data-component="edit-trigger">
|
<div data-component="edit-trigger">
|
||||||
<div data-slot="message-part-title-area">
|
<div data-slot="message-part-title-area">
|
||||||
@@ -1542,6 +1544,7 @@ ToolRegistry.register({
|
|||||||
<BasicTool
|
<BasicTool
|
||||||
{...props}
|
{...props}
|
||||||
icon="code-lines"
|
icon="code-lines"
|
||||||
|
defer
|
||||||
trigger={
|
trigger={
|
||||||
<div data-component="write-trigger">
|
<div data-component="write-trigger">
|
||||||
<div data-slot="message-part-title-area">
|
<div data-slot="message-part-title-area">
|
||||||
@@ -1602,6 +1605,16 @@ ToolRegistry.register({
|
|||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
const diffComponent = useDiffComponent()
|
const diffComponent = useDiffComponent()
|
||||||
const files = createMemo(() => (props.metadata.files ?? []) as ApplyPatchFile[])
|
const files = createMemo(() => (props.metadata.files ?? []) as ApplyPatchFile[])
|
||||||
|
const [expanded, setExpanded] = createSignal<string[]>([])
|
||||||
|
let seeded = false
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
const list = files()
|
||||||
|
if (list.length === 0) return
|
||||||
|
if (seeded) return
|
||||||
|
seeded = true
|
||||||
|
setExpanded(list.filter((f) => f.type !== "delete").map((f) => f.filePath))
|
||||||
|
})
|
||||||
|
|
||||||
const subtitle = createMemo(() => {
|
const subtitle = createMemo(() => {
|
||||||
const count = files().length
|
const count = files().length
|
||||||
@@ -1613,60 +1626,89 @@ ToolRegistry.register({
|
|||||||
<BasicTool
|
<BasicTool
|
||||||
{...props}
|
{...props}
|
||||||
icon="code-lines"
|
icon="code-lines"
|
||||||
|
defer
|
||||||
trigger={{
|
trigger={{
|
||||||
title: i18n.t("ui.tool.patch"),
|
title: i18n.t("ui.tool.patch"),
|
||||||
subtitle: subtitle(),
|
subtitle: subtitle(),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Show when={files().length > 0}>
|
<Show when={files().length > 0}>
|
||||||
<div data-component="apply-patch-files">
|
<Accordion
|
||||||
|
multiple
|
||||||
|
data-scope="apply-patch"
|
||||||
|
value={expanded()}
|
||||||
|
onChange={(value) => setExpanded(Array.isArray(value) ? value : value ? [value] : [])}
|
||||||
|
>
|
||||||
<For each={files()}>
|
<For each={files()}>
|
||||||
{(file) => (
|
{(file) => {
|
||||||
<div data-component="apply-patch-file">
|
const active = createMemo(() => expanded().includes(file.filePath))
|
||||||
<div data-slot="apply-patch-file-header">
|
const [visible, setVisible] = createSignal(false)
|
||||||
<Switch>
|
|
||||||
<Match when={file.type === "delete"}>
|
createEffect(() => {
|
||||||
<span data-slot="apply-patch-file-action" data-type="delete">
|
if (!active()) {
|
||||||
{i18n.t("ui.patch.action.deleted")}
|
setVisible(false)
|
||||||
</span>
|
return
|
||||||
</Match>
|
}
|
||||||
<Match when={file.type === "add"}>
|
|
||||||
<span data-slot="apply-patch-file-action" data-type="add">
|
requestAnimationFrame(() => {
|
||||||
{i18n.t("ui.patch.action.created")}
|
if (!active()) return
|
||||||
</span>
|
setVisible(true)
|
||||||
</Match>
|
})
|
||||||
<Match when={file.type === "move"}>
|
})
|
||||||
<span data-slot="apply-patch-file-action" data-type="move">
|
|
||||||
{i18n.t("ui.patch.action.moved")}
|
return (
|
||||||
</span>
|
<Accordion.Item value={file.filePath} data-type={file.type}>
|
||||||
</Match>
|
<Accordion.Header>
|
||||||
<Match when={file.type === "update"}>
|
<Accordion.Trigger>
|
||||||
<span data-slot="apply-patch-file-action" data-type="update">
|
<div data-slot="apply-patch-trigger-content">
|
||||||
{i18n.t("ui.patch.action.patched")}
|
<span data-slot="apply-patch-file-path">{file.relativePath}</span>
|
||||||
</span>
|
<div data-slot="apply-patch-trigger-actions">
|
||||||
</Match>
|
<Switch>
|
||||||
</Switch>
|
<Match when={file.type === "delete"}>
|
||||||
<span data-slot="apply-patch-file-path">{file.relativePath}</span>
|
<span data-slot="apply-patch-file-action" data-type="delete">
|
||||||
<Show when={file.type !== "delete"}>
|
{i18n.t("ui.patch.action.deleted")}
|
||||||
<DiffChanges changes={{ additions: file.additions, deletions: file.deletions }} />
|
</span>
|
||||||
</Show>
|
</Match>
|
||||||
<Show when={file.type === "delete"}>
|
<Match when={file.type === "add"}>
|
||||||
<span data-slot="apply-patch-deletion-count">-{file.deletions}</span>
|
<span data-slot="apply-patch-file-action" data-type="add">
|
||||||
</Show>
|
{i18n.t("ui.patch.action.created")}
|
||||||
</div>
|
</span>
|
||||||
<Show when={file.type !== "delete"}>
|
</Match>
|
||||||
<div data-component="apply-patch-file-diff">
|
<Match when={file.type === "move"}>
|
||||||
<Dynamic
|
<span data-slot="apply-patch-file-action" data-type="move">
|
||||||
component={diffComponent}
|
{i18n.t("ui.patch.action.moved")}
|
||||||
before={{ name: file.filePath, contents: file.before }}
|
</span>
|
||||||
after={{ name: file.filePath, contents: file.after }}
|
</Match>
|
||||||
/>
|
</Switch>
|
||||||
</div>
|
<Show when={file.type !== "delete"}>
|
||||||
</Show>
|
<DiffChanges changes={{ additions: file.additions, deletions: file.deletions }} />
|
||||||
</div>
|
</Show>
|
||||||
)}
|
<Show when={file.type === "delete"}>
|
||||||
|
<span data-slot="apply-patch-deletion-count">-{file.deletions}</span>
|
||||||
|
</Show>
|
||||||
|
<span data-slot="apply-patch-file-chevron">
|
||||||
|
<Icon name="chevron-down" size="small" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Accordion.Trigger>
|
||||||
|
</Accordion.Header>
|
||||||
|
<Accordion.Content>
|
||||||
|
<Show when={visible()}>
|
||||||
|
<div data-component="apply-patch-file-diff">
|
||||||
|
<Dynamic
|
||||||
|
component={diffComponent}
|
||||||
|
before={{ name: file.filePath, contents: file.before }}
|
||||||
|
after={{ name: file.movePath ?? file.filePath, contents: file.after }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</Accordion.Content>
|
||||||
|
</Accordion.Item>
|
||||||
|
)
|
||||||
|
}}
|
||||||
</For>
|
</For>
|
||||||
</div>
|
</Accordion>
|
||||||
</Show>
|
</Show>
|
||||||
</BasicTool>
|
</BasicTool>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -130,19 +130,13 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="session-turn-diff"] {
|
[data-slot="session-turn-diff-trigger"] {
|
||||||
border: 1px solid var(--border-weaker-base);
|
|
||||||
border-radius: var(--radius-md);
|
|
||||||
overflow: clip;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-slot="session-turn-diff-header"] {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 6px 10px;
|
width: 100%;
|
||||||
border-bottom: 1px solid var(--border-weaker-base);
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-slot="session-turn-diff-path"] {
|
[data-slot="session-turn-diff-path"] {
|
||||||
@@ -166,9 +160,36 @@
|
|||||||
font-weight: var(--font-weight-medium);
|
font-weight: var(--font-weight-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-slot="session-turn-diff-meta"] {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="session-turn-diff-chevron"] {
|
||||||
|
display: inline-flex;
|
||||||
|
color: var(--icon-weaker);
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
transition: transform 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="accordion-item"][data-expanded] [data-slot="session-turn-diff-chevron"] {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
[data-slot="session-turn-diff-view"] {
|
[data-slot="session-turn-diff-view"] {
|
||||||
background-color: var(--surface-inset-base);
|
background-color: var(--surface-inset-base);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
max-height: 420px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="session-turn-diff-view"]::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import { useDiffComponent } from "../context/diff"
|
|||||||
|
|
||||||
import { Binary } from "@opencode-ai/util/binary"
|
import { Binary } from "@opencode-ai/util/binary"
|
||||||
import { getDirectory, getFilename } from "@opencode-ai/util/path"
|
import { getDirectory, getFilename } from "@opencode-ai/util/path"
|
||||||
import { createMemo, createSignal, For, ParentProps, Show } from "solid-js"
|
import { createEffect, createMemo, createSignal, For, on, ParentProps, Show } from "solid-js"
|
||||||
import { Dynamic } from "solid-js/web"
|
import { Dynamic } from "solid-js/web"
|
||||||
import { AssistantParts, Message } from "./message-part"
|
import { AssistantParts, Message } from "./message-part"
|
||||||
import { Card } from "./card"
|
import { Card } from "./card"
|
||||||
|
import { Accordion } from "./accordion"
|
||||||
import { Collapsible } from "./collapsible"
|
import { Collapsible } from "./collapsible"
|
||||||
import { DiffChanges } from "./diff-changes"
|
import { DiffChanges } from "./diff-changes"
|
||||||
|
import { Icon } from "./icon"
|
||||||
import { TextShimmer } from "./text-shimmer"
|
import { TextShimmer } from "./text-shimmer"
|
||||||
import { createAutoScroll } from "../hooks"
|
import { createAutoScroll } from "../hooks"
|
||||||
import { useI18n } from "../context/i18n"
|
import { useI18n } from "../context/i18n"
|
||||||
@@ -175,6 +177,17 @@ export function SessionTurn(
|
|||||||
})
|
})
|
||||||
const edited = createMemo(() => diffs().length)
|
const edited = createMemo(() => diffs().length)
|
||||||
const [open, setOpen] = createSignal(false)
|
const [open, setOpen] = createSignal(false)
|
||||||
|
const [expanded, setExpanded] = createSignal<string[]>([])
|
||||||
|
|
||||||
|
createEffect(
|
||||||
|
on(
|
||||||
|
open,
|
||||||
|
(value, prev) => {
|
||||||
|
if (!value && prev) setExpanded([])
|
||||||
|
},
|
||||||
|
{ defer: true },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
const assistantMessages = createMemo(
|
const assistantMessages = createMemo(
|
||||||
() => {
|
() => {
|
||||||
@@ -280,7 +293,7 @@ export function SessionTurn(
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
<Show when={edited() > 0}>
|
<Show when={edited() > 0 && !working()}>
|
||||||
<div data-slot="session-turn-diffs">
|
<div data-slot="session-turn-diffs">
|
||||||
<Collapsible open={open()} onOpenChange={setOpen} variant="ghost">
|
<Collapsible open={open()} onOpenChange={setOpen} variant="ghost">
|
||||||
<Collapsible.Trigger>
|
<Collapsible.Trigger>
|
||||||
@@ -302,30 +315,76 @@ export function SessionTurn(
|
|||||||
<Collapsible.Content>
|
<Collapsible.Content>
|
||||||
<Show when={open()}>
|
<Show when={open()}>
|
||||||
<div data-component="session-turn-diffs-content">
|
<div data-component="session-turn-diffs-content">
|
||||||
<For each={diffs()}>
|
<Accordion
|
||||||
{(diff) => (
|
multiple
|
||||||
<div data-component="session-turn-diff">
|
value={expanded()}
|
||||||
<div data-slot="session-turn-diff-header">
|
onChange={(value) => setExpanded(Array.isArray(value) ? value : value ? [value] : [])}
|
||||||
<span data-slot="session-turn-diff-path">
|
>
|
||||||
<Show when={diff.file.includes("/")}>
|
<For each={diffs()}>
|
||||||
<span data-slot="session-turn-diff-directory">{getDirectory(diff.file)}</span>
|
{(diff) => {
|
||||||
</Show>
|
const active = createMemo(() => expanded().includes(diff.file))
|
||||||
<span data-slot="session-turn-diff-filename">{getFilename(diff.file)}</span>
|
const [visible, setVisible] = createSignal(false)
|
||||||
</span>
|
|
||||||
<span data-slot="session-turn-diff-changes">
|
createEffect(
|
||||||
<DiffChanges changes={diff} />
|
on(
|
||||||
</span>
|
active,
|
||||||
</div>
|
(value) => {
|
||||||
<div data-slot="session-turn-diff-view">
|
if (!value) {
|
||||||
<Dynamic
|
setVisible(false)
|
||||||
component={diffComponent}
|
return
|
||||||
before={{ name: diff.file, contents: diff.before }}
|
}
|
||||||
after={{ name: diff.file, contents: diff.after }}
|
|
||||||
/>
|
requestAnimationFrame(() => {
|
||||||
</div>
|
if (!active()) return
|
||||||
</div>
|
setVisible(true)
|
||||||
)}
|
})
|
||||||
</For>
|
},
|
||||||
|
{ defer: true },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion.Item value={diff.file}>
|
||||||
|
<Accordion.Header>
|
||||||
|
<Accordion.Trigger>
|
||||||
|
<div data-slot="session-turn-diff-trigger">
|
||||||
|
<span data-slot="session-turn-diff-path">
|
||||||
|
<Show when={diff.file.includes("/")}>
|
||||||
|
<span data-slot="session-turn-diff-directory">
|
||||||
|
{getDirectory(diff.file)}
|
||||||
|
</span>
|
||||||
|
</Show>
|
||||||
|
<span data-slot="session-turn-diff-filename">
|
||||||
|
{getFilename(diff.file)}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div data-slot="session-turn-diff-meta">
|
||||||
|
<span data-slot="session-turn-diff-changes">
|
||||||
|
<DiffChanges changes={diff} />
|
||||||
|
</span>
|
||||||
|
<span data-slot="session-turn-diff-chevron">
|
||||||
|
<Icon name="chevron-down" size="small" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Accordion.Trigger>
|
||||||
|
</Accordion.Header>
|
||||||
|
<Accordion.Content>
|
||||||
|
<Show when={visible()}>
|
||||||
|
<div data-slot="session-turn-diff-view" data-scrollable>
|
||||||
|
<Dynamic
|
||||||
|
component={diffComponent}
|
||||||
|
before={{ name: diff.file, contents: diff.before }}
|
||||||
|
after={{ name: diff.file, contents: diff.after }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</Accordion.Content>
|
||||||
|
</Accordion.Item>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</For>
|
||||||
|
</Accordion>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
</Collapsible.Content>
|
</Collapsible.Content>
|
||||||
|
|||||||
Reference in New Issue
Block a user