authorgravatar for me@pixp.ccAlex <me@pixp.cc> 2026-10-11 11:28:25-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-11 11:28:25-07:00
logb4af60253bf013ebd146e23d8f66af94854da5d6
treea288cff1f512a40e49f99400c1479134f88bbc89
parent4bd0ecca19934dce38e16cd42eba5bf81c170d91
signature Signed by PGP key B5690EEEBB952194

fix(mobile): restore compact iPad trackpad scrolling (#13665)


1 files changed, 52 insertions(+), 45 deletions(-)

apps/mobile/src/features/home/HomeScreen.tsx+52-45
......@@ -25,6 +25,7 @@ import {
2525 type NativeSyntheticEvent,
2626} from "react-native";
2727import { ScrollViewMarker } from "react-native-screens";
28import { GestureDetector, useNativeGesture } from "react-native-gesture-handler";
2829import type { SwipeableMethods } from "react-native-gesture-handler/ReanimatedSwipeable";
2930import { useSafeAreaInsets } from "react-native-safe-area-context";
3031
......@@ -280,6 +281,8 @@ export function HomeScreen(props: HomeScreenProps) {
280281 const fullSwipeWidth = primaryColumn && columnMetrics ? columnMetrics.width - 20 : undefined;
281282 const queuedThreadKeys = useQueuedThreadKeys();
282283 const openSwipeableRef = useRef<SwipeableMethods | null>(null);
284 // Let trackpad scrolling coexist with each row's horizontal swipe gesture.
285 const homeScrollGesture = useNativeGesture();
283286 const insets = useSafeAreaInsets();
284287 const { fabClearance } = useAndroidControlSizing();
285288 const screenMetrics = useNativeLayoutMetrics();
......@@ -807,6 +810,7 @@ export function HomeScreen(props: HomeScreenProps) {
807810 onMoveThread={handleMoveThread}
808811 onSwipeableClose={handleSwipeableClose}
809812 onSwipeableWillOpen={handleSwipeableWillOpen}
813 simultaneousSwipeGesture={homeScrollGesture}
810814 activationKey={item.key}
811815 />
812816 );
......@@ -826,6 +830,7 @@ export function HomeScreen(props: HomeScreenProps) {
826830 handleSwipeableWillOpen,
827831 handleUnsettleThread,
828832 handleSetThreadAutoSettle,
833 homeScrollGesture,
829834 autoSettleOptOutEnvironmentIds,
830835 pinningEnvironmentIds,
831836 autoSettleOptOutEnvironmentIds,
......@@ -1012,51 +1017,53 @@ export function HomeScreen(props: HomeScreenProps) {
10121017 rebuilds and `itemsAreEqual` keeps a minute tick (or an unrelated
10131018 shell update) from re-rendering untouched rows. */}
10141019 <SwipeableScrollGateProvider enabled={swipeEnabled} activation={swipeRowActivation}>
1015 <LegendList
1016 ref={listRef}
1017 onLoad={() => activateVisibleRows(threadListV2Items)}
1018 onTouchStart={(event) => trackListTouches(event, true)}
1019 onTouchEnd={(event) => trackListTouches(event, false)}
1020 onTouchCancel={(event) => trackListTouches(event, false)}
1021 renderScrollComponent={Platform.OS === "ios" ? renderHomeScrollView : undefined}
1022 data={threadListV2Items}
1023 renderItem={renderV2Item}
1024 keyExtractor={v2KeyExtractor}
1025 getItemType={(item) => item.type}
1026 itemsAreEqual={threadListV2ListItemsAreEqual}
1027 estimatedItemSize={ESTIMATED_THREAD_LIST_V2_ROW_HEIGHT}
1028 drawDistance={THREAD_LIST_V2_DRAW_DISTANCE}
1029 recycleItems
1030 extraData={v2ExtraData}
1031 ListHeaderComponent={v2ListHeader}
1032 ListFooterComponent={
1033 settledShelfExpanded && threadListV2Layout.hiddenSettledCount > 0 ? (
1034 <ThreadListV2ShowMoreRow
1035 hiddenCount={threadListV2Layout.hiddenSettledCount}
1036 onPress={showMoreSettled}
1037 />
1038 ) : null
1039 }
1040 ListEmptyComponent={v2ListEmpty}
1041 style={{ flex: 1 }}
1042 automaticallyAdjustsScrollIndicatorInsets={Platform.OS === "ios"}
1043 contentInsetAdjustmentBehavior="never"
1044 contentInset={Platform.OS === "ios" ? { top: insets.top } : undefined}
1045 contentInsetStartAdjustment={Platform.OS === "ios" ? insets.top : 0}
1046 showsVerticalScrollIndicator={false}
1047 keyboardDismissMode="on-drag"
1048 keyboardShouldPersistTaps="handled"
1049 {...scrollGateHandlers}
1050 scrollEventThrottle={16}
1051 contentContainerStyle={{
1052 paddingLeft: (contentSideInsets?.left ?? 0) + (primaryColumn ? 8 : 0),
1053 paddingRight: (contentSideInsets?.right ?? 0) + (primaryColumn ? 8 : 0),
1054 paddingBottom:
1055 Platform.OS === "ios"
1056 ? iosBottomClearance
1057 : Math.max(insets.bottom, 16) + (Platform.OS === "android" ? fabClearance : 88),
1058 }}
1059 />
1020 <GestureDetector gesture={homeScrollGesture}>
1021 <LegendList
1022 ref={listRef}
1023 onLoad={() => activateVisibleRows(threadListV2Items)}
1024 onTouchStart={(event) => trackListTouches(event, true)}
1025 onTouchEnd={(event) => trackListTouches(event, false)}
1026 onTouchCancel={(event) => trackListTouches(event, false)}
1027 renderScrollComponent={Platform.OS === "ios" ? renderHomeScrollView : undefined}
1028 data={threadListV2Items}
1029 renderItem={renderV2Item}
1030 keyExtractor={v2KeyExtractor}
1031 getItemType={(item) => item.type}
1032 itemsAreEqual={threadListV2ListItemsAreEqual}
1033 estimatedItemSize={ESTIMATED_THREAD_LIST_V2_ROW_HEIGHT}
1034 drawDistance={THREAD_LIST_V2_DRAW_DISTANCE}
1035 recycleItems
1036 extraData={v2ExtraData}
1037 ListHeaderComponent={v2ListHeader}
1038 ListFooterComponent={
1039 settledShelfExpanded && threadListV2Layout.hiddenSettledCount > 0 ? (
1040 <ThreadListV2ShowMoreRow
1041 hiddenCount={threadListV2Layout.hiddenSettledCount}
1042 onPress={showMoreSettled}
1043 />
1044 ) : null
1045 }
1046 ListEmptyComponent={v2ListEmpty}
1047 style={{ flex: 1 }}
1048 automaticallyAdjustsScrollIndicatorInsets={Platform.OS === "ios"}
1049 contentInsetAdjustmentBehavior="never"
1050 contentInset={Platform.OS === "ios" ? { top: insets.top } : undefined}
1051 contentInsetStartAdjustment={Platform.OS === "ios" ? insets.top : 0}
1052 showsVerticalScrollIndicator={false}
1053 keyboardDismissMode="on-drag"
1054 keyboardShouldPersistTaps="handled"
1055 {...scrollGateHandlers}
1056 scrollEventThrottle={16}
1057 contentContainerStyle={{
1058 paddingLeft: (contentSideInsets?.left ?? 0) + (primaryColumn ? 8 : 0),
1059 paddingRight: (contentSideInsets?.right ?? 0) + (primaryColumn ? 8 : 0),
1060 paddingBottom:
1061 Platform.OS === "ios"
1062 ? iosBottomClearance
1063 : Math.max(insets.bottom, 16) + (Platform.OS === "android" ? fabClearance : 88),
1064 }}
1065 />
1066 </GestureDetector>
10601067 </SwipeableScrollGateProvider>
10611068 </View>
10621069 </View>