Skip to content

Commit

Permalink
CP-5865: Fix iOS performance regression with BigList (#746)
Browse files Browse the repository at this point in the history
  • Loading branch information
atn4z7 authored Jul 10, 2023
1 parent 0cc0085 commit 4bf7c4b
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 17 deletions.
7 changes: 0 additions & 7 deletions app/components/BigList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,10 @@ import {
StyleProp,
ViewStyle
} from 'react-native'
import {
DragEndParams,
DraggableRenderItem
} from 'components/draggableList/types'

interface BigListProps<TItem> {
data: TItem[]
renderItem: (item: ListRenderItemInfo<TItem>) => React.ReactElement
draggableListItem?: DraggableRenderItem<TItem>
ListEmptyComponent?: React.ComponentType<unknown> | React.ReactElement
refreshing?: boolean
onRefresh?: () => void
Expand All @@ -24,8 +19,6 @@ interface BigListProps<TItem> {
onEndReachedThreshold?: number
refreshControl?: React.ReactElement<RefreshControlProps>
estimatedItemSize?: number
isDraggable?: boolean
onDragEnd?: (params: DragEndParams<TItem>) => void
}

/**
Expand Down
68 changes: 68 additions & 0 deletions app/components/FlashList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { FlashList as ShopifyFlashList } from '@shopify/flash-list'
import React from 'react'
import {
ContentStyle,
ListRenderItem as FlashListRenderItem
} from '@shopify/flash-list/dist/FlashListProps'
import { RefreshControlProps } from 'react-native'

interface AvaListProps<TItem> {
data: TItem[]
renderItem: FlashListRenderItem<TItem>
ItemSeparatorComponent?: React.ComponentType
ListEmptyComponent?: React.ComponentType | React.ReactElement
refreshing?: boolean
onRefresh?: () => void
keyExtractor: (item: TItem) => string
extraData?: unknown
contentContainerStyle?: ContentStyle
onEndReached?: () => void
onEndReachedThreshold?: number
refreshControl?: React.ReactElement<RefreshControlProps> | undefined
getItemType?: (item: TItem, index: number, extraData?: unknown) => string
estimatedItemSize?: number
}

/**
* Performant list for large data set. This offer better performance than BigList.
*
* Warning: Do not use this component on Android as it causes intermittent crash
*/
const FlashList = <T,>({
data,
renderItem,
ItemSeparatorComponent,
ListEmptyComponent,
refreshing,
onRefresh,
keyExtractor,
extraData,
contentContainerStyle,
onEndReached,
onEndReachedThreshold,
refreshControl,
getItemType,
estimatedItemSize
}: AvaListProps<T>) => {
return (
<ShopifyFlashList
data={data}
renderItem={renderItem}
ItemSeparatorComponent={ItemSeparatorComponent}
ListEmptyComponent={ListEmptyComponent}
refreshing={refreshing}
onRefresh={onRefresh}
refreshControl={refreshControl}
contentContainerStyle={contentContainerStyle}
keyExtractor={keyExtractor}
indicatorStyle="white"
getItemType={getItemType}
onEndReached={onEndReached}
onEndReachedThreshold={onEndReachedThreshold}
estimatedItemSize={estimatedItemSize}
extraData={extraData}
/>
)
}

export default FlashList
30 changes: 26 additions & 4 deletions app/screens/shared/ActivityList/Transactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {
Dimensions,
StyleSheet,
View,
ListRenderItemInfo,
FlatList
FlatList,
Platform
} from 'react-native'
import AvaText from 'components/AvaText'
import ActivityListItem from 'screens/activity/ActivityListItem'
Expand All @@ -27,6 +27,7 @@ import { BridgeTransaction } from '@avalabs/bridge-sdk'
import { UI, useIsUIDisabled } from 'hooks/useIsUIDisabled'
import { RefreshControl } from 'components/RefreshControl'
import { usePostCapture } from 'hooks/usePosthogCapture'
import FlashList from 'components/FlashList'

const SCREEN_WIDTH = Dimensions.get('window').width
const BOTTOM_PADDING = SCREEN_WIDTH * 0.3
Expand Down Expand Up @@ -137,7 +138,7 @@ const Transactions = ({
)
}

const renderItem = ({ item }: ListRenderItemInfo<Item>) => {
const renderItem = (item: Item) => {
// render section header
if (typeof item === 'string') {
return renderSectionHeader(item)
Expand Down Expand Up @@ -186,10 +187,31 @@ const Transactions = ({
}

const renderTransactions = () => {
if (Platform.OS === 'ios') {
return (
<FlashList
data={combinedData}
renderItem={item => renderItem(item.item)}
keyExtractor={keyExtractor}
contentContainerStyle={styles.contentContainer}
onEndReached={onEndReached}
onEndReachedThreshold={0.5}
ListEmptyComponent={TransactionsZeroState}
refreshControl={
<RefreshControl onRefresh={onRefresh} refreshing={isRefreshing} />
}
getItemType={(item: Item) => {
return typeof item === 'string' ? 'sectionHeader' : 'row'
}}
estimatedItemSize={71}
/>
)
}

return (
<FlatList
data={combinedData}
renderItem={renderItem}
renderItem={item => renderItem(item.item)}
keyExtractor={keyExtractor}
contentContainerStyle={styles.contentContainer}
onEndReached={onEndReached}
Expand Down
18 changes: 16 additions & 2 deletions app/screens/watchlist/components/WatchList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { StyleSheet, View } from 'react-native'
import { Platform, StyleSheet, View } from 'react-native'
import WatchListItem from 'screens/watchlist/components/WatchListItem'
import { useNavigation } from '@react-navigation/native'
import AppNavigation from 'navigation/AppNavigation'
Expand All @@ -21,6 +21,7 @@ import {
import { DragEndParams } from 'components/draggableList/types'
import DraggableList from 'components/draggableList/DraggableList'
import BigList from 'components/BigList'
import FlashList from 'components/FlashList'
import { WatchlistFilter } from '../types'

const getDisplayValue = (
Expand Down Expand Up @@ -113,9 +114,22 @@ const WatchList: React.FC<Props> = ({
)
}

if (Platform.OS === 'ios') {
return (
<FlashList
data={tokens}
renderItem={item => renderItem(item.item, item.index)}
ListEmptyComponent={EmptyComponent}
refreshing={false}
onRefresh={() => dispatch(onWatchlistRefresh)}
keyExtractor={keyExtractor}
estimatedItemSize={64}
/>
)
}

return (
<BigList
isDraggable={isShowingFavorites}
data={tokens}
renderItem={item => renderItem(item.item, item.index)}
ListEmptyComponent={EmptyComponent}
Expand Down
6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,8 @@ PODS:
- React-Core
- SDWebImage (~> 5.11.1)
- SDWebImageWebPCoder (~> 0.8.4)
- RNFlashList (1.4.3):
- React-Core
- RNFS (2.19.0):
- React-Core
- RNGestureHandler (2.9.0):
Expand Down Expand Up @@ -602,6 +604,7 @@ DEPENDENCIES:
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNDominantColor (from `../node_modules/rn-dominant-color`)
- RNFastImage (from `../node_modules/react-native-fast-image`)
- "RNFlashList (from `../node_modules/@shopify/flash-list`)"
- RNFS (from `../node_modules/react-native-fs`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNInAppBrowser (from `../node_modules/react-native-inappbrowser-reborn`)
Expand Down Expand Up @@ -767,6 +770,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/rn-dominant-color"
RNFastImage:
:path: "../node_modules/react-native-fast-image"
RNFlashList:
:path: "../node_modules/@shopify/flash-list"
RNFS:
:path: "../node_modules/react-native-fs"
RNGestureHandler:
Expand Down Expand Up @@ -877,6 +882,7 @@ SPEC CHECKSUMS:
RNDeviceInfo: 0a7c1d2532aa7691f9b9925a27e43af006db4dae
RNDominantColor: 7c17c31201566a592ba4b2fbe2bb7e00df468753
RNFastImage: 5c9c9fed9c076e521b3f509fe79e790418a544e8
RNFlashList: ade81b4e928ebd585dd492014d40fb8d0e848aab
RNFS: fc610f78fdf8bfc89a9e5cc2f898519f4dba1002
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
RNInAppBrowser: e36d6935517101ccba0e875bac8ad7b0cb655364
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@
"vm-browserify": "0.0.4",
"web3": "1.7.1",
"xss": "1.0.14",
"zod": "3.20.2"
"zod": "3.20.2",
"@shopify/flash-list": "1.4.3"
},
"resolutions": {
"minimist": "1.2.6",
Expand Down
28 changes: 25 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5839,6 +5839,14 @@
xcode "3.0.1"
yargs "^16.2.0"

"@shopify/[email protected]":
version "1.4.3"
resolved "https://registry.yarnpkg.com/@shopify/flash-list/-/flash-list-1.4.3.tgz#b7a4fe03d64f3c5ce9646859b49b9d95307f203d"
integrity sha512-jtIReAbwWzYBV0dQ6Io9wBX+pD0C4qQFMrb5/fkEvX8PYDgBl5KRYvpfr9WLLj8CV2Jsn1X0mYOsB+ysWrI/8g==
dependencies:
recyclerlistview "4.2.0"
tslib "2.4.0"

"@shopify/[email protected]":
version "4.1.2"
resolved "https://registry.yarnpkg.com/@shopify/react-native-performance/-/react-native-performance-4.1.2.tgz#bd111af291b85ee125feaccd54c8e5f237a76ce7"
Expand Down Expand Up @@ -17329,7 +17337,7 @@ [email protected]:
resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9"
integrity sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==

lodash.debounce@^4.0.8:
lodash.debounce@4.0.8, lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
Expand Down Expand Up @@ -20246,7 +20254,7 @@ prompts@^2.0.1, prompts@^2.4.0, prompts@^2.4.2:
kleur "^3.0.3"
sisteransi "^1.0.5"

prop-types@*, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
prop-types@*, prop-types@15.8.1, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
Expand Down Expand Up @@ -21307,6 +21315,15 @@ recursive-readdir@^2.2.2:
dependencies:
minimatch "3.0.4"

[email protected]:
version "4.2.0"
resolved "https://registry.yarnpkg.com/recyclerlistview/-/recyclerlistview-4.2.0.tgz#a140149aaa470c9787a1426452651934240d69ef"
integrity sha512-uuBCi0c+ggqHKwrzPX4Z/mJOzsBbjZEAwGGmlwpD/sD7raXixdAbdJ6BTcAmuWG50Cg4ru9p12M94Njwhr/27A==
dependencies:
lodash.debounce "4.0.8"
prop-types "15.8.1"
ts-object-utils "0.0.5"

[email protected]:
version "2.0.2"
resolved "https://registry.yarnpkg.com/redux-flipper/-/redux-flipper-2.0.2.tgz#5deca22ef81e71253912fdf8a403f272db9ed27f"
Expand Down Expand Up @@ -23560,6 +23577,11 @@ [email protected], ts-node@^10.9.1:
v8-compile-cache-lib "^3.0.1"
yn "3.1.1"

[email protected]:
version "0.0.5"
resolved "https://registry.yarnpkg.com/ts-object-utils/-/ts-object-utils-0.0.5.tgz#95361cdecd7e52167cfc5e634c76345e90a26077"
integrity sha512-iV0GvHqOmilbIKJsfyfJY9/dNHCs969z3so90dQWsO1eMMozvTpnB1MEaUbb3FYtZTGjv5sIy/xmslEz0Rg2TA==

tsconfig-paths@^3.14.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a"
Expand All @@ -23575,7 +23597,7 @@ [email protected], tslib@^1.8.1, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==

tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0:
tslib@2.4.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
Expand Down

0 comments on commit 4bf7c4b

Please sign in to comment.