fix(app): timeline jank
This commit is contained in:
@@ -1091,7 +1091,9 @@ export default function Page() {
|
|||||||
|
|
||||||
const el = scroller
|
const el = scroller
|
||||||
const delta = next - dockHeight
|
const delta = next - dockHeight
|
||||||
const stick = el ? el.scrollHeight - el.clientHeight - el.scrollTop < 10 + Math.max(0, delta) : false
|
const stick = el
|
||||||
|
? !autoScroll.userScrolled() || el.scrollHeight - el.clientHeight - el.scrollTop < 10 + Math.max(0, delta)
|
||||||
|
: false
|
||||||
|
|
||||||
dockHeight = next
|
dockHeight = next
|
||||||
|
|
||||||
|
|||||||
@@ -689,7 +689,9 @@ export function MessageTimeline(props: {
|
|||||||
if (!item || active()) return false
|
if (!item || active()) return false
|
||||||
return messageID > item.id
|
return messageID > item.id
|
||||||
})
|
})
|
||||||
const comments = createMemo(() => messageComments(sync.data.part[messageID] ?? []))
|
const comments = createMemo(() => messageComments(sync.data.part[messageID] ?? []), [], {
|
||||||
|
equals: (a, b) => JSON.stringify(a) === JSON.stringify(b),
|
||||||
|
})
|
||||||
const commentCount = createMemo(() => comments().length)
|
const commentCount = createMemo(() => comments().length)
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
Show,
|
Show,
|
||||||
Switch,
|
Switch,
|
||||||
onCleanup,
|
onCleanup,
|
||||||
|
Index,
|
||||||
type JSX,
|
type JSX,
|
||||||
} from "solid-js"
|
} from "solid-js"
|
||||||
import stripAnsi from "strip-ansi"
|
import stripAnsi from "strip-ansi"
|
||||||
@@ -458,50 +459,67 @@ export function AssistantParts(props: {
|
|||||||
const last = createMemo(() => grouped().at(-1)?.key)
|
const last = createMemo(() => grouped().at(-1)?.key)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<For each={grouped()}>
|
<Index each={grouped()}>
|
||||||
{(entry) => {
|
{(entryAccessor) => {
|
||||||
if (entry.type === "context") {
|
const entryType = createMemo(() => entryAccessor().type)
|
||||||
const parts = createMemo(
|
|
||||||
() =>
|
|
||||||
entry.refs
|
|
||||||
.map((ref) => partByID(list(data.store.part?.[ref.messageID], emptyParts), ref.partID))
|
|
||||||
.filter((part): part is ToolPart => !!part && isContextGroupTool(part)),
|
|
||||||
emptyTools,
|
|
||||||
{ equals: same },
|
|
||||||
)
|
|
||||||
const busy = createMemo(() => props.working && last() === entry.key)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Show when={parts().length > 0}>
|
|
||||||
<ContextToolGroup parts={parts()} busy={busy()} />
|
|
||||||
</Show>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const message = createMemo(() => props.messages.find((item) => item.id === entry.ref.messageID))
|
|
||||||
const part = createMemo(() =>
|
|
||||||
partByID(list(data.store.part?.[entry.ref.messageID], emptyParts), entry.ref.partID),
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Show when={message()}>
|
<Switch>
|
||||||
{(message) => (
|
<Match when={entryType() === "context"}>
|
||||||
<Show when={part()}>
|
{(() => {
|
||||||
{(part) => (
|
const parts = createMemo(
|
||||||
<Part
|
() => {
|
||||||
part={part()}
|
const entry = entryAccessor() as { type: "context"; refs: PartRef[] }
|
||||||
message={message()}
|
return entry.refs
|
||||||
showAssistantCopyPartID={props.showAssistantCopyPartID}
|
.map((ref) => partByID(list(data.store.part?.[ref.messageID], emptyParts), ref.partID))
|
||||||
turnDurationMs={props.turnDurationMs}
|
.filter((part): part is ToolPart => !!part && isContextGroupTool(part))
|
||||||
defaultOpen={partDefaultOpen(part(), props.shellToolDefaultOpen, props.editToolDefaultOpen)}
|
},
|
||||||
/>
|
emptyTools,
|
||||||
)}
|
{ equals: same },
|
||||||
</Show>
|
)
|
||||||
)}
|
const busy = createMemo(() => props.working && last() === entryAccessor().key)
|
||||||
</Show>
|
|
||||||
|
return (
|
||||||
|
<Show when={parts().length > 0}>
|
||||||
|
<ContextToolGroup parts={parts()} busy={busy()} />
|
||||||
|
</Show>
|
||||||
|
)
|
||||||
|
})()}
|
||||||
|
</Match>
|
||||||
|
<Match when={entryType() === "part"}>
|
||||||
|
{(() => {
|
||||||
|
const message = createMemo(() => {
|
||||||
|
const entry = entryAccessor() as { type: "part"; ref: PartRef }
|
||||||
|
return props.messages.find((item) => item.id === entry.ref.messageID)
|
||||||
|
})
|
||||||
|
const part = createMemo(() => {
|
||||||
|
const entry = entryAccessor() as { type: "part"; ref: PartRef }
|
||||||
|
return partByID(list(data.store.part?.[entry.ref.messageID], emptyParts), entry.ref.partID)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Show when={message()}>
|
||||||
|
{(msg) => (
|
||||||
|
<Show when={part()}>
|
||||||
|
{(p) => (
|
||||||
|
<Part
|
||||||
|
part={p()}
|
||||||
|
message={msg()}
|
||||||
|
showAssistantCopyPartID={props.showAssistantCopyPartID}
|
||||||
|
turnDurationMs={props.turnDurationMs}
|
||||||
|
defaultOpen={partDefaultOpen(p(), props.shellToolDefaultOpen, props.editToolDefaultOpen)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Show>
|
||||||
|
)}
|
||||||
|
</Show>
|
||||||
|
)
|
||||||
|
})()}
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</For>
|
</Index>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,36 +650,56 @@ export function AssistantMessageDisplay(props: {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<For each={grouped()}>
|
<Index each={grouped()}>
|
||||||
{(entry) => {
|
{(entryAccessor) => {
|
||||||
if (entry.type === "context") {
|
const entryType = createMemo(() => entryAccessor().type)
|
||||||
const parts = createMemo(
|
|
||||||
() =>
|
|
||||||
entry.refs
|
|
||||||
.map((ref) => partByID(props.parts, ref.partID))
|
|
||||||
.filter((part): part is ToolPart => !!part && isContextGroupTool(part)),
|
|
||||||
emptyTools,
|
|
||||||
{ equals: same },
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Show when={parts().length > 0}>
|
|
||||||
<ContextToolGroup parts={parts()} />
|
|
||||||
</Show>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const part = createMemo(() => partByID(props.parts, entry.ref.partID))
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Show when={part()}>
|
<Switch>
|
||||||
{(part) => (
|
<Match when={entryType() === "context"}>
|
||||||
<Part part={part()} message={props.message} showAssistantCopyPartID={props.showAssistantCopyPartID} />
|
{(() => {
|
||||||
)}
|
const parts = createMemo(
|
||||||
</Show>
|
() => {
|
||||||
|
const entry = entryAccessor() as { type: "context"; refs: PartRef[] }
|
||||||
|
return entry.refs
|
||||||
|
.map((ref) => partByID(props.parts, ref.partID))
|
||||||
|
.filter((part): part is ToolPart => !!part && isContextGroupTool(part))
|
||||||
|
},
|
||||||
|
emptyTools,
|
||||||
|
{ equals: same },
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Show when={parts().length > 0}>
|
||||||
|
<ContextToolGroup parts={parts()} />
|
||||||
|
</Show>
|
||||||
|
)
|
||||||
|
})()}
|
||||||
|
</Match>
|
||||||
|
<Match when={entryType() === "part"}>
|
||||||
|
{(() => {
|
||||||
|
const part = createMemo(() => {
|
||||||
|
const entry = entryAccessor() as { type: "part"; ref: PartRef }
|
||||||
|
return partByID(props.parts, entry.ref.partID)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Show when={part()}>
|
||||||
|
{(p) => (
|
||||||
|
<Part
|
||||||
|
part={p()}
|
||||||
|
message={props.message}
|
||||||
|
showAssistantCopyPartID={props.showAssistantCopyPartID}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Show>
|
||||||
|
)
|
||||||
|
})()}
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</For>
|
</Index>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,10 @@ export function createAutoScroll(options: AutoScrollOptions) {
|
|||||||
|
|
||||||
const handleInteraction = () => {
|
const handleInteraction = () => {
|
||||||
if (!active()) return
|
if (!active()) return
|
||||||
stop()
|
const selection = window.getSelection()
|
||||||
|
if (selection && selection.toString().length > 0) {
|
||||||
|
stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateOverflowAnchor = (el: HTMLElement) => {
|
const updateOverflowAnchor = (el: HTMLElement) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user