Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Fix: Reset scrollIntoView state earlier
Browse files Browse the repository at this point in the history
  • Loading branch information
justjanne committed Apr 8, 2022
1 parent 0d07613 commit 677903c
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 34 deletions.
6 changes: 5 additions & 1 deletion src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1296,8 +1296,11 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
});
}
this.updateTopUnreadMessagesBar();
};

if (this.state.initialEventId && this.state.initialEventScrollIntoView) {
private resetJumpToEvent = (eventId?: string) => {
if (this.state.initialEventId && this.state.initialEventScrollIntoView &&
this.state.initialEventId === eventId) {
debuglog("Removing scroll_into_view flag from initial event");
dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
Expand Down Expand Up @@ -2064,6 +2067,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
eventScrollIntoView={this.state.initialEventScrollIntoView}
eventPixelOffset={this.state.initialEventPixelOffset}
onScroll={this.onMessageListScroll}
onEventScrolledIntoView={this.resetJumpToEvent}
onReadMarkerUpdated={this.updateTopUnreadMessagesBar}
showUrlPreview={this.state.showUrlPreview}
className={this.messagePanelClassNames}
Expand Down
7 changes: 4 additions & 3 deletions src/components/structures/ThreadView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,9 @@ export default class ThreadView extends React.Component<IProps, IState> {
}
};

private resetJumpToEvent = (): void => {
if (this.props.initialEvent && this.props.initialEventScrollIntoView) {
private resetJumpToEvent = (event?: string): void => {
if (this.props.initialEvent && this.props.initialEventScrollIntoView &&
event === this.props.initialEvent?.getId()) {
dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
room_id: this.props.room.roomId,
Expand Down Expand Up @@ -375,7 +376,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
eventId={this.props.initialEvent?.getId()}
highlightedEventId={highlightedEventId}
eventScrollIntoView={this.props.initialEventScrollIntoView}
onScroll={this.resetJumpToEvent}
onEventScrolledIntoView={this.resetJumpToEvent}
onPaginationRequest={this.onPaginationRequest}
/>
</div> }
Expand Down
67 changes: 37 additions & 30 deletions src/components/structures/TimelinePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ interface IProps {
// callback which is called when the panel is scrolled.
onScroll?(event: Event): void;

onEventScrolledIntoView?(eventId?: string): void;

// callback which is called when the read-up-to mark is updated.
onReadMarkerUpdated?(): void;

Expand Down Expand Up @@ -1128,6 +1130,40 @@ class TimelinePanel extends React.Component<IProps, IState> {
return this.loadTimeline(initialEvent, pixelOffset, offsetBase, props.eventScrollIntoView);
}

private scrollIntoView(eventId?: string, pixelOffset?: number, offsetBase?: number): void {
const doScroll = () => {
if (eventId) {
debuglog("TimelinePanel scrolling to eventId " + eventId +
" at position " + (offsetBase * 100) + "% + " + pixelOffset);
this.messagePanel.current.scrollToEvent(
eventId,
pixelOffset,
offsetBase,
);
} else {
debuglog("TimelinePanel scrolling to bottom");
this.messagePanel.current.scrollToBottom();
}
};

debuglog("TimelinePanel scheduling scroll to event");
this.props.onEventScrolledIntoView?.(eventId);
// Ensure the correct scroll position pre render, if the messages have already been loaded to DOM,
// to avoid it jumping around
doScroll();

// Ensure the correct scroll position post render for correct behaviour.
//
// requestAnimationFrame runs our code immediately after the DOM update but before the next repaint.
//
// If the messages have just been loaded for the first time, this ensures we'll repeat setting the
// correct scroll position after React has re-rendered the TimelinePanel and MessagePanel and
// updated the DOM.
window.requestAnimationFrame(() => {
doScroll();
});
}

/**
* (re)-load the event timeline, and initialise the scroll state, centered
* around the given event.
Expand Down Expand Up @@ -1180,37 +1216,8 @@ class TimelinePanel extends React.Component<IProps, IState> {
return;
}

const doScroll = () => {
if (eventId) {
debuglog("TimelinePanel scrolling to eventId " + eventId +
" at position " + (offsetBase * 100) + "% + " + pixelOffset);
this.messagePanel.current.scrollToEvent(
eventId,
pixelOffset,
offsetBase,
);
} else {
debuglog("TimelinePanel scrolling to bottom");
this.messagePanel.current.scrollToBottom();
}
};

if (scrollIntoView) {
debuglog("TimelinePanel scheduling scroll to event");
// Ensure the correct scroll position pre render, if the messages have already been loaded to DOM, to
// avoid it jumping around
doScroll();

// Ensure the correct scroll position post render for correct behaviour.
//
// requestAnimationFrame runs our code immediately after the DOM update but before the next repaint.
//
// If the messages have just been loaded for the first time, this ensures we'll repeat setting the
// correct scroll position after React has re-rendered the TimelinePanel and MessagePanel and updated
// the DOM.
window.requestAnimationFrame(doScroll);
} else {
debuglog("TimelinePanel ignoring scroll, as requested");
this.scrollIntoView(eventId, pixelOffset, offsetBase);
}

if (this.props.sendReadReceiptOnLoad) {
Expand Down

0 comments on commit 677903c

Please sign in to comment.