Skip to content

Commit 8100062

Browse files
authored
fix(mobile): improve keyboard avoiding (#5451)
1 parent a1762fd commit 8100062

2 files changed

Lines changed: 7 additions & 54 deletions

File tree

‎apps/mobile/package.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,5 +138,10 @@
138138
"@react-native-menu/menu"
139139
]
140140
}
141+
},
142+
"reanimated": {
143+
"staticFeatureFlags": {
144+
"DISABLE_COMMIT_PAUSING_MECHANISM": true
145+
}
141146
}
142147
}

‎apps/mobile/src/features/threads/ThreadFeed.tsx‎

Lines changed: 2 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,7 @@ import {
4545
import { TouchableOpacity } from "react-native-gesture-handler";
4646
import ImageViewing from "react-native-image-viewing";
4747
import { useSafeAreaInsets } from "react-native-safe-area-context";
48-
import Animated, {
49-
FadeIn,
50-
FadeInUp,
51-
useSharedValue,
52-
withTiming,
53-
type LayoutAnimationsValues,
54-
type SharedValue,
55-
} from "react-native-reanimated";
48+
import Animated, { FadeIn, FadeInUp, type SharedValue } from "react-native-reanimated";
5649
import { useThemeColor } from "../../lib/useThemeColor";
5750
import { useFontFamily } from "../../lib/useFontFamily";
5851
import { copyTextWithHaptic } from "../../lib/copyTextWithHaptic";
@@ -117,14 +110,6 @@ function formatMessageTime(input: string): string {
117110
return MESSAGE_TIME_FORMATTER.format(timestamp);
118111
}
119112

120-
// Rows shift when content above them grows (streaming text, work-log folds);
121-
// animating the container position turns those jumps into slides. Applied
122-
// conditionally — see the gated transition in ThreadFeed: while browsing
123-
// history the animation must NOT run, or every estimate→actual size
124-
// correction plays as a visible slide against the instant scroll-offset
125-
// compensation from maintainVisibleContentPosition.
126-
const FEED_ITEM_LAYOUT_DURATION_MS = 180;
127-
128113
// Pre-measurement heights for getFixedItemSize, mirroring renderFeedEntry's
129114
// classNames. The fold row's min-h-11 (44px) stays taller than its single
130115
// text-sm line at every supported base font size (26px at the 22pt maximum),
@@ -1457,22 +1442,13 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
14571442
},
14581443
[props.onHeaderMaterialVisibilityChange],
14591444
);
1460-
// True while the viewport sits within ~one screen of the list end — the
1461-
// only region where layout shifts should animate. Starts true because the
1462-
// list opens pinned to the end.
1463-
const nearListEnd = useSharedValue(true);
1464-
14651445
const handleScroll = useCallback(
14661446
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
14671447
// anchorTopInset, not topContentInset: under automatic insets the list
14681448
// rests at contentOffset.y = -headerHeight (the inset lives only in
14691449
// UIKit's adjustedContentInset, so topContentInset is 0 here). Add the
14701450
// header height back or the material toggles a full header too late.
14711451
reportHeaderMaterialVisibility(event.nativeEvent.contentOffset.y + anchorTopInset > 6);
1472-
const { contentOffset, contentSize, layoutMeasurement } = event.nativeEvent;
1473-
nearListEnd.value =
1474-
contentSize.height - layoutMeasurement.height - contentOffset.y < layoutMeasurement.height;
1475-
14761452
// Latch bookkeeping. LegendList recomputes its inset-aware end distance
14771453
// before invoking this handler, so getState() is current. Returning to
14781454
// the end re-arms follow no matter who scrolled (the user, or our own
@@ -1488,7 +1464,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
14881464
}
14891465
}
14901466
},
1491-
[reportHeaderMaterialVisibility, anchorTopInset, nearListEnd, props.listRef, setEndFollow],
1467+
[reportHeaderMaterialVisibility, anchorTopInset, props.listRef, setEndFollow],
14921468
);
14931469
const handleScrollBeginDrag = useCallback(() => {
14941470
userScrollSessionRef.current = true;
@@ -1508,33 +1484,6 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
15081484
userScrollSessionRef.current = false;
15091485
}, []);
15101486

1511-
// Gated variant of the 180ms feed layout slide. Instant while browsing
1512-
// history: maintainVisibleContentPosition compensates the scroll offset in
1513-
// the same frame a row's measured size lands, so an instant reposition is
1514-
// invisible — animating it is exactly what made cold upward scrolls slide
1515-
// and jump. Near the end the slide stays on: streaming growth and sends
1516-
// shift rows at rest, where the animation is the thing preventing a hard
1517-
// visual snap.
1518-
const feedItemLayoutTransition = useMemo(() => {
1519-
return (values: LayoutAnimationsValues) => {
1520-
"worklet";
1521-
const duration = nearListEnd.value ? FEED_ITEM_LAYOUT_DURATION_MS : 0;
1522-
return {
1523-
initialValues: {
1524-
originX: values.currentOriginX,
1525-
originY: values.currentOriginY,
1526-
width: values.currentWidth,
1527-
height: values.currentHeight,
1528-
},
1529-
animations: {
1530-
originX: withTiming(values.targetOriginX, { duration }),
1531-
originY: withTiming(values.targetOriginY, { duration }),
1532-
width: withTiming(values.targetWidth, { duration }),
1533-
height: withTiming(values.targetHeight, { duration }),
1534-
},
1535-
};
1536-
};
1537-
}, [nearListEnd]);
15381487
const handleViewportLayout = useCallback((event: LayoutChangeEvent) => {
15391488
const nextWidth = Math.round(event.nativeEvent.layout.width);
15401489
const nextHeight = Math.round(event.nativeEvent.layout.height);
@@ -1886,7 +1835,6 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
18861835
}
18871836
: { scrollIndicatorInsets: { top: topContentInset, bottom: 0 } })}
18881837
{...(anchoredEndSpace ? { anchoredEndSpace } : {})}
1889-
itemLayoutAnimation={feedItemLayoutTransition}
18901838
// Patched LegendList prop (patches/@legendapp__list@3.2.0.patch):
18911839
// lets its scroll math clamp programmatic scrolls to -headerInset
18921840
// instead of 0, so initialScrollAtEnd/maintainScrollAtEnd on short

0 commit comments

Comments
 (0)