Skip to content

Commit d0e1155

Browse files
authored
Merge pull request Expensify#67745 from software-mansion-labs/@zfurtak/bump-flashlist-v2
Bump flashlist to v2
2 parents 0db6a75 + c502847 commit d0e1155

22 files changed

Lines changed: 110 additions & 244 deletions

File tree

package-lock.json

Lines changed: 4 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
"@react-navigation/stack": "7.3.3",
120120
"@react-ng/bounds-observer": "^0.2.1",
121121
"@rnmapbox/maps": "10.1.33",
122-
"@shopify/flash-list": "1.8.2",
122+
"@shopify/flash-list": "2.0.3",
123123
"@ua/react-native-airship": "~24.4.0",
124124
"awesome-phonenumber": "^5.4.0",
125125
"babel-polyfill": "^6.26.0",
@@ -410,4 +410,4 @@
410410
"node": "20.19.3",
411411
"npm": "10.8.2"
412412
}
413-
}
413+
}

patches/recyclerlistview+4.2.3.patch

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/components/DisplayNames/index.native.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ import TextWithEmojiFragment from '@pages/home/report/comment/TextWithEmojiFragm
88
import type DisplayNamesProps from './types';
99

1010
// As we don't have to show tooltips of the Native platform so we simply render the full display names list.
11-
function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfLines = 1, renderAdditionalText}: DisplayNamesProps) {
11+
function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfLines = 1, renderAdditionalText, testID}: DisplayNamesProps) {
1212
const {translate} = useLocalize();
1313
const titleContainsTextAndCustomEmoji = useMemo(() => containsCustomEmoji(fullTitle) && !containsOnlyCustomEmoji(fullTitle), [fullTitle]);
1414
return (
1515
<Text
1616
accessibilityLabel={accessibilityLabel}
1717
style={textStyles}
1818
numberOfLines={numberOfLines}
19-
testID={DisplayNames.displayName}
19+
testID={`${DisplayNames.displayName}${testID !== undefined ? `-${testID}` : ''}`}
2020
>
2121
{titleContainsTextAndCustomEmoji ? (
2222
<TextWithEmojiFragment

src/components/DisplayNames/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ type DisplayNamesProps = {
4545

4646
/** Additional Text component to render after the displayNames */
4747
renderAdditionalText?: () => React.ReactNode;
48+
49+
/** TestID indicating order */
50+
testID?: number;
4851
};
4952

5053
export default DisplayNamesProps;

src/components/EmojiPicker/EmojiPickerMenu/BaseEmojiPickerMenu.tsx

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import {FlashList} from '@shopify/flash-list';
2-
import type {ListRenderItem} from '@shopify/flash-list';
3-
import React, {useMemo} from 'react';
2+
import type {FlashListRef, ListRenderItem} from '@shopify/flash-list';
3+
import React from 'react';
44
import type {ForwardedRef} from 'react';
5-
import {StyleSheet, View} from 'react-native';
5+
import {View} from 'react-native';
66
import type {StyleProp, ViewStyle} from 'react-native';
77
import type {OnyxEntry} from 'react-native-onyx';
88
import CategoryShortcutBar from '@components/EmojiPicker/CategoryShortcutBar';
99
import EmojiSkinToneList from '@components/EmojiPicker/EmojiSkinToneList';
1010
import Text from '@components/Text';
1111
import useLocalize from '@hooks/useLocalize';
12-
import useResponsiveLayout from '@hooks/useResponsiveLayout';
1312
import useThemeStyles from '@hooks/useThemeStyles';
14-
import useWindowDimensions from '@hooks/useWindowDimensions';
1513
import type {EmojiPickerList, EmojiPickerListItem, HeaderIndices} from '@libs/EmojiUtils';
1614
import CONST from '@src/CONST';
1715

@@ -81,18 +79,9 @@ function ListEmptyComponent() {
8179

8280
function BaseEmojiPickerMenu(
8381
{headerEmojis, scrollToHeader, isFiltered, listWrapperStyle = [], data, renderItem, stickyHeaderIndices = [], extraData = [], alwaysBounceVertical = false}: BaseEmojiPickerMenuProps,
84-
ref: ForwardedRef<FlashList<EmojiPickerListItem>>,
82+
ref: ForwardedRef<FlashListRef<EmojiPickerListItem>>,
8583
) {
8684
const styles = useThemeStyles();
87-
const {windowWidth} = useWindowDimensions();
88-
const {shouldUseNarrowLayout} = useResponsiveLayout();
89-
90-
// Estimated list size should be a whole integer to avoid floating point precision errors
91-
// More info: https://github.com/Expensify/App/issues/34522
92-
const listWidth = shouldUseNarrowLayout ? Math.floor(windowWidth) : CONST.EMOJI_PICKER_SIZE.WIDTH;
93-
94-
const flattenListWrapperStyle = useMemo(() => StyleSheet.flatten(listWrapperStyle), [listWrapperStyle]);
95-
9685
return (
9786
<>
9887
{!isFiltered && (
@@ -113,8 +102,6 @@ function BaseEmojiPickerMenu(
113102
stickyHeaderIndices={stickyHeaderIndices}
114103
ListEmptyComponent={ListEmptyComponent}
115104
alwaysBounceVertical={alwaysBounceVertical}
116-
estimatedItemSize={CONST.EMOJI_PICKER_ITEM_HEIGHT}
117-
estimatedListSize={{height: flattenListWrapperStyle.height as number, width: listWidth}}
118105
contentContainerStyle={styles.ph4}
119106
extraData={extraData}
120107
getItemType={getItemType}

src/components/EmojiPicker/EmojiPickerMenu/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,13 @@ function EmojiPickerMenu({onEmojiSelected, activeEmoji}: EmojiPickerMenuProps, r
259259

260260
if ('header' in item && item.header) {
261261
return (
262-
<View style={[styles.emojiHeaderContainer, target === 'StickyHeader' ? styles.stickyHeaderEmoji(shouldUseNarrowLayout, windowWidth) : undefined]}>
262+
<View
263+
style={[
264+
styles.emojiHeaderContainer,
265+
styles.emojiHeaderContainerWidth(shouldUseNarrowLayout, windowWidth),
266+
target === 'StickyHeader' ? styles.stickyHeaderEmoji : undefined,
267+
]}
268+
>
263269
<Text style={styles.textLabelSupporting}>{translate(`emojiPicker.headers.${code}` as TranslationPaths)}</Text>
264270
</View>
265271
);

src/components/EmojiPicker/EmojiPickerMenu/useEmojiPickerMenu.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {FlashList} from '@shopify/flash-list';
1+
import type {FlashListRef} from '@shopify/flash-list';
22
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
33
import emojis from '@assets/emojis';
44
import useKeyboardState from '@hooks/useKeyboardState';
@@ -12,7 +12,7 @@ import {getHeaderEmojis, getSpacersIndexes, mergeEmojisWithFrequentlyUsedEmojis,
1212
import ONYXKEYS from '@src/ONYXKEYS';
1313

1414
const useEmojiPickerMenu = () => {
15-
const emojiListRef = useRef<FlashList<EmojiPickerListItem>>(null);
15+
const emojiListRef = useRef<FlashListRef<EmojiPickerListItem>>(null);
1616
const [frequentlyUsedEmojis] = useOnyx(ONYXKEYS.FREQUENTLY_USED_EMOJIS, {canBeMissing: true});
1717
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
1818
const allEmojis = useMemo(() => mergeEmojisWithFrequentlyUsedEmojis(emojis, processFrequentlyUsedEmojis(frequentlyUsedEmojis)), [frequentlyUsedEmojis]);

src/components/LHNOptionsList/LHNOptionsList.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {useIsFocused, useRoute} from '@react-navigation/native';
2-
import type {FlashListProps} from '@shopify/flash-list';
2+
import type {FlashListProps, FlashListRef} from '@shopify/flash-list';
33
import {FlashList} from '@shopify/flash-list';
44
import type {ReactElement} from 'react';
55
import React, {memo, useCallback, useContext, useEffect, useMemo, useRef} from 'react';
@@ -10,7 +10,6 @@ import * as Expensicons from '@components/Icon/Expensicons';
1010
import LottieAnimations from '@components/LottieAnimations';
1111
import {ScrollOffsetContext} from '@components/ScrollOffsetContextProvider';
1212
import TextBlock from '@components/TextBlock';
13-
import useLHNEstimatedListSize from '@hooks/useLHNEstimatedListSize';
1413
import useLocalize from '@hooks/useLocalize';
1514
import useNetwork from '@hooks/useNetwork';
1615
import useOnyx from '@hooks/useOnyx';
@@ -42,7 +41,7 @@ const keyExtractor = (item: Report) => `report_${item.reportID}`;
4241
function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optionMode, shouldDisableFocusOptions = false, onFirstItemRendered = () => {}}: LHNOptionsListProps) {
4342
const {saveScrollOffset, getScrollOffset, saveScrollIndex, getScrollIndex} = useContext(ScrollOffsetContext);
4443
const {isOffline} = useNetwork();
45-
const flashListRef = useRef<FlashList<Report>>(null);
44+
const flashListRef = useRef<FlashListRef<Report>>(null);
4645
const route = useRoute();
4746
const isScreenFocused = useIsFocused();
4847

@@ -63,7 +62,6 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
6362
const theme = useTheme();
6463
const styles = useThemeStyles();
6564
const {translate, preferredLocale, localeCompare} = useLocalize();
66-
const estimatedListSize = useLHNEstimatedListSize();
6765
const isReportsSplitNavigatorLast = useRootNavigationState((state) => state?.routes?.at(-1)?.name === NAVIGATORS.REPORTS_SPLIT_NAVIGATOR);
6866
const shouldShowEmptyLHN = data.length === 0;
6967
const estimatedItemSize = optionMode === CONST.OPTION_MODE.COMPACT ? variables.optionRowHeightCompact : variables.optionRowHeight;
@@ -161,7 +159,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
161159
* Function which renders a row in the list
162160
*/
163161
const renderItem = useCallback(
164-
({item}: RenderItemProps): ReactElement => {
162+
({item, index}: RenderItemProps): ReactElement => {
165163
const reportID = item.reportID;
166164
const itemParentReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${item.parentReportID}`];
167165
const itemReportNameValuePairs = reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`];
@@ -248,6 +246,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
248246
isReportsSplitNavigatorLast={isReportsSplitNavigatorLast}
249247
isScreenFocused={isScreenFocused}
250248
localeCompare={localeCompare}
249+
testID={index}
251250
isReportArchived={isReportArchived}
252251
/>
253252
);
@@ -398,14 +397,14 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
398397
testID="lhn-options-list"
399398
keyExtractor={keyExtractor}
400399
renderItem={renderItem}
401-
estimatedItemSize={estimatedItemSize}
402-
overrideProps={{estimatedHeightSize: estimatedItemSize * CONST.LHN_VIEWPORT_ITEM_COUNT}}
403400
extraData={extraData}
404401
showsVerticalScrollIndicator={false}
405402
onLayout={onLayout}
406403
onScroll={onScroll}
407-
estimatedListSize={estimatedListSize}
408404
initialScrollIndex={isWebOrDesktop ? getScrollIndex(route) : undefined}
405+
maintainVisibleContentPosition={{disabled: true}}
406+
drawDistance={1000}
407+
removeClippedSubviews
409408
/>
410409
)}
411410
</View>

src/components/LHNOptionsList/OptionRowLHN.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ function OptionRowLHN({
6161
hasDraftComment,
6262
shouldShowRBRorGBRTooltip,
6363
isScreenFocused = false,
64+
testID,
6465
}: OptionRowLHNProps) {
6566
const theme = useTheme();
6667
const styles = useThemeStyles();
@@ -294,6 +295,7 @@ function OptionRowLHN({
294295
isGroupChat(report) ||
295296
isSystemChat(report)
296297
}
298+
testID={testID}
297299
/>
298300
{isChatUsedForOnboarding && <FreeTrial badgeStyles={[styles.mnh0, styles.pl2, styles.pr2, styles.ml1, styles.flexShrink1]} />}
299301
{isStatusVisible && (

0 commit comments

Comments
 (0)