fix(webui): preserve user scroll ownership near tail (#5193)

This commit is contained in:
chengyongru
2026-07-31 23:37:26 +08:00
committed by GitHub
parent dda9b61b1e
commit 172fe4f991
4 changed files with 191 additions and 11 deletions
+54
View File
@@ -410,6 +410,9 @@ describe("ThreadMotionCoordinator", () => {
expect(camera.jumpTo).toHaveBeenCalledWith(780);
coordinator.takeUserControl();
expect(coordinator.observeScroll(true)).toBe("user");
expect(coordinator.snapshot().mode).toBe("browsing-history");
expect(coordinator.observeScroll(false)).toBe("user");
expect(coordinator.snapshot().mode).toBe("browsing-history");
@@ -417,6 +420,57 @@ describe("ThreadMotionCoordinator", () => {
expect(coordinator.snapshot().mode).toBe("anchor-prompt");
});
it("resumes shallow history browsing when user intent turns toward latest", () => {
const {
camera,
coordinator,
advanceFrame,
} = motionHarness({
scrollTop: 1_400,
});
coordinator.updateTurn({
id: "turn-1",
promptId: "prompt-1",
hasOutput: true,
});
advanceFrame();
camera.followTo.mockClear();
coordinator.handleUserScrollIntent(true);
expect(coordinator.observeScroll(true)).toBe("user");
advanceFrame();
expect(camera.followTo).not.toHaveBeenCalled();
coordinator.handleUserScrollIntent(true, true);
expect(coordinator.observeScroll(true)).toBe("automatic");
expect(coordinator.snapshot().mode).toBe("follow-output");
advanceFrame();
expect(camera.followTo).toHaveBeenCalledWith(1_400);
});
it("resumes shallow history browsing from forward intent at the boundary", () => {
const {
advanceFrame,
coordinator,
onAutoFollow,
} = motionHarness({
scrollTop: 1_400,
});
coordinator.updateTurn({
id: "turn-1",
promptId: "prompt-1",
hasOutput: true,
});
advanceFrame();
coordinator.handleUserScrollIntent(true);
expect(coordinator.observeScroll(true)).toBe("user");
coordinator.handleUserScrollIntent(false, true);
expect(coordinator.snapshot().mode).toBe("follow-output");
expect(onAutoFollow).toHaveBeenCalledTimes(1);
});
it("preserves history browsing when an active turn is cleared", () => {
const {
camera,