diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 4f01badf4..2c49489ba 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -1091,7 +1091,9 @@ export default function Page() { const el = scroller 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 diff --git a/packages/app/src/pages/session/message-timeline.tsx b/packages/app/src/pages/session/message-timeline.tsx index 0aa07bf74..19d6e09d9 100644 --- a/packages/app/src/pages/session/message-timeline.tsx +++ b/packages/app/src/pages/session/message-timeline.tsx @@ -689,7 +689,9 @@ export function MessageTimeline(props: { if (!item || active()) return false 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) return (
grouped().at(-1)?.key) return ( - - {(entry) => { - if (entry.type === "context") { - 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 ( - 0}> - - - ) - } - - 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), - ) + + {(entryAccessor) => { + const entryType = createMemo(() => entryAccessor().type) return ( - - {(message) => ( - - {(part) => ( - - )} - - )} - + + + {(() => { + const parts = createMemo( + () => { + const entry = entryAccessor() as { type: "context"; refs: PartRef[] } + return 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() === entryAccessor().key) + + return ( + 0}> + + + ) + })()} + + + {(() => { + 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 ( + + {(msg) => ( + + {(p) => ( + + )} + + )} + + ) + })()} + + ) }} - + ) } @@ -632,36 +650,56 @@ export function AssistantMessageDisplay(props: { ) return ( - - {(entry) => { - if (entry.type === "context") { - const parts = createMemo( - () => - entry.refs - .map((ref) => partByID(props.parts, ref.partID)) - .filter((part): part is ToolPart => !!part && isContextGroupTool(part)), - emptyTools, - { equals: same }, - ) - - return ( - 0}> - - - ) - } - - const part = createMemo(() => partByID(props.parts, entry.ref.partID)) + + {(entryAccessor) => { + const entryType = createMemo(() => entryAccessor().type) return ( - - {(part) => ( - - )} - + + + {(() => { + const parts = createMemo( + () => { + 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 ( + 0}> + + + ) + })()} + + + {(() => { + const part = createMemo(() => { + const entry = entryAccessor() as { type: "part"; ref: PartRef } + return partByID(props.parts, entry.ref.partID) + }) + + return ( + + {(p) => ( + + )} + + ) + })()} + + ) }} - + ) } diff --git a/packages/ui/src/hooks/create-auto-scroll.tsx b/packages/ui/src/hooks/create-auto-scroll.tsx index c32017739..8483915a8 100644 --- a/packages/ui/src/hooks/create-auto-scroll.tsx +++ b/packages/ui/src/hooks/create-auto-scroll.tsx @@ -142,7 +142,10 @@ export function createAutoScroll(options: AutoScrollOptions) { const handleInteraction = () => { if (!active()) return - stop() + const selection = window.getSelection() + if (selection && selection.toString().length > 0) { + stop() + } } const updateOverflowAnchor = (el: HTMLElement) => {