From cf9dfcf9477e16582bdd50220618b1793b7333bd Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Tue, 21 Jul 2026 21:33:47 +0200 Subject: [PATCH] fix(app): stop Android chat jumping during streaming The inverted list's native position maintenance fought the sticky-bottom controller as the live message grew. Let the controller exclusively own the Android sticky-bottom anchor while preserving position maintenance when reading history. --- packages/app/src/agent-stream/strategy-native.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/app/src/agent-stream/strategy-native.tsx b/packages/app/src/agent-stream/strategy-native.tsx index 0f9f04b8c..4463aae6f 100644 --- a/packages/app/src/agent-stream/strategy-native.tsx +++ b/packages/app/src/agent-stream/strategy-native.tsx @@ -11,6 +11,7 @@ import { FlatList, ActivityIndicator, Keyboard, + Platform, View, type LayoutChangeEvent, type ListRenderItemInfo, @@ -189,6 +190,12 @@ function NativeStreamViewport(props: StreamRenderInput & { strategy: StreamStrat }, scrollToBottom, }); + // Android's maintainVisibleContentPosition ignores the list inversion transform and + // fights the controller's offset-zero correction while the live header grows. + const maintainVisibleContentPosition = + Platform.OS === "android" && bottomAnchorController.mode === "sticky-bottom" + ? undefined + : DEFAULT_MAINTAIN_VISIBLE_CONTENT_POSITION; useEffect(() => { streamViewportMetricsRef.current = { @@ -414,7 +421,7 @@ function NativeStreamViewport(props: StreamRenderInput & { strategy: StreamStrat onScroll={handleScroll} scrollEventThrottle={16} onContentSizeChange={handleContentSizeChange} - maintainVisibleContentPosition={DEFAULT_MAINTAIN_VISIBLE_CONTENT_POSITION} + maintainVisibleContentPosition={maintainVisibleContentPosition} initialNumToRender={40} maxToRenderPerBatch={40} updateCellsBatchingPeriod={0}