Fix: Remove jittery timeline scrolling after jumping to an event (#8263)

* Fix: Remove jittery timeline scrolling after jumping to an event

* Fix: Remove onUserScroll handler and merge it with onScroll

* Fix: Reset scrollIntoView state earlier

Co-authored-by: Janne Mareike Koschinski <jannemk@element.io>
This commit is contained in:
Janne Mareike Koschinski 2022-04-08 20:48:57 +02:00 committed by GitHub
parent 285dc25b3e
commit 579a166113
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 118 additions and 87 deletions

View file

@ -155,6 +155,8 @@ export interface IRoomState {
initialEventPixelOffset?: number;
// Whether to highlight the event scrolled to
isInitialEventHighlighted?: boolean;
// Whether to scroll the event into view
initialEventScrollIntoView?: boolean;
replyToEvent?: MatrixEvent;
numUnreadMessages: number;
searchTerm?: string;
@ -404,7 +406,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
const roomId = RoomViewStore.instance.getRoomId();
const newState: Pick<IRoomState, any> = {
// This convoluted type signature ensures we get IntelliSense *and* correct typing
const newState: Partial<IRoomState> & Pick<IRoomState, any> = {
roomId,
roomAlias: RoomViewStore.instance.getRoomAlias(),
roomLoading: RoomViewStore.instance.isRoomLoading(),
@ -443,22 +446,29 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
);
}
// If we have an initial event, we want to reset the event pixel offset to ensure it ends up
// visible
newState.initialEventPixelOffset = null;
const thread = initialEvent?.getThread();
if (thread && !initialEvent?.isThreadRoot) {
showThread({
rootEvent: thread.rootEvent,
initialEvent,
highlighted: RoomViewStore.instance.isInitialEventHighlighted(),
scroll_into_view: RoomViewStore.instance.initialEventScrollIntoView(),
});
} else {
newState.initialEventId = initialEventId;
newState.isInitialEventHighlighted = RoomViewStore.instance.isInitialEventHighlighted();
newState.initialEventScrollIntoView = RoomViewStore.instance.initialEventScrollIntoView();
if (thread && initialEvent?.isThreadRoot) {
showThread({
rootEvent: thread.rootEvent,
initialEvent,
highlighted: RoomViewStore.instance.isInitialEventHighlighted(),
scroll_into_view: RoomViewStore.instance.initialEventScrollIntoView(),
});
}
}
@ -758,19 +768,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
}
}
private onUserScroll = () => {
if (this.state.initialEventId && this.state.isInitialEventHighlighted) {
dis.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
room_id: this.state.room.roomId,
event_id: this.state.initialEventId,
highlighted: false,
replyingToEvent: this.state.replyToEvent,
metricsTrigger: undefined, // room doesn't change
});
}
};
private onRightPanelStoreUpdate = () => {
this.setState({
showRightPanel: RightPanelStore.instance.isOpenForRoom(this.state.roomId),
@ -1301,6 +1298,22 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
this.updateTopUnreadMessagesBar();
};
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,
room_id: this.state.room.roomId,
event_id: this.state.initialEventId,
highlighted: this.state.isInitialEventHighlighted,
scroll_into_view: false,
replyingToEvent: this.state.replyToEvent,
metricsTrigger: undefined, // room doesn't change
});
}
};
private injectSticker(url: string, info: object, text: string, threadId: string | null) {
if (this.context.isGuest()) {
dis.dispatch({ action: 'require_registration' });
@ -2051,9 +2064,10 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
hidden={hideMessagePanel}
highlightedEventId={highlightedEventId}
eventId={this.state.initialEventId}
eventScrollIntoView={this.state.initialEventScrollIntoView}
eventPixelOffset={this.state.initialEventPixelOffset}
onScroll={this.onMessageListScroll}
onUserScroll={this.onUserScroll}
onEventScrolledIntoView={this.resetJumpToEvent}
onReadMarkerUpdated={this.updateTopUnreadMessagesBar}
showUrlPreview={this.state.showUrlPreview}
className={this.messagePanelClassNames}