fix(chat): register touch opt-out by finger direction

On touch surfaces the gesture opt-out waited for the viewport to have
already left the end, but streaming corrections re-pin the viewport every
chunk, so the drag never registered: the user could not scroll away
mid-stream, the scroll-to-bottom pill (which waits for a gesture) never
appeared, and live-follow stayed armed — which also made the mobile
load-older button throw the viewport to the bottom, since the prepend's
content growth ran the end correction.

Track the finger's Y between touch events and treat a downward drag (the
touch mirror of wheel-up) as an immediate opt-out. Loading older history
also releases live follow explicitly before the prepend, covering the
case where the button is reachable without any prior scroll.
This commit is contained in:
Bohdan Triapitsyn
2026-08-25 15:06:31 +03:00
parent 34ae8b059e
commit 4d3542fdb4
2 changed files with 31 additions and 5 deletions
@@ -1009,8 +1009,12 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({
&& timelineController.historySignals.canLoadEarlier;
const timelineLoadEarlier = timelineController.loadEarlier;
const handleLoadOlderClick = React.useCallback(() => {
// Loading older history is an explicit move INTO the past: release
// live follow first, or the prepend's content growth would trigger an
// end correction and throw the viewport to the bottom.
onManualNavigation();
void timelineLoadEarlier({ userInitiated: true });
}, [timelineLoadEarlier]);
}, [onManualNavigation, timelineLoadEarlier]);
React.useEffect(() => {
activeTurnChangeRef.current = timelineController.handleActiveTurnChange;