From 608282672fcd7d92e6285e7295150a7005ffeb02 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 25 Apr 2026 01:24:48 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Optimize=20date=20filtering?= =?UTF-8?q?=20and=20FlatList=20rendering=20in=20FlightScreen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: TargetMisser <52361977+TargetMisser@users.noreply.github.com> --- .jules/bolt.md | 6 +++--- src/screens/FlightScreen.tsx | 26 +++++++++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index e37d378..db134a6 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -1,3 +1,3 @@ -## 2024-04-13 - Missing React.memo for FlatList Items -**Learning:** The React Native FlatList components in this codebase frequently render unmemoized inline items (like `ContactRow`, `PasswordRow`, etc.), causing unnecessary re-renders of the entire list when individual state changes. -**Action:** Always wrap long list item components in `React.memo()` to prevent cascading re-renders and improve FlatList scrolling performance. +## 2024-05-18 - React Native Date Instantiation in Array Filters +**Learning:** Instantiating `Date` objects inside high-frequency loops (like `Array.prototype.filter`) on large arrays in React Native significantly degrades performance because of garbage collection. +**Action:** Always pre-calculate day boundaries as Unix timestamps outside the loop and use simple numeric comparisons (e.g., `ts >= startTs && ts < endTs`) to filter time-series data. diff --git a/src/screens/FlightScreen.tsx b/src/screens/FlightScreen.tsx index 7b37ca6..16f74d8 100644 --- a/src/screens/FlightScreen.tsx +++ b/src/screens/FlightScreen.tsx @@ -538,21 +538,28 @@ export default function FlightScreen() { }, []); const userShift = activeDay === 'today' ? shifts.today : shifts.tomorrow; - const selectedDate = activeDay === 'today' ? new Date() : (() => { const d = new Date(); d.setDate(d.getDate() + 1); return d; })(); - const isSameDay = (d1: Date, d2: Date) => - d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate(); - - const currentData = (() => { + const currentData = useMemo(() => { const source = filterMode === 'all' ? (activeTab === 'arrivals' ? allArrivalsFull : allDeparturesFull) : (activeTab === 'arrivals' ? arrivals : departures); + + // ⚡ Bolt: Pre-calculate boundaries to avoid instantiating Date objects in the high-frequency filter loop + const d = new Date(); + if (activeDay !== 'today') d.setDate(d.getDate() + 1); + + const startOfDay = new Date(d.getFullYear(), d.getMonth(), d.getDate()); + const endOfDay = new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1); + + const startTs = Math.floor(startOfDay.getTime() / 1000); + const endTs = Math.floor(endOfDay.getTime() / 1000); + return source.filter(item => { const ts = activeTab === 'arrivals' ? item.flight?.time?.scheduled?.arrival : item.flight?.time?.scheduled?.departure; - return ts && isSameDay(new Date(ts * 1000), selectedDate); + return ts && ts >= startTs && ts < endTs; }); - })(); + }, [filterMode, activeTab, arrivals, departures, allArrivalsFull, allDeparturesFull, activeDay]); const renderFlight = useCallback(({ item }: { item: any }) => { const flightNumber = item.flight?.identification?.number?.default || 'N/A'; @@ -818,6 +825,11 @@ export default function FlightScreen() { refreshControl={ { setRefreshing(true); fetchAll(); }} tintColor={colors.primary} />} ListEmptyComponent={{t('flightNoFlights')}} showsVerticalScrollIndicator={false} + // ⚡ Bolt: Virtualization settings for long lists to improve memory and render speed + initialNumToRender={10} + windowSize={5} + maxToRenderPerBatch={10} + removeClippedSubviews={true} /> )}