1
0
Fork 0
forked from Mirrors/gomuks

web/timeline: fix scroll to bottom firing incorrectly in some cases

This commit is contained in:
Tulir Asokan 2024-10-25 03:29:32 +03:00
parent f88b1b5b7f
commit 854a929c92
2 changed files with 9 additions and 7 deletions

View file

@ -28,11 +28,14 @@ export class RoomContextData {
public setEditing: (evt: MemDBEvent | null) => void = noop("setEditing") public setEditing: (evt: MemDBEvent | null) => void = noop("setEditing")
public isEditing = new NonNullCachedEventDispatcher<boolean>(false) public isEditing = new NonNullCachedEventDispatcher<boolean>(false)
public ownMessages: EventRowID[] = [] public ownMessages: EventRowID[] = []
public scrolledToBottom = true
constructor(public store: RoomStateStore) {} constructor(public store: RoomStateStore) {}
scrollToBottom() { scrollToBottom() {
this.timelineBottomRef.current?.scrollIntoView() if (this.scrolledToBottom) {
this.timelineBottomRef.current?.scrollIntoView()
}
} }
} }

View file

@ -36,7 +36,6 @@ const TimelineView = () => {
const timelineViewRef = useRef<HTMLDivElement>(null) const timelineViewRef = useRef<HTMLDivElement>(null)
const prevOldestTimelineRow = useRef(0) const prevOldestTimelineRow = useRef(0)
const oldScrollHeight = useRef(0) const oldScrollHeight = useRef(0)
const scrolledToBottom = useRef(true)
const focused = useFocus() const focused = useFocus()
// When the user scrolls the timeline manually, remember if they were at the bottom, // When the user scrolls the timeline manually, remember if they were at the bottom,
@ -46,15 +45,15 @@ const TimelineView = () => {
return return
} }
const timelineView = timelineViewRef.current const timelineView = timelineViewRef.current
scrolledToBottom.current = timelineView.scrollTop + timelineView.clientHeight + 1 >= timelineView.scrollHeight roomCtx.scrolledToBottom = timelineView.scrollTop + timelineView.clientHeight + 1 >= timelineView.scrollHeight
}, []) }, [roomCtx])
// Save the scroll height prior to updating the timeline, so that we can adjust the scroll position if needed. // Save the scroll height prior to updating the timeline, so that we can adjust the scroll position if needed.
if (timelineViewRef.current) { if (timelineViewRef.current) {
oldScrollHeight.current = timelineViewRef.current.scrollHeight oldScrollHeight.current = timelineViewRef.current.scrollHeight
} }
useLayoutEffect(() => { useLayoutEffect(() => {
const bottomRef = roomCtx.timelineBottomRef const bottomRef = roomCtx.timelineBottomRef
if (bottomRef.current && scrolledToBottom.current) { if (bottomRef.current && roomCtx.scrolledToBottom) {
// For any timeline changes, if we were at the bottom, scroll to the new bottom // For any timeline changes, if we were at the bottom, scroll to the new bottom
bottomRef.current.scrollIntoView() bottomRef.current.scrollIntoView()
} else if (timelineViewRef.current && prevOldestTimelineRow.current > (timeline[0]?.timeline_rowid ?? 0)) { } else if (timelineViewRef.current && prevOldestTimelineRow.current > (timeline[0]?.timeline_rowid ?? 0)) {
@ -72,7 +71,7 @@ const TimelineView = () => {
useEffect(() => { useEffect(() => {
const newestEvent = timeline[timeline.length - 1] const newestEvent = timeline[timeline.length - 1]
if ( if (
scrolledToBottom.current roomCtx.scrolledToBottom
&& focused && focused
&& newestEvent && newestEvent
&& newestEvent.timeline_rowid > 0 && newestEvent.timeline_rowid > 0
@ -85,7 +84,7 @@ const TimelineView = () => {
err => console.error(`Failed to send read receipt for ${newestEvent.event_id}:`, err), err => console.error(`Failed to send read receipt for ${newestEvent.event_id}:`, err),
) )
} }
}, [focused, client, room, timeline]) }, [focused, client, roomCtx, room, timeline])
useEffect(() => { useEffect(() => {
const topElem = topRef.current const topElem = topRef.current
if (!topElem) { if (!topElem) {