From c1bdc0e4e6c5c011d62a2fc8f2a1822b04f44a41 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 07:47:57 +0000 Subject: [PATCH 1/3] Initial plan From 121ebfcc069828196c9aa4633a275267f5bc7b73 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 07:54:46 +0000 Subject: [PATCH 2/3] fix: resolve home screen lag with memoization and FlatList optimizations Agent-Logs-Url: https://github.com/prince-d-simform/AI-spec/sessions/d50f284e-f7c1-4c37-b1fb-1e6e9bee53ef Co-authored-by: prince-d-simform <104822674+prince-d-simform@users.noreply.github.com> --- app/modules/home/HomeScreen.tsx | 41 ++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/app/modules/home/HomeScreen.tsx b/app/modules/home/HomeScreen.tsx index f46cc2c..3039acb 100755 --- a/app/modules/home/HomeScreen.tsx +++ b/app/modules/home/HomeScreen.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, type FC } from 'react'; +import React, { useCallback, useMemo, type FC } from 'react'; import { FlatList, ScrollView, View } from 'react-native'; import { CustomButton, Spinner, Text } from '../../components'; import { Strings } from '../../constants'; @@ -190,11 +190,29 @@ const HomeScreen: FC = (): React.ReactElement => { ); }, [shouldShowRefreshError, styles.productStatusContainer, styles.productStatusText]); - const productFeedback = - renderCategoryProductsLoadingState() || - renderCategoryProductRetryState() || - renderProductsLoadingState() || - renderProductRetryState(); + const productFeedback = useMemo( + () => + renderCategoryProductsLoadingState() || + renderCategoryProductRetryState() || + renderProductsLoadingState() || + renderProductRetryState(), + [ + renderCategoryProductsLoadingState, + renderCategoryProductRetryState, + renderProductsLoadingState, + renderProductRetryState + ] + ); + + const flatListContentContainerStyle = useMemo( + () => [styles.grid, filteredProducts.length === 0 ? styles.gridEmptyContent : undefined], + [filteredProducts.length, styles.grid, styles.gridEmptyContent] + ); + + const flatListColumnWrapperStyle = useMemo( + () => (filteredProducts.length > 0 ? styles.columnWrapper : undefined), + [filteredProducts.length, styles.columnWrapper] + ); return ( @@ -214,13 +232,14 @@ const HomeScreen: FC = (): React.ReactElement => { {productFeedback || ( removeClippedSubviews - columnWrapperStyle={filteredProducts.length > 0 ? styles.columnWrapper : undefined} - contentContainerStyle={[ - styles.grid, - filteredProducts.length === 0 ? styles.gridEmptyContent : undefined - ]} + columnWrapperStyle={flatListColumnWrapperStyle} + contentContainerStyle={flatListContentContainerStyle} data={filteredProducts} + // Covers ~3 visible rows in the 2-column grid without over-rendering on first paint. + initialNumToRender={6} ListEmptyComponent={renderEmptyState} + // Render 2 rows per JS frame during scroll to reduce JS thread pressure. + maxToRenderPerBatch={4} numColumns={2} windowSize={5} keyExtractor={keyExtractor} From f543424cfb0d37785aa2a5bb2fee6c85618cc08e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:20:53 +0000 Subject: [PATCH 3/3] fix: replace FlatList with FlashList on home screen Agent-Logs-Url: https://github.com/prince-d-simform/AI-spec/sessions/cf2a3ba1-5ef2-4263-8d9e-c74de5fd6985 Co-authored-by: prince-d-simform <104822674+prince-d-simform@users.noreply.github.com> --- app/modules/home/HomeScreen.tsx | 26 +++++++++----------------- app/modules/home/HomeStyles.ts | 6 +----- package.json | 1 + 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/app/modules/home/HomeScreen.tsx b/app/modules/home/HomeScreen.tsx index 3039acb..8b8bf10 100755 --- a/app/modules/home/HomeScreen.tsx +++ b/app/modules/home/HomeScreen.tsx @@ -1,8 +1,10 @@ import React, { useCallback, useMemo, type FC } from 'react'; -import { FlatList, ScrollView, View } from 'react-native'; +import { ScrollView, View } from 'react-native'; +import { FlashList } from '@shopify/flash-list'; import { CustomButton, Spinner, Text } from '../../components'; import { Strings } from '../../constants'; import { useTheme } from '../../hooks'; +import { scale } from '../../theme'; import styleSheet from './HomeStyles'; import { CategoryChip } from './sub-components/category-chip'; import { CategoryChipShimmer } from './sub-components/category-chip-shimmer'; @@ -17,7 +19,7 @@ import type { Category, Product } from './HomeTypes'; * SafeAreaView (screenBackground) * └── HomeHeader (branded greeting) * └── ScrollView horizontal (category chip row — sticky) - * └── FlatList numColumns={2} (product grid or empty state) + * └── FlashList numColumns={2} (product grid or empty state) * * All state and logic delegated to useHome(). */ @@ -204,16 +206,11 @@ const HomeScreen: FC = (): React.ReactElement => { ] ); - const flatListContentContainerStyle = useMemo( + const flashListContentContainerStyle = useMemo( () => [styles.grid, filteredProducts.length === 0 ? styles.gridEmptyContent : undefined], [filteredProducts.length, styles.grid, styles.gridEmptyContent] ); - const flatListColumnWrapperStyle = useMemo( - () => (filteredProducts.length > 0 ? styles.columnWrapper : undefined), - [filteredProducts.length, styles.columnWrapper] - ); - return ( @@ -230,18 +227,13 @@ const HomeScreen: FC = (): React.ReactElement => { {renderCategoryStatus()} {renderProductStatus()} {productFeedback || ( - - removeClippedSubviews - columnWrapperStyle={flatListColumnWrapperStyle} - contentContainerStyle={flatListContentContainerStyle} + + contentContainerStyle={flashListContentContainerStyle} data={filteredProducts} - // Covers ~3 visible rows in the 2-column grid without over-rendering on first paint. - initialNumToRender={6} + // Estimated height of a ProductCard in the 2-column grid (image + info section), scaled to device. + estimatedItemSize={scale(300)} ListEmptyComponent={renderEmptyState} - // Render 2 rows per JS frame during scroll to reduce JS thread pressure. - maxToRenderPerBatch={4} numColumns={2} - windowSize={5} keyExtractor={keyExtractor} refreshing={activeCategory === 'all' ? isProductsRefreshing : false} renderItem={renderProductItem} diff --git a/app/modules/home/HomeStyles.ts b/app/modules/home/HomeStyles.ts index bf3ea3c..a27be51 100755 --- a/app/modules/home/HomeStyles.ts +++ b/app/modules/home/HomeStyles.ts @@ -27,10 +27,6 @@ const styles = (theme: ThemeMode) => paddingHorizontal: scale(10), paddingTop: scale(4) }, - /** columnWrapperStyle for the 2-column FlatList */ - columnWrapper: { - justifyContent: 'space-between' - }, /** Empty-state container — centred vertically */ emptyContainer: { alignItems: 'center', @@ -56,7 +52,7 @@ const styles = (theme: ThemeMode) => fontSize: scale(15), textAlign: 'center' }, - /** FlatList contentContainerStyle */ + /** FlashList contentContainerStyle */ grid: { paddingBottom: scale(24), paddingHorizontal: scale(8) diff --git a/package.json b/package.json index 765a872..f862d91 100755 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "preset": "jest-expo" }, "dependencies": { + "@shopify/flash-list": "2.3.1", "@expo/config-plugins": "54.0.1", "@expo-google-fonts/rubik": "0.4.2", "@expo/vector-icons": "15.0.2",