Skip to content

Commit 8b7f600

Browse files
authored
Merge pull request #90326 from software-mansion-labs/@GCyganek/landscape-mode/fix-claim-offer-banner-cut-off
2 parents d6a8779 + f58a0c9 commit 8b7f600

1 file changed

Lines changed: 28 additions & 4 deletions

File tree

src/components/CollapsibleHeaderOnKeyboard/index.native.tsx

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import React, {useEffect, useRef} from 'react';
33
import type {LayoutChangeEvent} from 'react-native';
44
import {useReanimatedKeyboardAnimation} from 'react-native-keyboard-controller';
55
import Reanimated, {Easing, useAnimatedReaction, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated';
6+
import useDebounce from '@hooks/useDebounce';
67
import usePrevious from '@hooks/usePrevious';
78
import useWindowDimensions from '@hooks/useWindowDimensions';
89
import isInLandscapeModeUtil from '@libs/isInLandscapeMode';
910
import type {CollapsibleHeaderOnKeyboardProps} from './types';
1011

1112
const COLLAPSE_DURATION = 100;
1213
const RESTORE_DURATION = 300;
14+
const HEADER_CONTENT_LAYOUT_STABILIZATION_TIME_ON_ORIENTATION_CHANGE = 300;
1315
// Assumed vertical space for the focused input field — used to reserve space above the keyboard.
1416
const VERTICAL_SPACE_FOR_FOCUSED_INPUT = 120;
1517
const KEYBOARD_OPENING_PROGRESS_THRESHOLDS = [0.5, 0.7, 0.8, 0.85, 0.9, 0.95, 0.99];
@@ -60,12 +62,33 @@ function CollapsibleHeaderOnKeyboard({children, collapsibleHeaderOffset = 0}: Co
6062
isInLandscapeModeSV.set(isInLandscapeMode);
6163
}, [isInLandscapeMode, isInLandscapeModeSV]);
6264

65+
const debouncedUpdateNaturalHeightRef = useDebounce((height: number) => {
66+
if (isInLandscapeMode) {
67+
return;
68+
}
69+
naturalHeightRef.current = height;
70+
}, HEADER_CONTENT_LAYOUT_STABILIZATION_TIME_ON_ORIENTATION_CHANGE);
71+
6372
const onLayout = (e: LayoutChangeEvent) => {
6473
const height = e.nativeEvent.layout.height;
6574

6675
if (height <= 0) {
6776
return;
6877
}
78+
79+
// Header re-measured in portrait mode and the content is taller than the previous measurement,
80+
// set the natural height to the new height and animate the height to the new height.
81+
// This can happen when header has different height on portrait and landscape mode.
82+
if (!isInLandscapeMode && height > naturalHeightRef.current && naturalHeightRef.current !== -1) {
83+
naturalHeight.set(height);
84+
animatedHeight.set(withTiming(height, {duration: RESTORE_DURATION}));
85+
86+
// we need to debounce the update of the natural height ref to make sure we don't block height updates
87+
// on landscape -> portrait mode change where header layout might not be stable at first.
88+
debouncedUpdateNaturalHeightRef(height);
89+
return;
90+
}
91+
6992
// First measurement, or content changed while header is fully open
7093
// (to skip onLayout calls triggered by our own height animation collapsing the view to 0)
7194
if (naturalHeightRef.current === -1 || animatedHeight.get() >= naturalHeightRef.current) {
@@ -77,19 +100,20 @@ function CollapsibleHeaderOnKeyboard({children, collapsibleHeaderOffset = 0}: Co
77100

78101
// Restores the header when the screen goes from landscape to portrait mode.
79102
useEffect(() => {
80-
const naturalHeightValue = naturalHeightRef.current;
103+
const naturalHeightValue = naturalHeight.get();
81104
if (!isInLandscapeMode && isFocused && naturalHeightValue !== -1) {
82105
animatedHeight.set(withTiming(naturalHeightValue, {duration: RESTORE_DURATION}));
83106
}
84-
}, [isInLandscapeMode, isFocused, animatedHeight]);
107+
// eslint-disable-next-line react-hooks/exhaustive-deps
108+
}, [isInLandscapeMode]);
85109

86110
// Restores the header when the screen loses focus
87111
useEffect(() => {
88112
if (!prevIsFocused || isFocused) {
89113
return;
90114
}
91115

92-
const naturalHeightValue = naturalHeightRef.current;
116+
const naturalHeightValue = naturalHeight.get();
93117
if (naturalHeightValue === -1) {
94118
return;
95119
}
@@ -159,7 +183,7 @@ function CollapsibleHeaderOnKeyboard({children, collapsibleHeaderOffset = 0}: Co
159183
// When fully open, leave height undefined so the view sizes itself naturally.
160184
// This avoids fighting the layout engine during orientation changes.
161185
if (animatedHeight.get() >= naturalHeight.get()) {
162-
return {overflow: 'hidden'};
186+
return {overflow: 'hidden', height: 'auto'};
163187
}
164188
return {height: animatedHeight.get(), overflow: 'hidden'};
165189
});

0 commit comments

Comments
 (0)