Skip to content

Commit efd5f0a

Browse files
authored
fix(app): preserve timeline selection autoscroll (#35383)
1 parent 7135bc4 commit efd5f0a

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

packages/app/e2e/performance/timeline-stability/scroll-interaction.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,40 @@ test("does not reverse visible rows when the user wheels during shell remeasurem
4848
await reportVisualStability(testInfo, "wheel-during-resize", trace, rowPairPlan(regions, 1))
4949
})
5050

51+
test("keeps moving upward while drag-selecting above the timeline", async ({ page }) => {
52+
await setupTimeline(page, {
53+
messages: history(80),
54+
viewport: { width: 1400, height: 700 },
55+
reducedMotion: true,
56+
})
57+
const scroller = page.locator(".scroll-view__viewport", { has: page.locator("[data-timeline-row]") })
58+
const text = page.getByText("History 79.", { exact: false })
59+
await expect(text).toBeVisible()
60+
await scroller.evaluate((element) => {
61+
element.dataset.selectionLength = "0"
62+
document.addEventListener("selectionchange", () => {
63+
element.dataset.selectionLength = String(
64+
Math.max(Number(element.dataset.selectionLength), window.getSelection()?.toString().length ?? 0),
65+
)
66+
})
67+
})
68+
const textBox = await text.boundingBox()
69+
const scrollBox = await scroller.boundingBox()
70+
expect(textBox).not.toBeNull()
71+
expect(scrollBox).not.toBeNull()
72+
if (!textBox || !scrollBox) return
73+
74+
await page.mouse.move(textBox.x + textBox.width - 10, textBox.y + textBox.height / 2)
75+
await page.mouse.down()
76+
await page.mouse.move(textBox.x + 20, scrollBox.y - 120, { steps: 30 })
77+
78+
await expect.poll(() => scroller.evaluate((element) => Number(element.dataset.selectionLength))).toBeGreaterThan(0)
79+
await expect
80+
.poll(() => scroller.evaluate((element) => element.scrollHeight - element.clientHeight - element.scrollTop))
81+
.toBeGreaterThan(500)
82+
await page.mouse.up()
83+
})
84+
5185
test("does not pull a keyboard-scrolled user during shell remeasurement", async ({ page }, testInfo) => {
5286
const shellID = "prt_keyboard_01_shell"
5387
const followingID = "prt_keyboard_02_following"

packages/app/src/pages/session/timeline/message-timeline.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,12 @@ export function MessageTimeline(props: {
598598

599599
const handleListPointerDown = (event: PointerEvent & { currentTarget: HTMLDivElement }) => {
600600
if (!prependLoading) clearPrependAnchor()
601-
if (event.target !== event.currentTarget) return
602-
props.onMarkScrollGesture(event.currentTarget)
601+
props.onMarkScrollGesture(event.target)
602+
}
603+
604+
const handleListPointerMove = (event: PointerEvent) => {
605+
if (event.buttons !== 1) return
606+
props.onMarkScrollGesture(event.target)
603607
}
604608

605609
const handleListKeyDown = (event: KeyboardEvent & { currentTarget: HTMLDivElement }) => {
@@ -1356,6 +1360,7 @@ export function MessageTimeline(props: {
13561360
onTouchEnd={handleListTouchEnd}
13571361
onTouchCancel={handleListTouchEnd}
13581362
onPointerDown={handleListPointerDown}
1363+
onPointerMove={handleListPointerMove}
13591364
onKeyDown={handleListKeyDown}
13601365
onScroll={handleListScroll}
13611366
onClick={props.onAutoScrollInteraction}

0 commit comments

Comments
 (0)