From a74adb9a8ce9fa7f12f65968aeff3b331778c810 Mon Sep 17 00:00:00 2001 From: chrispader Date: Wed, 15 Jul 2026 10:04:20 +0200 Subject: [PATCH 1/9] Upgrade react-native-keyboard-controller for inverted scroll views --- package-lock.json | 8 +-- package.json | 2 +- .../details.md | 4 +- ...+1.22.1+001+fix-insets-in-landscape.patch} | 16 +++--- .../__mocks__/index.android.tsx | 3 +- .../__mocks__/index.ios.tsx | 3 +- .../__mocks__/index.tsx | 3 +- .../index.android.tsx | 46 +++++++++++++++- .../ActionSheetAwareScrollView/index.ios.tsx | 53 ++++++++++++++++++- .../ActionSheetAwareScrollView/index.tsx | 4 +- .../ActionSheetAwareScrollView/types.ts | 6 +++ src/pages/inbox/report/ReportActionsList.tsx | 2 +- 12 files changed, 126 insertions(+), 24 deletions(-) rename patches/react-native-keyboard-controller/{react-native-keyboard-controller+1.21.0-beta.1+001+fix-insets-in-landscape.patch => react-native-keyboard-controller+1.22.1+001+fix-insets-in-landscape.patch} (69%) diff --git a/package-lock.json b/package-lock.json index 05485c7179c3..bac4105bc473 100644 --- a/package-lock.json +++ b/package-lock.json @@ -118,7 +118,7 @@ "react-native-image-picker": "^7.1.2", "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#8a1c3b7359977462cdd4e63b09ea45afbd3d77c7", "react-native-key-command": "1.0.14", - "react-native-keyboard-controller": "1.21.0-beta.1", + "react-native-keyboard-controller": "^1.22.0", "react-native-localize": "^3.5.4", "react-native-nitro-modules": "0.35.0", "react-native-nitro-sqlite": "9.6.0", @@ -35781,9 +35781,9 @@ "license": "MIT" }, "node_modules/react-native-keyboard-controller": { - "version": "1.21.0-beta.1", - "resolved": "https://registry.npmjs.org/react-native-keyboard-controller/-/react-native-keyboard-controller-1.21.0-beta.1.tgz", - "integrity": "sha512-YoO4nCWRjgzwESAyt6p7tBVZshR+CwWRhNKuRXgHdyFeAuwmkmlN42b99o5NG2Bfb2Z0maw+RLowWSfkfNeV+Q==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/react-native-keyboard-controller/-/react-native-keyboard-controller-1.22.1.tgz", + "integrity": "sha512-U5koRfcFRQTVeGmPW7YS2kUU8oShT1UZm6VHkRlRP3tJjQewPLRZgP+kolYZX0QPvii4WvRpOwUYWEpqJOHx/w==", "license": "MIT", "dependencies": { "react-native-is-edge-to-edge": "^1.2.1" diff --git a/package.json b/package.json index 926b7bf7d239..66a084e75fde 100644 --- a/package.json +++ b/package.json @@ -192,7 +192,7 @@ "react-native-image-picker": "^7.1.2", "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#8a1c3b7359977462cdd4e63b09ea45afbd3d77c7", "react-native-key-command": "1.0.14", - "react-native-keyboard-controller": "1.21.0-beta.1", + "react-native-keyboard-controller": "^1.22.0", "react-native-localize": "^3.5.4", "react-native-nitro-modules": "0.35.0", "react-native-nitro-sqlite": "9.6.0", diff --git a/patches/react-native-keyboard-controller/details.md b/patches/react-native-keyboard-controller/details.md index c55b5f8d3f75..99aa8fc28212 100644 --- a/patches/react-native-keyboard-controller/details.md +++ b/patches/react-native-keyboard-controller/details.md @@ -1,6 +1,6 @@ # `react-native-keyboard-controller` patches -### [react-native-keyboard-controller+1.21.0-beta.1+001+fix-insets-in-landscape.patch](react-native-keyboard-controller+1.21.0-beta.1+001+fix-insets-in-landscape.patch) +### [react-native-keyboard-controller+1.22.1+001+fix-insets-in-landscape.patch](react-native-keyboard-controller+1.22.1+001+fix-insets-in-landscape.patch) - Reason: @@ -10,4 +10,4 @@ - Upstream PR/issue: - - E/App issue: https://github.com/Expensify/App/issues/87307 -- PR introducing patch: https://github.com/Expensify/App/pull/87376 \ No newline at end of file +- PR introducing patch: https://github.com/Expensify/App/pull/87376 diff --git a/patches/react-native-keyboard-controller/react-native-keyboard-controller+1.21.0-beta.1+001+fix-insets-in-landscape.patch b/patches/react-native-keyboard-controller/react-native-keyboard-controller+1.22.1+001+fix-insets-in-landscape.patch similarity index 69% rename from patches/react-native-keyboard-controller/react-native-keyboard-controller+1.21.0-beta.1+001+fix-insets-in-landscape.patch rename to patches/react-native-keyboard-controller/react-native-keyboard-controller+1.22.1+001+fix-insets-in-landscape.patch index b63ed87575eb..61927273cb9a 100644 --- a/patches/react-native-keyboard-controller/react-native-keyboard-controller+1.21.0-beta.1+001+fix-insets-in-landscape.patch +++ b/patches/react-native-keyboard-controller/react-native-keyboard-controller+1.22.1+001+fix-insets-in-landscape.patch @@ -1,28 +1,28 @@ diff --git a/node_modules/react-native-keyboard-controller/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt b/node_modules/react-native-keyboard-controller/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt -index 003890b..90d3375 100644 +index 3689418..a236663 100644 --- a/node_modules/react-native-keyboard-controller/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +++ b/node_modules/react-native-keyboard-controller/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt -@@ -116,13 +116,21 @@ class EdgeToEdgeReactViewGroup( - val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) +@@ -118,13 +118,21 @@ class EdgeToEdgeReactViewGroup( + if (!shouldApplyBottomPadding) 0 else insets.getInsets(WindowInsetsCompat.Type.ime()).bottom params.setMargins( - navBarInsets.left, -+ if (shouldApplyZeroPaddingBottom) { ++ if (this.isNavigationBarTranslucent) { + 0 + } else { + navBarInsets.left + }, - if (shouldApplyZeroPaddingTop) { + if (this.isStatusBarTranslucent) { 0 } else { systemBarInsets.top }, - navBarInsets.right, -+ if (shouldApplyZeroPaddingBottom) { ++ if (this.isNavigationBarTranslucent) { + 0 + } else { + navBarInsets.right + }, - if (shouldApplyZeroPaddingBottom) { - 0 + if (this.isNavigationBarTranslucent) { + keyboardInsets } else { diff --git a/src/components/ActionSheetAwareScrollView/__mocks__/index.android.tsx b/src/components/ActionSheetAwareScrollView/__mocks__/index.android.tsx index dd2e929205ae..36e887a7d312 100644 --- a/src/components/ActionSheetAwareScrollView/__mocks__/index.android.tsx +++ b/src/components/ActionSheetAwareScrollView/__mocks__/index.android.tsx @@ -1,5 +1,6 @@ import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollViewActions, useActionSheetAwareScrollViewState} from './ActionSheetAwareScrollViewContext'; const renderScrollComponent = undefined; +const renderInvertedScrollComponent = undefined; -export {renderScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; +export {renderScrollComponent, renderInvertedScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; diff --git a/src/components/ActionSheetAwareScrollView/__mocks__/index.ios.tsx b/src/components/ActionSheetAwareScrollView/__mocks__/index.ios.tsx index dd2e929205ae..36e887a7d312 100644 --- a/src/components/ActionSheetAwareScrollView/__mocks__/index.ios.tsx +++ b/src/components/ActionSheetAwareScrollView/__mocks__/index.ios.tsx @@ -1,5 +1,6 @@ import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollViewActions, useActionSheetAwareScrollViewState} from './ActionSheetAwareScrollViewContext'; const renderScrollComponent = undefined; +const renderInvertedScrollComponent = undefined; -export {renderScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; +export {renderScrollComponent, renderInvertedScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; diff --git a/src/components/ActionSheetAwareScrollView/__mocks__/index.tsx b/src/components/ActionSheetAwareScrollView/__mocks__/index.tsx index dd2e929205ae..36e887a7d312 100644 --- a/src/components/ActionSheetAwareScrollView/__mocks__/index.tsx +++ b/src/components/ActionSheetAwareScrollView/__mocks__/index.tsx @@ -1,5 +1,6 @@ import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollViewActions, useActionSheetAwareScrollViewState} from './ActionSheetAwareScrollViewContext'; const renderScrollComponent = undefined; +const renderInvertedScrollComponent = undefined; -export {renderScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; +export {renderScrollComponent, renderInvertedScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; diff --git a/src/components/ActionSheetAwareScrollView/index.android.tsx b/src/components/ActionSheetAwareScrollView/index.android.tsx index ea833305ead7..8ccabd8b48d5 100644 --- a/src/components/ActionSheetAwareScrollView/index.android.tsx +++ b/src/components/ActionSheetAwareScrollView/index.android.tsx @@ -1,12 +1,25 @@ import React from 'react'; +import {KeyboardChatScrollView} from 'react-native-keyboard-controller'; import Reanimated from 'react-native-reanimated'; -import type {ActionSheetAwareScrollViewProps, RenderActionSheetAwareScrollViewComponent} from './types'; +import type { + ActionSheetAwareKeyboardScrollViewProps, + ActionSheetAwareScrollViewProps, + RenderActionSheetAwareKeyboardScrollViewComponent, + RenderActionSheetAwareScrollViewComponent, +} from './types'; import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollViewActions, useActionSheetAwareScrollViewState} from './ActionSheetAwareScrollViewContext'; import useActionSheetAwareScrollViewRef from './useActionSheetAwareScrollViewRef'; import usePreventScrollOnKeyboardInteraction from './usePreventScrollOnKeyboardInteraction'; +const ReanimatedScrollView = React.forwardRef>((props, ref) => ( + +)); + function ActionSheetAwareScrollView({style, children, ref, ...restProps}: ActionSheetAwareScrollViewProps) { const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); @@ -23,6 +36,26 @@ function ActionSheetAwareScrollView({style, children, ref, ...restProps}: Action ); } +function ActionSheetAwareKeyboardScrollView({style, children, inverted, ref, ...restProps}: ActionSheetAwareKeyboardScrollViewProps) { + const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); + + usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); + + return ( + + {children} + + ); +} + /** * This function should be used as renderScrollComponent prop for FlatList * @param props - props that will be passed to the ScrollView from FlatList @@ -32,4 +65,13 @@ const renderScrollComponent: RenderActionSheetAwareScrollViewComponent = (props) return ; }; -export {renderScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; +const renderInvertedScrollComponent: RenderActionSheetAwareKeyboardScrollViewComponent = (props) => { + return ( + + ); +}; + +export {renderScrollComponent, renderInvertedScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; diff --git a/src/components/ActionSheetAwareScrollView/index.ios.tsx b/src/components/ActionSheetAwareScrollView/index.ios.tsx index a14eeb22d5fa..84104d915906 100644 --- a/src/components/ActionSheetAwareScrollView/index.ios.tsx +++ b/src/components/ActionSheetAwareScrollView/index.ios.tsx @@ -1,13 +1,28 @@ +import type {StyleProp, ViewStyle} from 'react-native'; + import React from 'react'; +import {KeyboardChatScrollView} from 'react-native-keyboard-controller'; import Reanimated, {useAnimatedStyle} from 'react-native-reanimated'; -import type {ActionSheetAwareScrollViewProps, RenderActionSheetAwareScrollViewComponent} from './types'; +import type { + ActionSheetAwareKeyboardScrollViewProps, + ActionSheetAwareScrollViewProps, + RenderActionSheetAwareKeyboardScrollViewComponent, + RenderActionSheetAwareScrollViewComponent, +} from './types'; import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollViewActions, useActionSheetAwareScrollViewState} from './ActionSheetAwareScrollViewContext'; import useActionSheetAwareScrollViewRef from './useActionSheetAwareScrollViewRef'; import useActionSheetKeyboardSpacing from './useActionSheetKeyboardSpacing'; import usePreventScrollOnKeyboardInteraction from './usePreventScrollOnKeyboardInteraction'; +const ReanimatedScrollView = React.forwardRef>((props, ref) => ( + +)); + function ActionSheetAwareScrollView({style, children, ref, ...restProps}: ActionSheetAwareScrollViewProps) { const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); @@ -29,6 +44,31 @@ function ActionSheetAwareScrollView({style, children, ref, ...restProps}: Action ); } +function ActionSheetAwareKeyboardScrollView({style, children, inverted, ref, ...restProps}: ActionSheetAwareKeyboardScrollViewProps) { + const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); + + const spacing = useActionSheetKeyboardSpacing(animatedRef); + const animatedStyle = useAnimatedStyle(() => ({ + paddingTop: spacing.get(), + })); + + usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); + + return ( + ]} + ScrollViewComponent={ReanimatedScrollView} + automaticallyAdjustContentInsets={false} + contentInsetAdjustmentBehavior="never" + inverted={inverted} + > + {children} + + ); +} + /** * This function should be used as renderScrollComponent prop for FlatList * @param props - props that will be passed to the ScrollView from FlatList @@ -38,4 +78,13 @@ const renderScrollComponent: RenderActionSheetAwareScrollViewComponent = (props) return ; }; -export {renderScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; +const renderInvertedScrollComponent: RenderActionSheetAwareKeyboardScrollViewComponent = (props) => { + return ( + + ); +}; + +export {renderScrollComponent, renderInvertedScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; diff --git a/src/components/ActionSheetAwareScrollView/index.tsx b/src/components/ActionSheetAwareScrollView/index.tsx index 818c7b48b751..4b43d06c8164 100644 --- a/src/components/ActionSheetAwareScrollView/index.tsx +++ b/src/components/ActionSheetAwareScrollView/index.tsx @@ -34,4 +34,6 @@ const renderScrollComponent: RenderActionSheetAwareScrollViewComponent = (props) return ; }; -export {renderScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; +const renderInvertedScrollComponent = renderScrollComponent; + +export {renderScrollComponent, renderInvertedScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; diff --git a/src/components/ActionSheetAwareScrollView/types.ts b/src/components/ActionSheetAwareScrollView/types.ts index 480dc8731b08..ff5ebe75c170 100644 --- a/src/components/ActionSheetAwareScrollView/types.ts +++ b/src/components/ActionSheetAwareScrollView/types.ts @@ -3,6 +3,7 @@ import type {ActionWithPayload, State} from '@hooks/useWorkletStateMachine'; import type {Ref} from 'react'; // eslint-disable-next-line no-restricted-imports import type {ScrollView, ScrollViewProps} from 'react-native'; +import type {KeyboardChatScrollViewProps} from 'react-native-keyboard-controller'; import type Reanimated from 'react-native-reanimated'; import type {SharedValue} from 'react-native-reanimated'; @@ -33,12 +34,17 @@ type ActionSheetAwareScrollViewProps = ScrollViewProps & { ref?: Ref; }; +type ActionSheetAwareKeyboardScrollViewProps = ActionSheetAwareScrollViewProps & Pick; + type RenderActionSheetAwareScrollViewComponent = (props: ActionSheetAwareScrollViewProps) => React.ReactElement; +type RenderActionSheetAwareKeyboardScrollViewComponent = (props: ActionSheetAwareKeyboardScrollViewProps) => React.ReactElement; export type { ActionSheetAwareScrollViewProps, + ActionSheetAwareKeyboardScrollViewProps, ActionSheetAwareScrollViewHandle, RenderActionSheetAwareScrollViewComponent, + RenderActionSheetAwareKeyboardScrollViewComponent, ActionSheetAwareScrollViewContextValue, ActionSheetAwareScrollViewStateContextValue, ActionSheetAwareScrollViewActionsContextValue, diff --git a/src/pages/inbox/report/ReportActionsList.tsx b/src/pages/inbox/report/ReportActionsList.tsx index 2a50b26e35c6..a3636e2aa080 100644 --- a/src/pages/inbox/report/ReportActionsList.tsx +++ b/src/pages/inbox/report/ReportActionsList.tsx @@ -1,4 +1,4 @@ -import {renderScrollComponent as renderActionSheetAwareScrollView} from '@components/ActionSheetAwareScrollView'; +import {renderInvertedScrollComponent as renderActionSheetAwareScrollView} from '@components/ActionSheetAwareScrollView'; import InvertedFlashList from '@components/FlashList/InvertedFlashList'; import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView'; From b7657e795bd03b8bd04ff364a5e00468fc3a5dc2 Mon Sep 17 00:00:00 2001 From: chrispader Date: Wed, 15 Jul 2026 10:24:40 +0200 Subject: [PATCH 2/9] Update action sheet scroll handling for keyboard controller 1.22 --- .../index.android.tsx | 10 ++-------- .../ActionSheetAwareScrollView/index.ios.tsx | 19 +++---------------- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/components/ActionSheetAwareScrollView/index.android.tsx b/src/components/ActionSheetAwareScrollView/index.android.tsx index 8ccabd8b48d5..bbbddefb6b2f 100644 --- a/src/components/ActionSheetAwareScrollView/index.android.tsx +++ b/src/components/ActionSheetAwareScrollView/index.android.tsx @@ -13,13 +13,6 @@ import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollVi import useActionSheetAwareScrollViewRef from './useActionSheetAwareScrollViewRef'; import usePreventScrollOnKeyboardInteraction from './usePreventScrollOnKeyboardInteraction'; -const ReanimatedScrollView = React.forwardRef>((props, ref) => ( - -)); - function ActionSheetAwareScrollView({style, children, ref, ...restProps}: ActionSheetAwareScrollViewProps) { const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); @@ -46,10 +39,11 @@ function ActionSheetAwareKeyboardScrollView({style, children, inverted, ref, ... {...restProps} ref={onRef} style={style} - ScrollViewComponent={ReanimatedScrollView} automaticallyAdjustContentInsets={false} contentInsetAdjustmentBehavior="never" inverted={inverted} + keyboardDismissMode="interactive" + keyboardLiftBehavior="never" > {children} diff --git a/src/components/ActionSheetAwareScrollView/index.ios.tsx b/src/components/ActionSheetAwareScrollView/index.ios.tsx index 84104d915906..a4c7e98b335d 100644 --- a/src/components/ActionSheetAwareScrollView/index.ios.tsx +++ b/src/components/ActionSheetAwareScrollView/index.ios.tsx @@ -1,5 +1,3 @@ -import type {StyleProp, ViewStyle} from 'react-native'; - import React from 'react'; import {KeyboardChatScrollView} from 'react-native-keyboard-controller'; import Reanimated, {useAnimatedStyle} from 'react-native-reanimated'; @@ -16,13 +14,6 @@ import useActionSheetAwareScrollViewRef from './useActionSheetAwareScrollViewRef import useActionSheetKeyboardSpacing from './useActionSheetKeyboardSpacing'; import usePreventScrollOnKeyboardInteraction from './usePreventScrollOnKeyboardInteraction'; -const ReanimatedScrollView = React.forwardRef>((props, ref) => ( - -)); - function ActionSheetAwareScrollView({style, children, ref, ...restProps}: ActionSheetAwareScrollViewProps) { const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); @@ -47,22 +38,18 @@ function ActionSheetAwareScrollView({style, children, ref, ...restProps}: Action function ActionSheetAwareKeyboardScrollView({style, children, inverted, ref, ...restProps}: ActionSheetAwareKeyboardScrollViewProps) { const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); - const spacing = useActionSheetKeyboardSpacing(animatedRef); - const animatedStyle = useAnimatedStyle(() => ({ - paddingTop: spacing.get(), - })); - usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); return ( ]} - ScrollViewComponent={ReanimatedScrollView} + style={style} automaticallyAdjustContentInsets={false} contentInsetAdjustmentBehavior="never" inverted={inverted} + keyboardDismissMode="interactive" + keyboardLiftBehavior="never" > {children} From 91a647a68f6f86d20ba1984b7c48b0463bcf440a Mon Sep 17 00:00:00 2001 From: chrispader Date: Wed, 15 Jul 2026 12:57:24 +0200 Subject: [PATCH 3/9] refactor: integrate `KeyboardChatScrollView` into `ActionSheetAwareScrollView` --- .../index.android.tsx | 26 ++++ .../index.ios.tsx | 34 +++++ .../index.tsx | 23 ++++ .../types.ts | 7 + .../index.android.tsx | 71 ---------- .../ActionSheetAwareScrollView/index.ios.tsx | 77 ----------- .../ActionSheetAwareScrollView/index.tsx | 44 +++--- .../ActionSheetAwareScrollView/types.ts | 9 +- src/pages/inbox/ReportScreen.tsx | 126 ++++++++++-------- 9 files changed, 178 insertions(+), 239 deletions(-) create mode 100644 src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.android.tsx create mode 100644 src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.ios.tsx create mode 100644 src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.tsx create mode 100644 src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/types.ts delete mode 100644 src/components/ActionSheetAwareScrollView/index.android.tsx delete mode 100644 src/components/ActionSheetAwareScrollView/index.ios.tsx diff --git a/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.android.tsx b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.android.tsx new file mode 100644 index 000000000000..4ea1191483ac --- /dev/null +++ b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.android.tsx @@ -0,0 +1,26 @@ +import useActionSheetAwareScrollViewRef from '@components/ActionSheetAwareScrollView/useActionSheetAwareScrollViewRef'; + +import React from 'react'; +import {KeyboardChatScrollView} from 'react-native-keyboard-controller'; + +import type AnimatedActionSheetAwareScrollViewProps from './types'; + +function AnimatedActionSheetAwareScrollView({children, ref, ...restProps}: AnimatedActionSheetAwareScrollViewProps) { + const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); + + // usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); + + return ( + + {children} + + ); +} + +export default AnimatedActionSheetAwareScrollView; diff --git a/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.ios.tsx b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.ios.tsx new file mode 100644 index 000000000000..1ea1d9baac0f --- /dev/null +++ b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.ios.tsx @@ -0,0 +1,34 @@ +import useActionSheetAwareScrollViewRef from '@components/ActionSheetAwareScrollView/useActionSheetAwareScrollViewRef'; +import useActionSheetKeyboardSpacing from '@components/ActionSheetAwareScrollView/useActionSheetKeyboardSpacing'; +import usePreventScrollOnKeyboardInteraction from '@components/ActionSheetAwareScrollView/usePreventScrollOnKeyboardInteraction'; + +import React from 'react'; +import {KeyboardChatScrollView} from 'react-native-keyboard-controller'; +import {useAnimatedStyle} from 'react-native-reanimated'; + +import type AnimatedActionSheetAwareScrollViewProps from './types'; + +function AnimatedActionSheetAwareScrollView({children, style, ref, ...restProps}: AnimatedActionSheetAwareScrollViewProps) { + const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); + + const spacing = useActionSheetKeyboardSpacing(animatedRef); + const animatedStyle = useAnimatedStyle(() => ({ + paddingTop: spacing.get(), + })); + // usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); + + return ( + + {children} + + ); +} + +export default AnimatedActionSheetAwareScrollView; diff --git a/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.tsx b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.tsx new file mode 100644 index 000000000000..5adf40a41c16 --- /dev/null +++ b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.tsx @@ -0,0 +1,23 @@ +import useActionSheetAwareScrollViewRef from '@components/ActionSheetAwareScrollView/useActionSheetAwareScrollViewRef'; + +// The action sheet is only used on native platforms (iOS and Android) +// On all other platforms, the action sheet is implemented using the Animated.ScrollView +import React from 'react'; +import Reanimated from 'react-native-reanimated'; + +import type AnimatedActionSheetAwareScrollViewProps from './types'; + +function AnimatedActionSheetAwareScrollView({children, ref, ...restProps}: AnimatedActionSheetAwareScrollViewProps) { + const {onRef} = useActionSheetAwareScrollViewRef(ref); + + return ( + + {children} + + ); +} + +export default AnimatedActionSheetAwareScrollView; diff --git a/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/types.ts b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/types.ts new file mode 100644 index 000000000000..cde046e2d614 --- /dev/null +++ b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/types.ts @@ -0,0 +1,7 @@ +import type {ActionSheetAwareScrollViewProps} from '@components/ActionSheetAwareScrollView/types'; + +import type {KeyboardChatScrollViewProps} from 'react-native-keyboard-controller'; + +type AnimatedActionSheetAwareScrollViewProps = ActionSheetAwareScrollViewProps & Pick; + +export default AnimatedActionSheetAwareScrollViewProps; diff --git a/src/components/ActionSheetAwareScrollView/index.android.tsx b/src/components/ActionSheetAwareScrollView/index.android.tsx deleted file mode 100644 index bbbddefb6b2f..000000000000 --- a/src/components/ActionSheetAwareScrollView/index.android.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react'; -import {KeyboardChatScrollView} from 'react-native-keyboard-controller'; -import Reanimated from 'react-native-reanimated'; - -import type { - ActionSheetAwareKeyboardScrollViewProps, - ActionSheetAwareScrollViewProps, - RenderActionSheetAwareKeyboardScrollViewComponent, - RenderActionSheetAwareScrollViewComponent, -} from './types'; - -import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollViewActions, useActionSheetAwareScrollViewState} from './ActionSheetAwareScrollViewContext'; -import useActionSheetAwareScrollViewRef from './useActionSheetAwareScrollViewRef'; -import usePreventScrollOnKeyboardInteraction from './usePreventScrollOnKeyboardInteraction'; - -function ActionSheetAwareScrollView({style, children, ref, ...restProps}: ActionSheetAwareScrollViewProps) { - const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); - - usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); - - return ( - - {children} - - ); -} - -function ActionSheetAwareKeyboardScrollView({style, children, inverted, ref, ...restProps}: ActionSheetAwareKeyboardScrollViewProps) { - const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); - - usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); - - return ( - - {children} - - ); -} - -/** - * This function should be used as renderScrollComponent prop for FlatList - * @param props - props that will be passed to the ScrollView from FlatList - * @returns - ActionSheetAwareScrollView - */ -const renderScrollComponent: RenderActionSheetAwareScrollViewComponent = (props) => { - return ; -}; - -const renderInvertedScrollComponent: RenderActionSheetAwareKeyboardScrollViewComponent = (props) => { - return ( - - ); -}; - -export {renderScrollComponent, renderInvertedScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; diff --git a/src/components/ActionSheetAwareScrollView/index.ios.tsx b/src/components/ActionSheetAwareScrollView/index.ios.tsx deleted file mode 100644 index a4c7e98b335d..000000000000 --- a/src/components/ActionSheetAwareScrollView/index.ios.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from 'react'; -import {KeyboardChatScrollView} from 'react-native-keyboard-controller'; -import Reanimated, {useAnimatedStyle} from 'react-native-reanimated'; - -import type { - ActionSheetAwareKeyboardScrollViewProps, - ActionSheetAwareScrollViewProps, - RenderActionSheetAwareKeyboardScrollViewComponent, - RenderActionSheetAwareScrollViewComponent, -} from './types'; - -import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollViewActions, useActionSheetAwareScrollViewState} from './ActionSheetAwareScrollViewContext'; -import useActionSheetAwareScrollViewRef from './useActionSheetAwareScrollViewRef'; -import useActionSheetKeyboardSpacing from './useActionSheetKeyboardSpacing'; -import usePreventScrollOnKeyboardInteraction from './usePreventScrollOnKeyboardInteraction'; - -function ActionSheetAwareScrollView({style, children, ref, ...restProps}: ActionSheetAwareScrollViewProps) { - const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); - - const spacing = useActionSheetKeyboardSpacing(animatedRef); - const animatedStyle = useAnimatedStyle(() => ({ - paddingTop: spacing.get(), - })); - - usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); - - return ( - - {children} - - ); -} - -function ActionSheetAwareKeyboardScrollView({style, children, inverted, ref, ...restProps}: ActionSheetAwareKeyboardScrollViewProps) { - const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); - - usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); - - return ( - - {children} - - ); -} - -/** - * This function should be used as renderScrollComponent prop for FlatList - * @param props - props that will be passed to the ScrollView from FlatList - * @returns - ActionSheetAwareScrollView - */ -const renderScrollComponent: RenderActionSheetAwareScrollViewComponent = (props) => { - return ; -}; - -const renderInvertedScrollComponent: RenderActionSheetAwareKeyboardScrollViewComponent = (props) => { - return ( - - ); -}; - -export {renderScrollComponent, renderInvertedScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; diff --git a/src/components/ActionSheetAwareScrollView/index.tsx b/src/components/ActionSheetAwareScrollView/index.tsx index 4b43d06c8164..63d89024013d 100644 --- a/src/components/ActionSheetAwareScrollView/index.tsx +++ b/src/components/ActionSheetAwareScrollView/index.tsx @@ -1,39 +1,31 @@ -// The action sheet is only used on native platforms (iOS and Android) -// On all other platforms, the action sheet is implemented using the Animated.ScrollView import React from 'react'; -import Reanimated from 'react-native-reanimated'; -import type {ActionSheetAwareScrollViewProps, RenderActionSheetAwareScrollViewComponent} from './types'; +import type {RenderActionSheetAwareScrollViewComponent} from './types'; import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollViewActions, useActionSheetAwareScrollViewState} from './ActionSheetAwareScrollViewContext'; -import useActionSheetAwareScrollViewRef from './useActionSheetAwareScrollViewRef'; - -function ActionSheetAwareScrollView({children, ref, ...restProps}: ActionSheetAwareScrollViewProps) { - const {onRef} = useActionSheetAwareScrollViewRef(ref); - - return ( - - {children} - - ); -} +import AnimatedActionSheetAwareScrollView from './AnimatedActionSheetAwareScrollView'; /** - * The bottom spacing config for this action sheet is only used on Android and iOS. On other platforms, - * this component will be a default Reanimated.ScrollView, because the onScroll handler used is from Reanimated. - * * This function should be used as renderScrollComponent prop for FlatList - * @param {Object} props - props that will be passed to the ScrollView from FlatList - * @returns {React.ReactElement} - ActionSheetAwareScrollView + * @param props - props that will be passed to the ScrollView from FlatList + * @returns - ActionSheetAwareScrollView */ - const renderScrollComponent: RenderActionSheetAwareScrollViewComponent = (props) => { - return ; + return ; }; -const renderInvertedScrollComponent = renderScrollComponent; +/** + * This function should be used as renderScrollComponent prop for FlatList + * @param props - props that will be passed to the ScrollView from FlatList + * @returns - ActionSheetAwareScrollView + */ +const renderInvertedScrollComponent: RenderActionSheetAwareScrollViewComponent = (props) => { + return ( + + ); +}; export {renderScrollComponent, renderInvertedScrollComponent, ActionSheetAwareScrollViewProvider, Actions, useActionSheetAwareScrollViewState, useActionSheetAwareScrollViewActions}; diff --git a/src/components/ActionSheetAwareScrollView/types.ts b/src/components/ActionSheetAwareScrollView/types.ts index ff5ebe75c170..70631dd058ee 100644 --- a/src/components/ActionSheetAwareScrollView/types.ts +++ b/src/components/ActionSheetAwareScrollView/types.ts @@ -3,7 +3,6 @@ import type {ActionWithPayload, State} from '@hooks/useWorkletStateMachine'; import type {Ref} from 'react'; // eslint-disable-next-line no-restricted-imports import type {ScrollView, ScrollViewProps} from 'react-native'; -import type {KeyboardChatScrollViewProps} from 'react-native-keyboard-controller'; import type Reanimated from 'react-native-reanimated'; import type {SharedValue} from 'react-native-reanimated'; @@ -34,17 +33,15 @@ type ActionSheetAwareScrollViewProps = ScrollViewProps & { ref?: Ref; }; -type ActionSheetAwareKeyboardScrollViewProps = ActionSheetAwareScrollViewProps & Pick; +type ActionSheetAwareScrollViewElement = React.ReactElement; -type RenderActionSheetAwareScrollViewComponent = (props: ActionSheetAwareScrollViewProps) => React.ReactElement; -type RenderActionSheetAwareKeyboardScrollViewComponent = (props: ActionSheetAwareKeyboardScrollViewProps) => React.ReactElement; +type RenderActionSheetAwareScrollViewComponent = (props: ActionSheetAwareScrollViewProps) => ActionSheetAwareScrollViewElement; export type { ActionSheetAwareScrollViewProps, - ActionSheetAwareKeyboardScrollViewProps, ActionSheetAwareScrollViewHandle, + ActionSheetAwareScrollViewElement, RenderActionSheetAwareScrollViewComponent, - RenderActionSheetAwareKeyboardScrollViewComponent, ActionSheetAwareScrollViewContextValue, ActionSheetAwareScrollViewStateContextValue, ActionSheetAwareScrollViewActionsContextValue, diff --git a/src/pages/inbox/ReportScreen.tsx b/src/pages/inbox/ReportScreen.tsx index 62f3d3f86171..0cc345fea66b 100644 --- a/src/pages/inbox/ReportScreen.tsx +++ b/src/pages/inbox/ReportScreen.tsx @@ -108,65 +108,73 @@ function ReportScreen({route, navigation}: ReportScreenProps) { useClearReportActionDraftsOnReportChange(reportIDFromRoute); return ( - - - - - - {!shouldDeferNonEssentials && ( - <> - - - - - - )} - - - - {!shouldDeferNonEssentials && } - - - {!shouldDeferNonEssentials && } - - - - {!shouldDeferNonEssentials && } - - - - - {shouldDeferNonEssentials ? : } - - - - - - - - - - - - - - + + + + + + + {!shouldDeferNonEssentials && ( + <> + + + + + + )} + + + + {!shouldDeferNonEssentials && } + + + {!shouldDeferNonEssentials && } + + + + {!shouldDeferNonEssentials && } + + + + + {shouldDeferNonEssentials ? : } + + + + + + + + + + + + + + + ); } From f96af77a7bb717cb54ac7d2ff23f2f0ed868ff60 Mon Sep 17 00:00:00 2001 From: chrispader Date: Wed, 15 Jul 2026 15:12:14 +0200 Subject: [PATCH 4/9] refactor: remove SwipeableView --- src/components/SwipeableView/index.native.tsx | 37 ------------------- src/components/SwipeableView/index.tsx | 4 -- src/components/SwipeableView/types.ts | 15 -------- src/pages/inbox/report/ReportFooter.tsx | 10 +---- 4 files changed, 2 insertions(+), 64 deletions(-) delete mode 100644 src/components/SwipeableView/index.native.tsx delete mode 100644 src/components/SwipeableView/index.tsx delete mode 100644 src/components/SwipeableView/types.ts diff --git a/src/components/SwipeableView/index.native.tsx b/src/components/SwipeableView/index.native.tsx deleted file mode 100644 index b1e8ea0dbce0..000000000000 --- a/src/components/SwipeableView/index.native.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import CONST from '@src/CONST'; - -import React, {useRef} from 'react'; -import {PanResponder, View} from 'react-native'; - -import type SwipeableViewProps from './types'; - -function SwipeableView({children, onSwipeDown, style}: SwipeableViewProps) { - const minimumPixelDistance = CONST.COMPOSER_MAX_HEIGHT; - const oldYRef = useRef(0); - const panResponder = useRef( - PanResponder.create({ - // The PanResponder gets focus only when the y-axis movement is over minimumPixelDistance & swipe direction is downwards - onMoveShouldSetPanResponderCapture: (_event, gestureState) => { - if (gestureState.dy - oldYRef.current > 0 && gestureState.dy > minimumPixelDistance) { - return true; - } - oldYRef.current = gestureState.dy; - return false; - }, - - // Calls the callback when the swipe down is released; after the completion of the gesture - onPanResponderRelease: onSwipeDown, - }), - ).current; - - return ( - - {children} - - ); -} - -export default SwipeableView; diff --git a/src/components/SwipeableView/index.tsx b/src/components/SwipeableView/index.tsx deleted file mode 100644 index d3881d2efd21..000000000000 --- a/src/components/SwipeableView/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import type SwipeableViewProps from './types'; - -// Swipeable View is available just on Android/iOS for now. -export default ({children}: SwipeableViewProps) => children; diff --git a/src/components/SwipeableView/types.ts b/src/components/SwipeableView/types.ts deleted file mode 100644 index b6a4f11ed8d0..000000000000 --- a/src/components/SwipeableView/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type {ReactNode} from 'react'; -import type {StyleProp, ViewStyle} from 'react-native'; - -type SwipeableViewProps = { - /** The content to be rendered within the SwipeableView */ - children: ReactNode; - - /** Callback to fire when the user swipes down on the child content */ - onSwipeDown: () => void; - - /** Additional styles applied to the wrapping view */ - style?: StyleProp; -}; - -export default SwipeableViewProps; diff --git a/src/pages/inbox/report/ReportFooter.tsx b/src/pages/inbox/report/ReportFooter.tsx index 148e628fd918..47c42ebeed09 100644 --- a/src/pages/inbox/report/ReportFooter.tsx +++ b/src/pages/inbox/report/ReportFooter.tsx @@ -99,11 +99,7 @@ function ReportFooter() { // Happy path — user can compose if (!shouldHideComposer) { - const composer = ( - - - - ); + const composer = ; return ( {shouldShowEnableNotificationsBanner ? ( @@ -182,9 +178,7 @@ function ReportFooter() { {isEditingWithComposer && ( - - - + )} Date: Wed, 15 Jul 2026 18:33:51 +0200 Subject: [PATCH 5/9] Update Podfile.lock --- ios/Podfile.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 58f1e7dcf7eb..0ad07f7379a0 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2612,7 +2612,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-keyboard-controller (1.21.0-beta.1): + - react-native-keyboard-controller (1.22.1): - boost - DoubleConversion - fast_float @@ -2630,7 +2630,7 @@ PODS: - React-graphics - React-ImageManager - React-jsi - - react-native-keyboard-controller/common (= 1.21.0-beta.1) + - react-native-keyboard-controller/common (= 1.22.1) - React-NativeModulesApple - React-RCTFabric - React-renderercss @@ -2641,7 +2641,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-keyboard-controller/common (1.21.0-beta.1): + - react-native-keyboard-controller/common (1.22.1): - boost - DoubleConversion - fast_float @@ -4901,7 +4901,7 @@ SPEC CHECKSUMS: react-native-document-picker: 18a9d68e6117d37ac5facd87619cbc3ff17575a7 react-native-image-picker: 1722f5d3dc5de5039d423e290dc31a717ba9605e react-native-key-command: 7538df85ed26502b2a929c0584235459b26c7a91 - react-native-keyboard-controller: 0619a578e4d79a38dc4b1bef3b89cee6525bc1c7 + react-native-keyboard-controller: 1fe3fcd7cc26a549e72e733905cf1131dc478948 react-native-netinfo: f94b3a0fc305e812f3f615989d99299d7110c2ae react-native-pager-view: c62ab82db28e2d11e7809c59085e2984a45979c5 react-native-pdf: 6a09a9be0e7ee954ea671437483316f9a28f8572 From 8bcde4e135a099e2dbf4cd2629dcc465899ad21f Mon Sep 17 00:00:00 2001 From: chrispader Date: Thu, 16 Jul 2026 19:30:56 +0200 Subject: [PATCH 6/9] feat: adjust report footer to enable interactive keyboard dismissal --- .../index.android.tsx | 10 +++--- .../index.ios.tsx | 11 +++---- .../usePreventScrollOnKeyboardInteraction.ts | 30 ------------------ .../KeyboardDismissibleFlatListContext.tsx | 10 +++++- .../KeyboardDismissibleFlatList/types.ts | 3 ++ src/pages/inbox/ReportScreen.tsx | 30 +++++++++++++----- src/pages/inbox/report/ReportFooter.tsx | 31 ++++++++++++------- src/styles/index.ts | 1 + 8 files changed, 65 insertions(+), 61 deletions(-) delete mode 100644 src/components/ActionSheetAwareScrollView/usePreventScrollOnKeyboardInteraction.ts diff --git a/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.android.tsx b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.android.tsx index 4ea1191483ac..a802a038f1d6 100644 --- a/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.android.tsx +++ b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.android.tsx @@ -1,21 +1,21 @@ import useActionSheetAwareScrollViewRef from '@components/ActionSheetAwareScrollView/useActionSheetAwareScrollViewRef'; +import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings'; + import React from 'react'; import {KeyboardChatScrollView} from 'react-native-keyboard-controller'; import type AnimatedActionSheetAwareScrollViewProps from './types'; function AnimatedActionSheetAwareScrollView({children, ref, ...restProps}: AnimatedActionSheetAwareScrollViewProps) { - const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); - - // usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); + const {onRef} = useActionSheetAwareScrollViewRef(ref); + const safeAreaPaddings = useSafeAreaPaddings(); return ( {children} diff --git a/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.ios.tsx b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.ios.tsx index 1ea1d9baac0f..21b0f20cb56d 100644 --- a/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.ios.tsx +++ b/src/components/ActionSheetAwareScrollView/AnimatedActionSheetAwareScrollView/index.ios.tsx @@ -1,6 +1,7 @@ import useActionSheetAwareScrollViewRef from '@components/ActionSheetAwareScrollView/useActionSheetAwareScrollViewRef'; import useActionSheetKeyboardSpacing from '@components/ActionSheetAwareScrollView/useActionSheetKeyboardSpacing'; -import usePreventScrollOnKeyboardInteraction from '@components/ActionSheetAwareScrollView/usePreventScrollOnKeyboardInteraction'; + +import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings'; import React from 'react'; import {KeyboardChatScrollView} from 'react-native-keyboard-controller'; @@ -11,19 +12,17 @@ import type AnimatedActionSheetAwareScrollViewProps from './types'; function AnimatedActionSheetAwareScrollView({children, style, ref, ...restProps}: AnimatedActionSheetAwareScrollViewProps) { const {onRef, animatedRef} = useActionSheetAwareScrollViewRef(ref); + const safeAreaPaddings = useSafeAreaPaddings(); const spacing = useActionSheetKeyboardSpacing(animatedRef); const animatedStyle = useAnimatedStyle(() => ({ paddingTop: spacing.get(), })); - // usePreventScrollOnKeyboardInteraction({scrollViewRef: animatedRef}); - return ( {children} diff --git a/src/components/ActionSheetAwareScrollView/usePreventScrollOnKeyboardInteraction.ts b/src/components/ActionSheetAwareScrollView/usePreventScrollOnKeyboardInteraction.ts deleted file mode 100644 index 4fa6ed2c466f..000000000000 --- a/src/components/ActionSheetAwareScrollView/usePreventScrollOnKeyboardInteraction.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type {AnimatedRef} from 'react-native-reanimated'; -import type Reanimated from 'react-native-reanimated'; - -import {useKeyboardHandler} from 'react-native-keyboard-controller'; -import {scrollTo, useScrollOffset} from 'react-native-reanimated'; - -type UsePreventScrollOnKeyboardInteractionProps = { - scrollViewRef: AnimatedRef; - enabled?: boolean; -}; - -function usePreventScrollOnKeyboardInteraction({scrollViewRef, enabled = false}: UsePreventScrollOnKeyboardInteractionProps) { - const scrollOffset = useScrollOffset(scrollViewRef); - - // Scroll to the latest scroll position whenever the keyboard is interacted with, - // to prevent additional scrolling when the keyboard is interactively dismissed. - useKeyboardHandler({ - onInteractive: () => { - 'worklet'; - - if (!enabled) { - return; - } - - scrollTo(scrollViewRef, 0, scrollOffset.get(), false); - }, - }); -} - -export default usePreventScrollOnKeyboardInteraction; diff --git a/src/components/KeyboardDismissibleFlatList/KeyboardDismissibleFlatListContext.tsx b/src/components/KeyboardDismissibleFlatList/KeyboardDismissibleFlatListContext.tsx index 6a7d2354fa2a..70e001ba53f5 100644 --- a/src/components/KeyboardDismissibleFlatList/KeyboardDismissibleFlatListContext.tsx +++ b/src/components/KeyboardDismissibleFlatList/KeyboardDismissibleFlatListContext.tsx @@ -5,6 +5,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import createDummySharedValue from '@src/utils/createDummySharedValue'; import type {PropsWithChildren} from 'react'; +import type {LayoutChangeEvent} from 'react-native'; import React, {createContext, useContext, useState} from 'react'; import {useKeyboardHandler} from 'react-native-keyboard-controller'; @@ -13,6 +14,7 @@ import {useAnimatedScrollHandler, useSharedValue} from 'react-native-reanimated' import type {KeyboardDismissibleFlatListActionsContextValue, KeyboardDismissibleFlatListStateContextValue, ListBehavior} from './types'; const defaultStateValue: KeyboardDismissibleFlatListStateContextValue = { + composerHeight: 0, keyboardHeight: createDummySharedValue(0), keyboardOffset: createDummySharedValue(0), scrollY: createDummySharedValue(0), @@ -23,6 +25,7 @@ const defaultStateValue: KeyboardDismissibleFlatListStateContextValue = { const defaultActionsValue: KeyboardDismissibleFlatListActionsContextValue = { onScroll: () => {}, setListBehavior: () => {}, + onComposerLayout: () => {}, }; const KeyboardDismissibleFlatListStateContext = createContext(defaultStateValue); @@ -35,6 +38,10 @@ function KeyboardDismissibleFlatListContextProvider({children}: PropsWithChildre const [listBehavior, setListBehavior] = useState(CONST.LIST_BEHAVIOR.INVERTED); + const [composerHeight, setComposerHeight] = useState(CONST.CHAT_FOOTER_MIN_HEIGHT); + + const onComposerLayout = (e: LayoutChangeEvent) => setComposerHeight(e.nativeEvent.layout.height); + const height = useSharedValue(0); const offset = useSharedValue(0); const scrollY = useSharedValue(0); @@ -125,6 +132,7 @@ function KeyboardDismissibleFlatListContextProvider({children}: PropsWithChildre // Because of the React Compiler we don't need to memoize it manually // eslint-disable-next-line react/jsx-no-constructed-context-values const stateValue: KeyboardDismissibleFlatListStateContextValue = { + composerHeight, keyboardHeight: height, keyboardOffset: offset, scrollY, @@ -134,7 +142,7 @@ function KeyboardDismissibleFlatListContextProvider({children}: PropsWithChildre // Because of the React Compiler we don't need to memoize it manually // eslint-disable-next-line react/jsx-no-constructed-context-values - const actionsValue: KeyboardDismissibleFlatListActionsContextValue = {onScroll, setListBehavior}; + const actionsValue: KeyboardDismissibleFlatListActionsContextValue = {onScroll, setListBehavior, onComposerLayout}; return ( diff --git a/src/components/KeyboardDismissibleFlatList/types.ts b/src/components/KeyboardDismissibleFlatList/types.ts index 806e8ce68952..0b61a25a8f20 100644 --- a/src/components/KeyboardDismissibleFlatList/types.ts +++ b/src/components/KeyboardDismissibleFlatList/types.ts @@ -1,11 +1,13 @@ import type CONST from '@src/CONST'; +import type {LayoutChangeEvent} from 'react-native'; import type {ScrollHandlerProcessed, SharedValue} from 'react-native-reanimated'; import type {ValueOf} from 'type-fest'; type ListBehavior = ValueOf; type KeyboardDismissibleFlatListStateContextValue = { + composerHeight: number; keyboardHeight: SharedValue; keyboardOffset: SharedValue; contentSizeHeight: SharedValue; @@ -16,6 +18,7 @@ type KeyboardDismissibleFlatListStateContextValue = { type KeyboardDismissibleFlatListActionsContextValue = { onScroll: ScrollHandlerProcessed>; setListBehavior: React.Dispatch>; + onComposerLayout: (e: LayoutChangeEvent) => void; }; type KeyboardDismissibleFlatListContextValue = KeyboardDismissibleFlatListStateContextValue & KeyboardDismissibleFlatListActionsContextValue; diff --git a/src/pages/inbox/ReportScreen.tsx b/src/pages/inbox/ReportScreen.tsx index 0cc345fea66b..e025a6d4d5ce 100644 --- a/src/pages/inbox/ReportScreen.tsx +++ b/src/pages/inbox/ReportScreen.tsx @@ -1,11 +1,12 @@ import CollapsibleHeaderOnKeyboard from '@components/CollapsibleHeaderOnKeyboard'; +import {useKeyboardDismissibleFlatListActions, useKeyboardDismissibleFlatListState} from '@components/KeyboardDismissibleFlatList/KeyboardDismissibleFlatListContext'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; import WideRHPOverlayWrapper from '@components/WideRHPOverlayWrapper'; import {useCurrentReportIDState} from '@hooks/useCurrentReportID'; import useOnyx from '@hooks/useOnyx'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings'; import useSubmitToDestinationVisible from '@hooks/useSubmitToDestinationVisible'; import useThemeStyles from '@hooks/useThemeStyles'; import useViewportOffsetTop from '@hooks/useViewportOffsetTop'; @@ -24,6 +25,7 @@ import type {ViewStyle} from 'react-native'; import {PortalHost} from '@gorhom/portal'; import React from 'react'; import {View} from 'react-native'; +import {KeyboardGestureArea, KeyboardStickyView} from 'react-native-keyboard-controller'; import type ReportScreenNavigationProps from './types'; @@ -75,11 +77,15 @@ function ReportScreenEditMessageProvider({reportID, children}: ReportScreenEditM function ReportScreen({route, navigation}: ReportScreenProps) { const styles = useThemeStyles(); const reportIDFromRoute = getNonEmptyStringOnyxID(route.params?.reportID); - const {isInNarrowPaneModal} = useResponsiveLayout(); - const {currentReportID: currentReportIDValue} = useCurrentReportIDState(); const viewportOffsetTop = useViewportOffsetTop(); - const isTopMostReportId = currentReportIDValue === reportIDFromRoute; const screenWrapperStyle: ViewStyle[] = [styles.appContent, styles.flex1, {marginTop: viewportOffsetTop}]; + const safeAreaPaddings = useSafeAreaPaddings(); + const {composerHeight} = useKeyboardDismissibleFlatListState(); + const {onComposerLayout} = useKeyboardDismissibleFlatListActions(); + + const keyboardGestureAreaOffset = composerHeight - safeAreaPaddings.paddingBottom; + + const [isComposerFullSize = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportIDFromRoute}`); const shouldDeferNonEssentials = useDeferNonEssentials(reportIDFromRoute); @@ -110,10 +116,10 @@ function ReportScreen({route, navigation}: ReportScreenProps) { return ( @@ -122,7 +128,10 @@ function ReportScreen({route, navigation}: ReportScreenProps) { {!shouldDeferNonEssentials && ( @@ -159,7 +168,12 @@ function ReportScreen({route, navigation}: ReportScreenProps) { testID="report-actions-view-wrapper" > - {shouldDeferNonEssentials ? : } + + {shouldDeferNonEssentials ? : } + diff --git a/src/pages/inbox/report/ReportFooter.tsx b/src/pages/inbox/report/ReportFooter.tsx index 47c42ebeed09..921986807d72 100644 --- a/src/pages/inbox/report/ReportFooter.tsx +++ b/src/pages/inbox/report/ReportFooter.tsx @@ -3,8 +3,8 @@ import ArchivedReportFooter from '@components/ArchivedReportFooter'; import Banner from '@components/Banner'; import BlockedReportFooter from '@components/BlockedReportFooter'; import OfflineIndicator from '@components/OfflineIndicator'; -import SwipeableView from '@components/SwipeableView'; +import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle'; import useIsAnonymousUser from '@hooks/useIsAnonymousUser'; import useIsReportReadyToDisplay from '@hooks/useIsReportReadyToDisplay'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; @@ -35,7 +35,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import {useRoute} from '@react-navigation/native'; import {isBlockedFromChatSelector} from '@selectors/BlockedFromChat'; import React from 'react'; -import {Keyboard, View} from 'react-native'; +import {View} from 'react-native'; import EnableNotificationsBanner, {BANNER_COMPOSER_OVERLAP_PX} from './EnableNotificationsBanner'; import ReportActionCompose from './ReportActionCompose/ReportActionCompose'; @@ -52,6 +52,17 @@ const composerOverlapStyle = {marginTop: -BANNER_COMPOSER_OVERLAP_PX}; * archived/anonymous/blocked/system chat/admins-only footer. */ function ReportFooter() { + const styles = useThemeStyles(); + const bottomSafeAreaPaddingStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, addOfflineIndicatorBottomSafeAreaPadding: false}); + + return ( + + + + ); +} + +function ReportFooterVariants() { const route = useRoute(); const routeParams = route.params as {reportID?: string} | undefined; const reportIDFromRoute = getNonEmptyStringOnyxID(routeParams?.reportID); @@ -95,13 +106,11 @@ function ReportFooter() { return null; } - const chatFooterStyles = {...styles.chatFooter, minHeight: !isOffline ? CONST.CHAT_FOOTER_MIN_HEIGHT : 0}; - // Happy path — user can compose if (!shouldHideComposer) { const composer = ; return ( - + {shouldShowEnableNotificationsBanner ? ( <> @@ -117,7 +126,7 @@ function ReportFooter() { // Archived room if (isArchivedRoom) { return ( - + {!shouldUseNarrowLayout && ( @@ -131,7 +140,7 @@ function ReportFooter() { // Anonymous user if (isAnonymousUser) { return ( - + {!shouldUseNarrowLayout && ( @@ -145,7 +154,7 @@ function ReportFooter() { // Blocked from chat if (isBlockedFromChat) { return ( - + {!shouldUseNarrowLayout && ( @@ -159,7 +168,7 @@ function ReportFooter() { // System chat where user can't write if (!canWriteInReport && isSystemChat) { return ( - + {!shouldUseNarrowLayout && ( @@ -175,7 +184,7 @@ function ReportFooter() { const isEditingWithComposer = shouldShowComposerForActiveEditDraft; return ( - + {isEditingWithComposer && ( @@ -204,7 +213,7 @@ function ReportFooter() { // indicators keep priority. if (!canWriteInReport) { return ( - + chatFooter: { paddingLeft: 20, paddingRight: 20, + paddingTop: 10, display: 'flex', backgroundColor: theme.appBG, }, From fb4a4a5ba4fe5ac9605bf3e30e76bbe146d920d8 Mon Sep 17 00:00:00 2001 From: chrispader Date: Thu, 16 Jul 2026 19:31:43 +0200 Subject: [PATCH 7/9] fix: always show offline indicator in composer footer --- .../inbox/report/ReportActionCompose/ComposerDefaultFooter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerDefaultFooter.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerDefaultFooter.tsx index 448c01ce571e..95676248c57e 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerDefaultFooter.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerDefaultFooter.tsx @@ -15,7 +15,7 @@ function ComposerDefaultFooter() { return ( - {!shouldUseNarrowLayout && } + From 82357f620c95b60e4828d1d8251f09a7055c9648 Mon Sep 17 00:00:00 2001 From: chrispader Date: Thu, 16 Jul 2026 19:32:19 +0200 Subject: [PATCH 8/9] fix: remove `ReportActionsListPaddingView` --- src/pages/inbox/report/ReportActionsList.tsx | 12 +- .../report/ReportActionsListPaddingView.tsx | 40 ------ src/styles/index.ts | 2 +- .../unit/ReportActionsListPaddingViewTest.tsx | 132 ------------------ 4 files changed, 8 insertions(+), 178 deletions(-) delete mode 100644 src/pages/inbox/report/ReportActionsListPaddingView.tsx delete mode 100644 tests/unit/ReportActionsListPaddingViewTest.tsx diff --git a/src/pages/inbox/report/ReportActionsList.tsx b/src/pages/inbox/report/ReportActionsList.tsx index a3636e2aa080..a8f98896b7c6 100644 --- a/src/pages/inbox/report/ReportActionsList.tsx +++ b/src/pages/inbox/report/ReportActionsList.tsx @@ -15,6 +15,7 @@ import useUnreadMarker from '@hooks/useUnreadMarker'; import useWindowDimensions from '@hooks/useWindowDimensions'; import {isConsecutiveChronosAutomaticTimerAction} from '@libs/ChronosUtils'; +import FS from '@libs/Fullstory'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute'; import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -62,13 +63,13 @@ import type {OnyxEntry} from 'react-native-onyx'; import {useRoute} from '@react-navigation/native'; import {isTrackIntentUserSelector} from '@selectors/Onboarding'; import React, {useEffect, useRef, useState} from 'react'; +import {View} from 'react-native'; import FloatingMessageCounter from './FloatingMessageCounter'; import ReportActionIndexContext from './ReportActionIndexContext'; import {useReportActionsListActions, useReportActionsListState} from './ReportActionsListContext'; import ReportActionsListHeader from './ReportActionsListHeader'; import ReportActionsListItemRenderer from './ReportActionsListItemRenderer'; -import ReportActionsListPaddingView from './ReportActionsListPaddingView'; import ReportActionsSkeletonGuard from './ReportActionsSkeletonGuard'; import ShowPreviousMessagesButton from './ShowPreviousMessagesButton'; import useFollowActionBadgeTarget from './useFollowActionBadgeTarget'; @@ -130,6 +131,7 @@ function ReportActionsListContent({reportID, onLayout}: ReportActionsListProps) const route = useRoute>(); const reportActionIDFromRoute = route?.params?.reportActionID; const {sessionStartTime} = useConciergeSessionState(); + const reportActionsListFSClass = FS.getChatFSClass(report); const didLayout = useRef(false); @@ -446,9 +448,9 @@ function ReportActionsListContent({reportID, onLayout}: ReportActionsListProps) onActionBadgePress={scrollToActionBadgeTarget} isMarkAsDone={shouldUseMarkAsDoneCopy} /> - - + ); } diff --git a/src/pages/inbox/report/ReportActionsListPaddingView.tsx b/src/pages/inbox/report/ReportActionsListPaddingView.tsx deleted file mode 100644 index 25c14d9f208c..000000000000 --- a/src/pages/inbox/report/ReportActionsListPaddingView.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import useReportRecipientLocalTime from '@hooks/useReportRecipientLocalTime'; -import useThemeStyles from '@hooks/useThemeStyles'; - -import FS from '@libs/Fullstory'; -import {canUserPerformWriteAction} from '@libs/ReportUtils'; - -import type * as OnyxTypes from '@src/types/onyx'; -import type ChildrenProps from '@src/types/utils/ChildrenProps'; - -import React from 'react'; -import {View} from 'react-native'; - -import useShouldShowComposerForActiveEditDraft from './useShouldShowComposerForActiveEditDraft'; - -type ReportActionsListPaddingViewProps = ChildrenProps & { - /** The report currently being looked at */ - report: OnyxTypes.Report; - /** Whether the report is archived */ - isReportArchived: boolean; -}; - -function ReportActionsListPaddingView({report, isReportArchived, children}: ReportActionsListPaddingViewProps) { - const styles = useThemeStyles(); - const canShowRecipientLocalTime = useReportRecipientLocalTime({report}); - const reportActionsListFSClass = FS.getChatFSClass(report); - - const shouldShowComposerForActiveEditDraft = useShouldShowComposerForActiveEditDraft(); - const hideComposer = !canUserPerformWriteAction(report, isReportArchived) && !shouldShowComposerForActiveEditDraft; - - return ( - - {children} - - ); -} - -export default ReportActionsListPaddingView; diff --git a/src/styles/index.ts b/src/styles/index.ts index 073700e1c047..5fc71af1b7e3 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -2172,7 +2172,7 @@ const staticStyles = (theme: ThemeColors) => chatContentScrollView: { flexGrow: 1, justifyContent: 'flex-start', - paddingBottom: 16, + // paddingBottom: 16, ...chatContentScrollViewPlatformStyles, }, diff --git a/tests/unit/ReportActionsListPaddingViewTest.tsx b/tests/unit/ReportActionsListPaddingViewTest.tsx deleted file mode 100644 index 8c91fa65dcc1..000000000000 --- a/tests/unit/ReportActionsListPaddingViewTest.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import {render, screen} from '@testing-library/react-native'; - -import Text from '@components/Text'; - -import useReportRecipientLocalTime from '@hooks/useReportRecipientLocalTime'; - -import {canUserPerformWriteAction} from '@libs/ReportUtils'; - -import ReportActionsListPaddingView from '@pages/inbox/report/ReportActionsListPaddingView'; -import useShouldShowComposerForActiveEditDraft from '@pages/inbox/report/useShouldShowComposerForActiveEditDraft'; - -import CONST from '@src/CONST'; -import type {Report} from '@src/types/onyx'; - -import type {ViewStyle} from 'react-native'; - -import React from 'react'; -import {StyleSheet} from 'react-native'; - -const PB4_PADDING_BOTTOM = 16; - -jest.mock('@hooks/useReportRecipientLocalTime'); -jest.mock('@pages/inbox/report/useShouldShowComposerForActiveEditDraft'); - -jest.mock('@libs/ReportUtils', () => ({ - parseReportRouteParams: jest.fn(() => ({})), - canUserPerformWriteAction: jest.fn(), -})); - -jest.mock('@hooks/useThemeStyles', () => () => ({ - flex1: {flex: 1}, - pb4: {paddingBottom: PB4_PADDING_BOTTOM}, -})); - -const mockUseReportRecipientLocalTime = useReportRecipientLocalTime as jest.MockedFunction; -const mockUseShouldShowComposerForActiveEditDraft = useShouldShowComposerForActiveEditDraft as jest.MockedFunction; -const mockCanUserPerformWriteAction = canUserPerformWriteAction as jest.MockedFunction; - -const CURRENT_USER_ACCOUNT_ID = 1; - -const REPORT = { - reportID: '1', - type: CONST.REPORT.TYPE.CHAT, - participants: { - [CURRENT_USER_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, - }, -} as Report; - -type PaddingScenario = { - canShowRecipientLocalTime: boolean; - canUserPerformWriteAction: boolean; - shouldShowComposerForActiveEditDraft: boolean; - shouldApplyBottomPadding: boolean; -}; - -const paddingScenarios: PaddingScenario[] = [ - { - canShowRecipientLocalTime: false, - canUserPerformWriteAction: true, - shouldShowComposerForActiveEditDraft: false, - shouldApplyBottomPadding: true, - }, - { - canShowRecipientLocalTime: true, - canUserPerformWriteAction: true, - shouldShowComposerForActiveEditDraft: false, - shouldApplyBottomPadding: false, - }, - { - canShowRecipientLocalTime: false, - canUserPerformWriteAction: false, - shouldShowComposerForActiveEditDraft: false, - shouldApplyBottomPadding: false, - }, - { - canShowRecipientLocalTime: false, - canUserPerformWriteAction: false, - shouldShowComposerForActiveEditDraft: true, - shouldApplyBottomPadding: true, - }, -]; - -function renderPaddingView(isReportArchived = false) { - return render( - - child - , - ); -} - -function getPaddingBottom(toJSON: ReturnType['toJSON']) { - const root = toJSON(); - - if (!root || typeof root !== 'object' || !('props' in root)) { - return undefined; - } - - return StyleSheet.flatten(root.props?.style as ViewStyle)?.paddingBottom; -} - -describe('ReportActionsListPaddingView', () => { - beforeEach(() => { - jest.clearAllMocks(); - mockUseShouldShowComposerForActiveEditDraft.mockReturnValue(false); - mockCanUserPerformWriteAction.mockReturnValue(true); - mockUseReportRecipientLocalTime.mockReturnValue(false); - }); - - it('renders children', () => { - renderPaddingView(); - - expect(screen.getByText('child')).toBeOnTheScreen(); - }); - - describe('bottom padding', () => { - it.each(paddingScenarios)( - 'shouldApplyBottomPadding=$shouldApplyBottomPadding when canShowRecipientLocalTime=$canShowRecipientLocalTime, canUserPerformWriteAction=$canUserPerformWriteAction, shouldShowComposerForActiveEditDraft=$shouldShowComposerForActiveEditDraft', - ({canShowRecipientLocalTime, canUserPerformWriteAction: canWrite, shouldShowComposerForActiveEditDraft, shouldApplyBottomPadding}) => { - mockUseReportRecipientLocalTime.mockReturnValue(canShowRecipientLocalTime); - mockCanUserPerformWriteAction.mockReturnValue(canWrite); - mockUseShouldShowComposerForActiveEditDraft.mockReturnValue(shouldShowComposerForActiveEditDraft); - - const view = renderPaddingView(); - - expect(getPaddingBottom(view.toJSON)).toBe(shouldApplyBottomPadding ? PB4_PADDING_BOTTOM : undefined); - }, - ); - }); -}); From 6dd86c22f0e7242c981ab733c01cc4c5639d22d9 Mon Sep 17 00:00:00 2001 From: chrispader Date: Thu, 16 Jul 2026 19:32:59 +0200 Subject: [PATCH 9/9] fix: enable `KeyboardGestureArea` offset --- src/pages/inbox/ReportScreen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/inbox/ReportScreen.tsx b/src/pages/inbox/ReportScreen.tsx index e025a6d4d5ce..293ac5b5b779 100644 --- a/src/pages/inbox/ReportScreen.tsx +++ b/src/pages/inbox/ReportScreen.tsx @@ -116,7 +116,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) { return (