11import React , { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
2- import { ActivityIndicator , RefreshControl , StatusBar } from 'react-native' ;
2+ import { ActivityIndicator , AppState , RefreshControl , StatusBar } from 'react-native' ;
33import Animated , {
44 LinearTransition ,
55 runOnJS ,
@@ -22,7 +22,12 @@ import {
2222import { ActionTabs , BottomSheetBackdrop , BottomSheetWrapper } from '@/components-next' ;
2323
2424import { EmptyStateIcon } from '@/svg-icons' ;
25- import { TAB_BAR_HEIGHT } from '@/constants' ;
25+ import {
26+ SCREENS ,
27+ TAB_BAR_HEIGHT ,
28+ LAST_ACTIVE_TIMESTAMP_KEY ,
29+ LAST_ACTIVE_TIMESTAMP_THRESHOLD ,
30+ } from '@/constants' ;
2631import {
2732 ConversationListStateProvider ,
2833 useConversationListStateContext ,
@@ -52,6 +57,11 @@ import { clearAssignableAgents } from '@/store/assignable-agent/assignableAgentS
5257
5358import i18n from '@/i18n' ;
5459import ActionBottomSheet from '@/navigation/tabs/ActionBottomSheet' ;
60+ import { getCurrentRouteName } from '@/utils/navigationUtils' ;
61+ import AsyncStorage from '@react-native-async-storage/async-storage' ;
62+
63+ // The screen list thats need to be checked for refreshing the conversations list
64+ const REFRESH_SCREEN_LIST = [ SCREENS . CONVERSATION , SCREENS . INBOX , SCREENS . SETTINGS ] ;
5565
5666const AnimatedFlashList = Animated . createAnimatedComponent ( FlashList ) ;
5767
@@ -62,6 +72,7 @@ type FlashListRenderItemType = {
6272
6373const ConversationList = ( ) => {
6474 const dispatch = useAppDispatch ( ) ;
75+ const [ appState , setAppState ] = useState ( AppState . currentState ) ;
6576
6677 // This is used to prevent the infinite scrolling before the list is ready
6778 const [ isFlashListReady , setFlashListReady ] = useState ( false ) ;
@@ -93,6 +104,11 @@ const ConversationList = () => {
93104 const filters = useAppSelector ( selectFilters ) ;
94105 const previousFilters = useRef ( filters ) ;
95106
107+ // Reset last active timestamp when the conversation screen is opened
108+ useEffect ( ( ) => {
109+ AsyncStorage . removeItem ( LAST_ACTIVE_TIMESTAMP_KEY ) ;
110+ } , [ ] ) ;
111+
96112 useEffect ( ( ) => {
97113 if ( previousFilters . current !== filters ) {
98114 previousFilters . current = filters ;
@@ -136,6 +152,40 @@ const ConversationList = () => {
136152 } ) ;
137153 } , [ clearAndFetchConversations , filters ] ) ;
138154
155+ const checkAppStateAndFetchConversations = useCallback ( async ( ) => {
156+ const lastActiveTimestamp = await AsyncStorage . getItem ( LAST_ACTIVE_TIMESTAMP_KEY ) ;
157+ if ( lastActiveTimestamp ) {
158+ const currentTimestamp = Date . now ( ) ;
159+ const difference = currentTimestamp - parseInt ( lastActiveTimestamp ) ;
160+ if ( difference > LAST_ACTIVE_TIMESTAMP_THRESHOLD ) {
161+ clearAndFetchConversations ( filters ) ;
162+ }
163+ }
164+ } , [ clearAndFetchConversations , filters ] ) ;
165+
166+ // Update conversations when app comes to foreground from background
167+ useEffect ( ( ) => {
168+ const appStateListener = AppState . addEventListener ( 'change' , nextAppState => {
169+ if ( appState . match ( / i n a c t i v e | b a c k g r o u n d / ) && nextAppState === 'active' ) {
170+ const routeName = getCurrentRouteName ( ) ;
171+ if ( routeName && REFRESH_SCREEN_LIST . includes ( routeName ) ) {
172+ checkAppStateAndFetchConversations ( ) ;
173+ }
174+ }
175+
176+ if ( appState === 'active' && nextAppState . match ( / i n a c t i v e | b a c k g r o u n d / ) ) {
177+ // App is going to background
178+ const currentTimestamp = Date . now ( ) ;
179+ AsyncStorage . setItem ( LAST_ACTIVE_TIMESTAMP_KEY , currentTimestamp . toString ( ) ) ;
180+ }
181+
182+ setAppState ( nextAppState ) ;
183+ } ) ;
184+ return ( ) => {
185+ appStateListener ?. remove ( ) ;
186+ } ;
187+ } , [ appState , checkAppStateAndFetchConversations , clearAndFetchConversations , filters ] ) ;
188+
139189 const fetchConversations = useCallback (
140190 async ( filters : FilterState , page : number = 1 ) => {
141191 const conversationFilters = {
0 commit comments