Adjust timeline message scroll targeting to use scrollIntoView

Co-authored-by: trevor-signal <trevor@signal.org>
This commit is contained in:
ayumi-signal
2025-10-21 09:22:14 -07:00
committed by GitHub
parent 74eb1c9bb9
commit 9d34375bb7
2 changed files with 15 additions and 4 deletions

View File

@@ -1021,7 +1021,7 @@ export class Message extends React.PureComponent<Props, State> {
this.setState(({ metadataWidth }) => ({
// We don't want text to jump around if the metadata shrinks, but we want to make
// sure we have enough room.
metadataWidth: Math.max(metadataWidth, newMetadataWidth),
metadataWidth: Math.ceil(Math.max(metadataWidth, newMetadataWidth)),
}));
};

View File

@@ -281,7 +281,7 @@ export class Timeline extends React.Component<
this.#messagesRef.current
?.querySelector(`[data-item-index="${itemIndex}"]`)
?.scrollIntoViewIfNeeded();
?.scrollIntoView({ block: 'center' });
}
#scrollToBottom = (setFocus?: boolean): void => {
@@ -532,6 +532,7 @@ export class Timeline extends React.Component<
const atBottomDetectorEl = this.#atBottomDetectorRef.current;
let centerMessageId: undefined | string;
let centerMessageRelativeTop = 0;
for (const [element, intersectionRatio] of this.#intersectionRatios) {
if (intersectionRatio === 0) {
continue;
@@ -548,8 +549,13 @@ export class Timeline extends React.Component<
const relativeTop =
element.getBoundingClientRect().top - containerElRectTop;
if (!centerMessageId || relativeTop < containerElMidline) {
if (
!centerMessageId ||
(relativeTop > centerMessageRelativeTop &&
relativeTop < containerElMidline)
) {
centerMessageId = messageId;
centerMessageRelativeTop = relativeTop;
}
}
@@ -728,7 +734,12 @@ export class Timeline extends React.Component<
);
}
} else if ('scrollToIndex' in snapshot) {
this.#scrollToItemIndex(snapshot.scrollToIndex);
// Wait to scroll until after another render has completed, to allow for message
// sizes to measured & stabilize
this.setState(
state => state,
() => this.#scrollToItemIndex(snapshot.scrollToIndex)
);
} else if ('scrollTop' in snapshot) {
containerEl.scrollTop = snapshot.scrollTop;
} else {