Skip to content

Commit 97bf507

Browse files
authored
Merge pull request #88191 from bernhardoj/fix/88051-popover-height-in-landscape-mode
[Landscape] Fix popup content is not fully shown
2 parents 2363a90 + 2dd1957 commit 97bf507

19 files changed

Lines changed: 311 additions & 278 deletions

src/CONST/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9654,6 +9654,7 @@ const CONST = {
96549654
AUTH_IMAGES: 'auth-images',
96559655
},
96569656

9657+
MODAL_MAX_HEIGHT_TO_WINDOW_HEIGHT_RATIO: 0.9,
96579658
MODAL_MAX_HEIGHT_TO_WINDOW_HEIGHT_RATIO_LANDSCAPE_MODE: 0.75,
96589659

96599660
MAP_VIEW_LAYERS: {

src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,8 @@ function MoneyRequestReportTransactionList({
533533

534534
const groupByPopoverComponent = useCallback(
535535
(props: {closeOverlay: () => void}) => (
536-
<View style={[!isSmallScreenWidth && styles.pv4]}>
537-
<View style={styles.getSelectionListPopoverHeight(groupByOptions.length || 1, windowHeight, false, isInLandscapeMode, false)}>
536+
<View style={[styles.pv4]}>
537+
<View style={styles.getSelectionListPopoverHeight({itemCount: groupByOptions.length || 1, windowHeight, isInLandscapeMode, hasButton: false})}>
538538
<SelectionList
539539
data={groupByOptions}
540540
shouldSingleExecuteRowSelect
@@ -551,7 +551,7 @@ function MoneyRequestReportTransactionList({
551551
</View>
552552
</View>
553553
),
554-
[groupByOptions, reportLayoutGroupBy, styles, windowHeight, isSmallScreenWidth, isInLandscapeMode],
554+
[groupByOptions, reportLayoutGroupBy, styles, windowHeight, isInLandscapeMode],
555555
);
556556

557557
const transactionListContent = (

src/components/Search/FilterDropdowns/BasePopup.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ function BasePopup({children, label, applySentryLabel, resetSentryLabel, style,
2323
const styles = useThemeStyles();
2424

2525
return (
26-
<View style={[!isSmallScreenWidth && styles.pv4, style]}>
26+
<View style={[styles.pv4, style]}>
2727
{onBackButtonPress ? (
2828
<HeaderWithBackButton
2929
shouldDisplayHelpButton={false}

src/components/Search/FilterDropdowns/CardSelectPopup.tsx

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {openSearchCardFiltersPage} from '@libs/actions/Search';
1919
import {buildCardFeedsData, buildCardsData, generateSelectedCards, getDomainFeedData, getSelectedCardsFromFeeds} from '@libs/CardFeedUtils';
2020
import type {CardFilterItem} from '@libs/CardFeedUtils';
2121
import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
22+
import variables from '@styles/variables';
2223
import CONST from '@src/CONST';
2324
import ONYXKEYS from '@src/ONYXKEYS';
2425
import type {SearchAdvancedFiltersForm} from '@src/types/form';
@@ -39,7 +40,8 @@ function CardSelectPopup({isExpanded, updateFilterForm, closeOverlay}: CardSelec
3940
const illustrations = useThemeIllustrations();
4041
const companyCardFeedIcons = useCompanyCardFeedIcons();
4142
const {windowHeight} = useWindowDimensions();
42-
const {shouldUseNarrowLayout, isInLandscapeMode} = useResponsiveLayout();
43+
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
44+
const {isSmallScreenWidth, isInLandscapeMode} = useResponsiveLayout();
4345

4446
const [areCardsLoaded] = useOnyx(ONYXKEYS.IS_SEARCH_FILTERS_CARD_DATA_LOADED);
4547
const [userCardList, userCardListMetadata] = useOnyx(ONYXKEYS.CARD_LIST);
@@ -185,31 +187,44 @@ function CardSelectPopup({isExpanded, updateFilterForm, closeOverlay}: CardSelec
185187
onApply={applyChanges}
186188
resetSentryLabel={CONST.SENTRY_LABEL.SEARCH.FILTER_POPUP_RESET_CARD}
187189
applySentryLabel={CONST.SENTRY_LABEL.SEARCH.FILTER_POPUP_APPLY_CARD}
188-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we want to fallback to 1 when it's 0
189-
style={styles.getCardSelectionListPopoverHeight(itemCount || 1, sectionHeaderCount, windowHeight, shouldUseNarrowLayout, isInLandscapeMode, shouldShowSearchInput)}
190190
>
191-
{!!shouldShowLoadingState && (
192-
<View style={[styles.flex1, styles.flexColumn, styles.justifyContentCenter, styles.alignItemsCenter]}>
193-
<ActivityIndicator
194-
color={theme.spinner}
195-
size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
196-
style={[styles.pl3]}
197-
reasonAttributes={reasonAttributes}
191+
<View
192+
style={[
193+
styles.getSelectionListPopoverHeight({
194+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we want to fallback to 1 when it's 0
195+
itemCount: itemCount || 1,
196+
itemHeight: variables.optionRowHeight,
197+
windowHeight,
198+
isInLandscapeMode,
199+
hasTitle: isSmallScreenWidth,
200+
isSearchable: shouldShowSearchInput,
201+
extraHeight: 28 * sectionHeaderCount,
202+
}),
203+
]}
204+
>
205+
{!!shouldShowLoadingState && (
206+
<View style={[styles.flex1, styles.flexColumn, styles.justifyContentCenter, styles.alignItemsCenter]}>
207+
<ActivityIndicator
208+
color={theme.spinner}
209+
size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
210+
style={[styles.pl3]}
211+
reasonAttributes={reasonAttributes}
212+
/>
213+
</View>
214+
)}
215+
{!shouldShowLoadingState && (
216+
<SelectionListWithSections<CardFilterItem>
217+
sections={sections}
218+
ListItem={CardListItem}
219+
onSelectRow={updateNewCards}
220+
shouldPreventDefaultFocusOnSelectRow={false}
221+
shouldShowTextInput={shouldShowSearchInput}
222+
textInputOptions={textInputOptions}
223+
shouldStopPropagation
224+
canSelectMultiple
198225
/>
199-
</View>
200-
)}
201-
{!shouldShowLoadingState && (
202-
<SelectionListWithSections<CardFilterItem>
203-
sections={sections}
204-
ListItem={CardListItem}
205-
onSelectRow={updateNewCards}
206-
shouldPreventDefaultFocusOnSelectRow={false}
207-
shouldShowTextInput={shouldShowSearchInput}
208-
textInputOptions={textInputOptions}
209-
shouldStopPropagation
210-
canSelectMultiple
211-
/>
212-
)}
226+
)}
227+
</View>
213228
</BasePopup>
214229
);
215230
}

src/components/Search/FilterDropdowns/DateSelectPopup/index.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import Text from '@components/Text';
1111
import useLocalize from '@hooks/useLocalize';
1212
import useResponsiveLayout from '@hooks/useResponsiveLayout';
1313
import useThemeStyles from '@hooks/useThemeStyles';
14-
import useWindowDimensions from '@hooks/useWindowDimensions';
1514
import type {SearchDateValues} from '@libs/SearchQueryUtils';
1615
import {getDateModifierTitle, getDateRangeDisplayValueFromFormValue} from '@libs/SearchQueryUtils';
1716
import type {SearchDateModifier} from '@libs/SearchUIUtils';
@@ -47,7 +46,6 @@ function DateSelectPopup({label, value, presets, style, closeOverlay, onChange,
4746

4847
const {translate} = useLocalize();
4948
const styles = useThemeStyles();
50-
const {windowHeight} = useWindowDimensions();
5149
const searchDatePresetFilterBaseRef = useRef<SearchDatePresetFilterBaseHandle>(null);
5250
const scrollViewRef = useRef<React.ComponentRef<typeof ScrollView>>(null);
5351
const [selectedDateModifier, setSelectedDateModifier] = useState<SearchDateModifier | null>(null);
@@ -130,8 +128,6 @@ function DateSelectPopup({label, value, presets, style, closeOverlay, onChange,
130128
closeOverlay();
131129
}, [clearSelection, closeOverlay, onChange, selectedDateModifier]);
132130

133-
const maxPopupHeight = Math.round(windowHeight * 0.875);
134-
135131
// For non-Range modes, use original simple styles. For Range, use custom layout
136132
const useRangeLayout = selectedDateModifier === CONST.SEARCH.DATE_MODIFIERS.RANGE;
137133

@@ -186,14 +182,13 @@ function DateSelectPopup({label, value, presets, style, closeOverlay, onChange,
186182
);
187183
}
188184

189-
const topPaddingStyle = selectedDateModifier ? styles.pt3 : undefined;
190185
const buttonRowSpacing = selectedDateModifier ? styles.mt4 : styles.mt2;
191-
const mobileContainerStyle = useRangeLayout ? [topPaddingStyle, styles.flexGrow1, {maxHeight: maxPopupHeight}] : styles.gap2;
186+
const mobileContainerStyle = useRangeLayout ? [styles.flexGrow1] : styles.gap2;
192187
const mobileLabelStyle = useRangeLayout ? [styles.textLabel, styles.ph5, styles.pb3] : [styles.textLabel, styles.textSupporting, styles.ph5, styles.pv1];
193188
const mobileButtonRowStyle = useRangeLayout ? [styles.flexRow, styles.ph5, buttonRowSpacing, styles.alignItemsCenter, styles.gap2] : [styles.flexRow, styles.gap2, styles.ph5];
194189

195190
return (
196-
<View style={[mobileContainerStyle, style, isInLandscapeMode ? styles.h100 : undefined]}>
191+
<View style={[styles.pv4, mobileContainerStyle, style, isInLandscapeMode ? styles.h100 : undefined]}>
197192
{!selectedDateModifier && !!label && <Text style={mobileLabelStyle}>{label}</Text>}
198193
<ScrollView
199194
ref={scrollViewRef}

src/components/Search/FilterDropdowns/DisplayPopup.tsx

Lines changed: 19 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import React, {useState} from 'react';
2-
import {View} from 'react-native';
32
import type {OnyxEntry} from 'react-native-onyx';
4-
import HeaderWithBackButton from '@components/HeaderWithBackButton';
53
import MenuItem from '@components/MenuItem';
64
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
5+
import ScrollView from '@components/ScrollView';
76
import type {SearchQueryJSON} from '@components/Search/types';
87
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
98
import useLocalize from '@hooks/useLocalize';
@@ -37,7 +36,7 @@ type DisplayPopupProps = {
3736
function DisplayPopup({queryJSON, searchResults, closeOverlay, onSort}: DisplayPopupProps) {
3837
const {translate} = useLocalize();
3938
const styles = useThemeStyles();
40-
const {shouldUseNarrowLayout, isLargeScreenWidth} = useResponsiveLayout();
39+
const {isLargeScreenWidth} = useResponsiveLayout();
4140
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Columns']);
4241
const [searchAdvancedFilters = getEmptyObject<SearchAdvancedFiltersForm>()] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM);
4342
const [selectedDisplayFilter, setSelectedDisplayFilter] = useState<
@@ -72,7 +71,7 @@ function DisplayPopup({queryJSON, searchResults, closeOverlay, onSort}: DisplayP
7271
const viewValue = searchAdvancedFilters[CONST.SEARCH.SYNTAX_ROOT_KEYS.VIEW];
7372

7473
return (
75-
<View style={[!shouldUseNarrowLayout && styles.pv4]}>
74+
<ScrollView contentContainerStyle={[styles.pv4]}>
7675
<MenuItemWithTopDescription
7776
shouldShowRightIcon
7877
description={translate('search.display.sortBy')}
@@ -127,7 +126,7 @@ function DisplayPopup({queryJSON, searchResults, closeOverlay, onSort}: DisplayP
127126
sentryLabel={CONST.SENTRY_LABEL.SEARCH.COLUMNS_BUTTON}
128127
/>
129128
)}
130-
</View>
129+
</ScrollView>
131130
);
132131
}
133132

@@ -162,46 +161,35 @@ function DisplayPopup({queryJSON, searchResults, closeOverlay, onSort}: DisplayP
162161
setSelectedDisplayFilter(null);
163162
};
164163

165-
const subtitle = {
166-
[CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY]: translate('search.display.sortBy'),
167-
[CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER]: translate('search.display.sortOrder'),
168-
[CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY]: translate('search.display.groupBy'),
169-
[CONST.SEARCH.SYNTAX_FILTER_KEYS.GROUP_CURRENCY]: translate('common.groupCurrency'),
170-
[CONST.SEARCH.SYNTAX_ROOT_KEYS.VIEW]: translate('search.view.label'),
171-
[CONST.SEARCH.SYNTAX_ROOT_KEYS.LIMIT]: translate('search.display.limitResults'),
172-
};
173-
174-
let subPopup: React.JSX.Element | null = null;
175-
176164
switch (selectedDisplayFilter) {
177165
case CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY:
178-
subPopup = (
166+
return (
179167
<SortByPopup
180168
searchResults={searchResults}
181169
queryJSON={queryJSON}
182170
groupBy={groupBy}
183171
onSort={onSort}
184172
onSortOrderPress={() => setSelectedDisplayFilter(CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER)}
173+
onBackButtonPress={goBack}
185174
closeOverlay={closeOverlay}
186175
/>
187176
);
188-
break;
189177
case CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER:
190-
subPopup = (
178+
return (
191179
<SortOrderPopup
192180
queryJSON={queryJSON}
193181
onSort={onSort}
182+
onBackButtonPress={goBack}
194183
closeOverlay={closeOverlay}
195184
/>
196185
);
197-
break;
198186
case CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY:
199-
subPopup = (
187+
return (
200188
<GroupByPopup
201-
style={styles.p0}
202189
sections={groupBySections}
203190
value={groupBy}
204191
closeOverlay={closeOverlay}
192+
onBackButtonPress={goBack}
205193
onChange={(item) => {
206194
const newValue = item?.value;
207195
if (!newValue) {
@@ -212,52 +200,39 @@ function DisplayPopup({queryJSON, searchResults, closeOverlay, onSort}: DisplayP
212200
}}
213201
/>
214202
);
215-
break;
216203
case CONST.SEARCH.SYNTAX_FILTER_KEYS.GROUP_CURRENCY:
217-
subPopup = (
204+
return (
218205
<GroupCurrencyPopup
219206
onChange={(item) => updateFilterForm({groupCurrency: item?.value})}
207+
onBackButtonPress={goBack}
220208
closeOverlay={closeOverlay}
221209
/>
222210
);
223-
break;
224211
case CONST.SEARCH.SYNTAX_ROOT_KEYS.VIEW:
225-
subPopup = (
212+
return (
226213
<SingleSelectPopup
227-
style={styles.p0}
228214
items={viewOptions}
229215
value={view}
216+
label={translate('search.view.label')}
217+
onBackButtonPress={goBack}
230218
closeOverlay={closeOverlay}
231219
onChange={(item) => updateFilterForm({view: item?.value ?? CONST.SEARCH.VIEW.TABLE})}
232220
/>
233221
);
234-
break;
235222
case CONST.SEARCH.SYNTAX_ROOT_KEYS.LIMIT:
236-
subPopup = (
223+
return (
237224
<TextInputPopup
238-
style={styles.pv0}
239225
placeholder={translate('search.filters.limit')}
240226
defaultValue={limitValue}
227+
label={translate('search.display.limitResults')}
228+
onBackButtonPress={goBack}
241229
closeOverlay={closeOverlay}
242230
onChange={(value) => updateFilterForm({limit: value})}
243231
/>
244232
);
245-
break;
246233
default:
247-
break;
234+
return null;
248235
}
249-
250-
return (
251-
<View style={[!shouldUseNarrowLayout && styles.pv4]}>
252-
<HeaderWithBackButton
253-
shouldDisplayHelpButton={false}
254-
style={[styles.h10, styles.pv1, styles.mb2]}
255-
subtitle={subtitle[selectedDisplayFilter]}
256-
onBackButtonPress={goBack}
257-
/>
258-
{subPopup}
259-
</View>
260-
);
261236
}
262237

263238
export default DisplayPopup;

src/components/Search/FilterDropdowns/DropdownButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ function DropdownButton({
195195
// This must be false because we dont want the modal to close if we open the RHP for selections
196196
// such as date years
197197
shouldCloseWhenBrowserNavigationChanged={false}
198-
innerContainerStyle={containerStyles}
198+
innerContainerStyle={{...containerStyles, ...styles.p0}}
199199
popoverDimensions={{
200200
width: actualPopoverWidth,
201201
height: CONST.POPOVER_DROPDOWN_MIN_HEIGHT,

src/components/Search/FilterDropdowns/GroupByPopup.tsx

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type {SearchGroupBy} from '@components/Search/types';
55
import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem';
66
import SelectionListWithSections from '@components/SelectionList/SelectionListWithSections';
77
import type {ListItem} from '@components/SelectionList/types';
8+
import useLocalize from '@hooks/useLocalize';
89
import useResponsiveLayout from '@hooks/useResponsiveLayout';
910
import useThemeStyles from '@hooks/useThemeStyles';
1011
import useWindowDimensions from '@hooks/useWindowDimensions';
@@ -18,16 +19,14 @@ type GroupByPopupItem = {
1819
};
1920

2021
type GroupByPopupProps = {
21-
/** The label to show when in an overlay on mobile */
22-
label?: string;
23-
2422
/** The grouped options to show in the list */
2523
sections: GroupBySection[];
2624

2725
/** The currently selected item */
2826
value: GroupByPopupItem | null;
2927

3028
style?: StyleProp<ViewStyle>;
29+
onBackButtonPress: () => void;
3130

3231
/** Function to call to close the overlay when changes are applied */
3332
closeOverlay: () => void;
@@ -36,10 +35,10 @@ type GroupByPopupProps = {
3635
onChange: (item: GroupByPopupItem | null) => void;
3736
};
3837

39-
function GroupByPopup({label, value, sections, style, closeOverlay, onChange}: GroupByPopupProps) {
38+
function GroupByPopup({value, sections, style, onBackButtonPress, closeOverlay, onChange}: GroupByPopupProps) {
39+
const {translate} = useLocalize();
4040
const styles = useThemeStyles();
41-
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
42-
const {isSmallScreenWidth, isInLandscapeMode} = useResponsiveLayout();
41+
const {isInLandscapeMode} = useResponsiveLayout();
4342
const {windowHeight} = useWindowDimensions();
4443
const [selectedItem, setSelectedItem] = useState(value);
4544

@@ -59,7 +58,7 @@ function GroupByPopup({label, value, sections, style, closeOverlay, onChange}: G
5958
[sections, selectedItem?.value, styles.dividerLine],
6059
);
6160

62-
const optionsCount = Math.max(
61+
const itemCount = Math.max(
6362
1,
6463
listSections.reduce((count, section) => count + section.data.length + (section.data.length > 0 && !!section.customHeader ? 1 : 0), 0),
6564
);
@@ -82,18 +81,16 @@ function GroupByPopup({label, value, sections, style, closeOverlay, onChange}: G
8281
closeOverlay();
8382
}, [closeOverlay, onChange]);
8483

85-
const shouldShowLabel = isSmallScreenWidth && !!label;
86-
8784
return (
8885
<BasePopup
89-
label={label}
9086
onReset={resetChanges}
9187
onApply={applyChanges}
88+
onBackButtonPress={onBackButtonPress}
89+
label={translate('search.display.groupBy')}
9290
resetSentryLabel={CONST.SENTRY_LABEL.SEARCH.FILTER_POPUP_RESET_SINGLE_SELECT}
9391
applySentryLabel={CONST.SENTRY_LABEL.SEARCH.FILTER_POPUP_APPLY_SINGLE_SELECT}
94-
style={style}
9592
>
96-
<View style={[styles.getSelectionListPopoverHeight(optionsCount, windowHeight, false, isInLandscapeMode, shouldShowLabel)]}>
93+
<View style={[style, styles.getSelectionListPopoverHeight({itemCount, windowHeight, isInLandscapeMode, hasHeader: true})]}>
9794
<SelectionListWithSections
9895
sections={listSections}
9996
shouldSingleExecuteRowSelect

0 commit comments

Comments
 (0)