From 2b8a91db4f8b44b6d9995431cb1a66fd062eb3d1 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Fri, 7 Nov 2025 11:48:54 +0100 Subject: [PATCH 1/3] fix whitespace --- app/src/components/PointHistoryList.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/components/PointHistoryList.tsx b/app/src/components/PointHistoryList.tsx index c95ba7dc0..f5ab029c0 100644 --- a/app/src/components/PointHistoryList.tsx +++ b/app/src/components/PointHistoryList.tsx @@ -348,6 +348,7 @@ const styles = StyleSheet.create({ justifyContent: 'center', alignItems: 'center', paddingHorizontal: 20, + paddingTop: 5, }, }); From 517e7e1a05dbc81b29d230b36b10e4d8e0038a85 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Fri, 7 Nov 2025 11:54:49 +0100 Subject: [PATCH 2/3] move effects for fetching points and incoming points to hooks, add items to deps array so that they refresh when we expect points to change. --- app/src/components/NavBar/Points.tsx | 34 +++------------ app/src/hooks/usePoints.ts | 65 ++++++++++++++++++++++++++++ app/src/screens/home/HomeScreen.tsx | 4 +- 3 files changed, 73 insertions(+), 30 deletions(-) create mode 100644 app/src/hooks/usePoints.ts diff --git a/app/src/components/NavBar/Points.tsx b/app/src/components/NavBar/Points.tsx index f21848b8b..8e2f545fe 100644 --- a/app/src/components/NavBar/Points.tsx +++ b/app/src/components/NavBar/Points.tsx @@ -11,6 +11,7 @@ import { useFocusEffect, useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { PointHistoryList } from '@/components/PointHistoryList'; +import { useIncomingPoints, usePoints } from '@/hooks/usePoints'; import BellWhiteIcon from '@/images/icons/bell_white.svg'; import ClockIcon from '@/images/icons/clock.svg'; import LockWhiteIcon from '@/images/icons/lock_white.svg'; @@ -36,24 +37,17 @@ import { } from '@/utils/notifications/notificationService'; import { formatTimeUntilDate, - getIncomingPoints, - getPointsAddress, - getTotalPoints, - type IncomingPoints, recordBackupPointEvent, recordNotificationPointEvent, } from '@/utils/points'; const Points: React.FC = () => { - const [selfPoints, setSelfPoints] = useState(0); const { bottom } = useSafeAreaInsets(); const navigation = useNavigation>(); const [isNovaSubscribed, setIsNovaSubscribed] = useState(false); const [isEnabling, setIsEnabling] = useState(false); - const [incomingPoints, setIncomingPoints] = useState( - null, - ); + const incomingPoints = useIncomingPoints(); const loadEvents = usePointEventStore(state => state.loadEvents); const { hasCompletedBackupForPoints, setBackupForPointsCompleted } = useSettingStore(); @@ -85,14 +79,7 @@ const Points: React.FC = () => { loadEvents(); }, [loadEvents]); - useEffect(() => { - const fetchPoints = async () => { - const address = await getPointsAddress(); - const points = await getTotalPoints(address); - setSelfPoints(points); - }; - fetchPoints(); - }, []); + const points = usePoints(); useEffect(() => { const checkSubscription = async () => { @@ -102,14 +89,6 @@ const Points: React.FC = () => { checkSubscription(); }, []); - useEffect(() => { - const fetchIncomingPoints = async () => { - const incoming = await getIncomingPoints(); - setIncomingPoints(incoming); - }; - fetchIncomingPoints(); - }, []); - const handleContentLayout = () => { if (!isContentReady) { setIsContentReady(true); @@ -211,15 +190,12 @@ const Points: React.FC = () => { setIsBackingUp(true); try { + // this will add event to store and the new event will then trigger useIncomingPoints hook to refetch incoming points const response = await recordBackupPointEvent(); if (response.success) { setBackupForPointsCompleted(); - const address = await getPointsAddress(); - const points = await getTotalPoints(address); - setSelfPoints(points); - if (listRefreshRef.current) { await listRefreshRef.current(); } @@ -302,7 +278,7 @@ const Points: React.FC = () => { lineHeight={32} letterSpacing={-1} > - {`${selfPoints} Self `} + {`${points} Self `} { + const [incomingPoints, setIncomingPoints] = useState( + null, + ); + const pointEvents = usePointEventStore(state => state.events); + const pointEventsCount = pointEvents.length; + + useEffect(() => { + const fetchIncomingPoints = async () => { + try { + const points = await getIncomingPoints(); + setIncomingPoints(points); + } catch (error) { + console.error('Error fetching incoming points:', error); + } + }; + fetchIncomingPoints(); + // when we record a new point event, we want to refetch incoming points + }, [pointEventsCount]); + + return incomingPoints; +}; + +/* + * Hook to fetch total points for the user. It refetches the total points when the next points update time is reached (each Sunday noon UTC). + */ +export const usePoints = () => { + const [truePoints, setTruePoints] = useState({ + points: 0, + }); + const nextPointsUpdate = getNextSundayNoonUTC().getTime(); + + useEffect(() => { + const fetchPoints = async () => { + try { + const address = await getPointsAddress(); + const points = await getTotalPoints(address); + setTruePoints({ points }); + } catch (error) { + console.error('Error fetching total points:', error); + } + }; + fetchPoints(); + return () => { + setTruePoints(prev => ({ ...prev, isRefetching: false })); + }; + // refresh when points update time changes as its the only time points can change + }, [nextPointsUpdate]); + + return truePoints.points; +}; diff --git a/app/src/screens/home/HomeScreen.tsx b/app/src/screens/home/HomeScreen.tsx index 15a14a829..7d2355587 100644 --- a/app/src/screens/home/HomeScreen.tsx +++ b/app/src/screens/home/HomeScreen.tsx @@ -24,6 +24,7 @@ import IdCardLayout from '@/components/homeScreen/idCard'; import { useAppUpdates } from '@/hooks/useAppUpdates'; import useConnectionModal from '@/hooks/useConnectionModal'; import { useEarnPointsFlow } from '@/hooks/useEarnPointsFlow'; +import { usePoints } from '@/hooks/usePoints'; import { useReferralConfirmation } from '@/hooks/useReferralConfirmation'; import { useTestReferralFlow } from '@/hooks/useTestReferralFlow'; import LogoInversed from '@/images/logo_inversed.svg'; @@ -52,7 +53,8 @@ const HomeScreen: React.FC = () => { Record >({}); const [loading, setLoading] = useState(true); - const [selfPoints] = useState(312); + + const selfPoints = usePoints(); // Calculate card dimensions exactly like IdCardLayout does const { width: screenWidth } = Dimensions.get('window'); From d7a78eaaea778237e8384a6131f011cfbd5d5e11 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Fri, 7 Nov 2025 12:08:18 +0100 Subject: [PATCH 3/3] cleanup --- app/src/components/NavBar/Points.tsx | 12 ++---------- app/src/hooks/usePoints.ts | 3 --- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/app/src/components/NavBar/Points.tsx b/app/src/components/NavBar/Points.tsx index 8e2f545fe..8262998cc 100644 --- a/app/src/components/NavBar/Points.tsx +++ b/app/src/components/NavBar/Points.tsx @@ -272,22 +272,14 @@ const Points: React.FC = () => { - {`${points} Self `} - - - points + {`${points} Self points`} { } }; fetchPoints(); - return () => { - setTruePoints(prev => ({ ...prev, isRefetching: false })); - }; // refresh when points update time changes as its the only time points can change }, [nextPointsUpdate]);