Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions apps/web/src/components/chat/MessagesTimeline.browser.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,45 @@ const TASK_ID = ScheduledTaskId.make("task-1");
const AUTOMATION_PROMPT = "Triage the inbox\n\nLabel every new issue and close duplicates.";

describe("MessagesTimeline work rows", () => {
it("keeps the worked-for heading in place when expanded at the bottom", async () => {
const props = baseProps();
const runId = RunId.make("completed-run");
const container = document.createElement("div");
container.style.cssText = "height: 600px; width: 900px; display: flex; flex-direction: column;";
await using screen = await render(
<MessagesTimeline
{...props}
timelineEntries={[
...Array.from({ length: 12 }, (_, index) =>
message(`Earlier context ${index}`, {}, `context-${index}`),
),
message("Progress details\n\n".repeat(50), { role: "assistant", runId }, "progress"),
message("Done", { role: "assistant", runId }, "final"),
]}
/>,
{ container },
);
const heading = screen.getByRole("button", { name: /^Worked for/ });
await expect.element(heading).toBeVisible();
const viewport = props.listRef.current!.getScrollableNode()!;
await vi.waitFor(() =>
expect(viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop).toBeLessThan(2),
);
expect(viewport.scrollTop).toBeGreaterThan(0);
const top = heading.element().getBoundingClientRect().top;
const height = viewport.scrollHeight;
using _timers = fakeTimers();
await heading.click();
await act(() => vi.advanceTimersByTime(1000));
await vi.waitFor(() => {
expect(viewport.scrollHeight).toBeGreaterThan(height + 500);
expect(heading.element().getBoundingClientRect().top).toBeCloseTo(top, 0);
expect(viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop).toBeGreaterThan(
500,
);
});
});

it.each(["delegated", "legacy", "missing"] as const)(
"uses the reported task for %s completion notifications",
async (source) => {
Expand Down
15 changes: 1 addition & 14 deletions apps/web/src/components/chat/MessagesTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -470,13 +470,6 @@ const ConversationTimeline = memo(function ConversationTimeline({
const normalizedFindQuery = findQuery.trim();
const findActive = findExpanded;

const disclosurePinsEndRef = useRef(false);
const pinDisclosureToEnd = () => {
if (!disclosurePinsEndRef.current) return;
const element = listRef.current?.getScrollableNode();
if (element) element.scrollTop = element.scrollHeight;
};

const scheduleDisclosureSettle = () => {
if (disclosureSettleFrameRef.current !== null) {
cancelAnimationFrame(disclosureSettleFrameRef.current);
Expand All @@ -485,10 +478,7 @@ const ConversationTimeline = memo(function ConversationTimeline({
cancelAnimationFrame(disclosureSettleSecondFrameRef.current);
}
disclosureSettleFrameRef.current = requestAnimationFrame(() => {
pinDisclosureToEnd();
disclosureSettleSecondFrameRef.current = requestAnimationFrame(() => {
pinDisclosureToEnd();
disclosurePinsEndRef.current = false;
disclosureAnchorKeyRef.current = null;
setDisclosureToggleSettling(false);
disclosureSettleFrameRef.current = null;
Expand All @@ -499,13 +489,11 @@ const ConversationTimeline = memo(function ConversationTimeline({

const suspendEndScrollMaintenanceForDisclosure = (anchorKey: string) => {
disclosureAnchorKeyRef.current = anchorKey;
disclosurePinsEndRef.current = resolveTimelineIsAtEnd(listRef.current?.getState()) === true;
setDisclosureToggleSettling(true);
scheduleDisclosureSettle();
};

const shouldRestoreVisibleContentPosition = (row: MessagesTimelineRow) => {
if (disclosurePinsEndRef.current) return false;
const disclosureAnchorKey = disclosureAnchorKeyRef.current;
return disclosureAnchorKey === null || row.id === disclosureAnchorKey;
};
Expand Down Expand Up @@ -955,8 +943,7 @@ const ConversationTimeline = memo(function ConversationTimeline({
};

const handleItemSizeChanged = () => {
if (disclosurePinsEndRef.current) {
queueMicrotask(pinDisclosureToEnd);
if (disclosureAnchorKeyRef.current !== null) {
scheduleDisclosureSettle();
}
scheduleMinimapRefresh();
Expand Down
Loading