Only set programmatic scroll if room scroll will move
This commit is contained in:
parent
2b26c033f6
commit
3f57607780
1 changed files with 8 additions and 11 deletions
|
|
@ -245,25 +245,22 @@
|
||||||
const topOf = (target: HTMLElement) =>
|
const topOf = (target: HTMLElement) =>
|
||||||
target.getBoundingClientRect().top - element!.getBoundingClientRect().top
|
target.getBoundingClientRect().top - element!.getBoundingClientRect().top
|
||||||
|
|
||||||
// Messages loading in below the pinned row are inserted at the scroll origin, which pushes
|
// Messages arriving at the origin push the pinned row away, and the browser does not compensate.
|
||||||
// everything else away from it. The browser has no reason to compensate for that, so put the
|
|
||||||
// row back where it was. scrollBy is in visual terms, so this reads the same way either way up.
|
|
||||||
//
|
|
||||||
// A row the scroll clamped at the origin is the exception: it is pinned to the live end of the
|
|
||||||
// loaded window, and once the forward walk reaches the present that is the live end of the
|
|
||||||
// conversation, where an arriving message belongs on screen. Settling there while the origin is
|
|
||||||
// still within reach of the row leaves a jump deep into history — clamped the same way with
|
|
||||||
// nothing newer loaded yet — where it landed.
|
|
||||||
const keepPinned = (caughtUp: boolean) => {
|
const keepPinned = (caughtUp: boolean) => {
|
||||||
const target = pinned && element?.querySelector(`[data-event="${pinned.id}"]`)
|
const target = pinned && element?.querySelector(`[data-event="${pinned.id}"]`)
|
||||||
|
|
||||||
if (target instanceof HTMLElement && pinned) {
|
if (target instanceof HTMLElement && pinned) {
|
||||||
const origin = Math.abs(element!.scrollTop)
|
const origin = Math.abs(element!.scrollTop)
|
||||||
|
|
||||||
|
// A pin clamped at the origin belongs at the live end once the forward walk catches up.
|
||||||
if (pinned.clamped && caughtUp && topOf(target) > origin) {
|
if (pinned.clamped && caughtUp && topOf(target) > origin) {
|
||||||
release()
|
release()
|
||||||
isProgrammaticScroll = true
|
|
||||||
element!.scrollTo({top: 0})
|
// Only a scroll event clears the flag, so claiming one that never fires discards the next.
|
||||||
|
if (origin >= 1) {
|
||||||
|
isProgrammaticScroll = true
|
||||||
|
element!.scrollTo({top: 0})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const drift = topOf(target) - pinned.top
|
const drift = topOf(target) - pinned.top
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue