From d7ce59de3a8eabe2df2a5ee0fe1dd6c6c20ed39e Mon Sep 17 00:00:00 2001 From: Varnit Goyal Date: Wed, 2 Aug 2023 13:32:18 +0530 Subject: [PATCH] TP-35796 | replaced redux with async storage --- src/common/TrackingComponent.tsx | 61 ++++++++++++++++++++------- src/components/utlis/storageHelper.ts | 6 +++ src/hooks/capturingApi.ts | 3 +- src/reducer/metadataSlice.ts | 18 +------- src/reducer/userSlice.ts | 7 +-- src/types/storageKeys.ts | 5 +++ 6 files changed, 60 insertions(+), 40 deletions(-) create mode 100644 src/components/utlis/storageHelper.ts create mode 100644 src/types/storageKeys.ts diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index 9954e7df..678e1738 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -2,6 +2,7 @@ import { type ReactNode, useEffect, useRef } from 'react'; import { type NativeEventSubscription, AppState, type AppStateStatus } from 'react-native'; import dayJs from 'dayjs'; import dayjs from 'dayjs'; +import { setItem, getItem } from '../components/utlis/storageHelper'; import UnstoppableService, { type IForegroundTask, } from '../services/foregroundServices/foreground.service'; @@ -15,7 +16,6 @@ import { useAppDispatch, useAppSelector } from '../hooks'; import { dataSyncService } from '../services/dataSync.service'; import { DATA_SYNC_TIME_INTERVAL, IS_DATA_SYNC_REQUIRED } from '../constants/config'; import useIsLocationEnabled from '../hooks/useIsLocationEnabled'; -import { setAppForegroundTimestamp, setAppBackgroundTimestamp } from '../reducer/metadataSlice'; import { type ISyncCaseIdPayload, type ISyncedCases, @@ -27,9 +27,10 @@ import { import { getSyncCaseIds } from '../components/utlis/firebaseFallbackUtils'; import { syncCasesByFallback } from '../reducer/allCasesSlice'; import { MILLISECONDS_IN_A_MINUTE } from '../../RN-UI-LIB/src/utlis/common'; -import { setIsActiveUser, setLockData } from '../reducer/userSlice'; +import { setLockData } from '../reducer/userSlice'; import { getConfigData } from '../action/configActions'; import { AppStates } from '../types/appStates'; +import { StorageKeys } from '../types/storageKeys'; export enum FOREGROUND_TASKS { GEOLOCATION = 'GEOLOCATION', @@ -44,15 +45,15 @@ interface ITrackingComponent { } let LAST_SYNC_STATUS = 'SKIP'; +const ACTIVITY_TIME_ON_APP = 5; // 5 seconds +const ACTIVITY_TIME_WINDOW = 10; // 10 minutes const TrackingComponent: React.FC = ({ children }) => { const isOnline = useIsOnline(); const dispatch = useAppDispatch(); const appState = useRef(AppState.currentState); const user = useAppSelector((state) => state.user); - const foregroundTimestamp = useAppSelector((state) => state.metadata.appForegroundTimestamp); - const backgroundTimestamp = useAppSelector((state) => state.metadata.appBackgroundTimestamp); - const isActive = useAppSelector((state) => state.user.user.isActive); + const isActive = useAppSelector((state) => state?.user?.user?.isActive); const { referenceId, @@ -88,7 +89,9 @@ const TrackingComponent: React.FC = ({ children }) => { }) ); if (user.isLoggedIn) { - await sendLocationAndActivenessToServer(location, isActive); + const isUserActive: string | boolean = + (await getItem(StorageKeys.IS_USER_ACTIVE)) || false; + await sendLocationAndActivenessToServer(location, Boolean(isUserActive)); } } } catch (e: any) { @@ -129,12 +132,38 @@ const TrackingComponent: React.FC = ({ children }) => { }; const handleUpdateActiveness = async () => { - const foregroundTime = foregroundTimestamp; - const backgroundTime = backgroundTimestamp; - const diff = dayjs(foregroundTime).diff(dayjs(backgroundTime), 'minute'); - if (diff <= 10) { - setIsActiveUser(true); + const foregroundTimestamp = await getItem(StorageKeys.APP_FOREGROUND_TIMESTAMP); + const backgroundTimestamp = await getItem(StorageKeys.APP_BACKGROUND_TIMESTAMP); + const foregroundTime = dayjs(foregroundTimestamp); + const backgroundTime = dayjs(backgroundTimestamp); + const diffBetweenBackgroundAndForegroundTime = dayJs(backgroundTime).diff( + foregroundTime, + 'seconds' + ); + const diffBetweenCurrentTimeAndForegroundTime = + dayjs().diff(foregroundTime, 'minutes') < 0 ? 0 : dayjs().diff(foregroundTime, 'minutes'); + const isForegroundTimeWithInRange = + diffBetweenCurrentTimeAndForegroundTime <= ACTIVITY_TIME_WINDOW; + const isForegroundTimeAfterBackground = dayjs(foregroundTimestamp).isAfter(backgroundTimestamp); + console.log({ + diffBetweenBackgroundAndForegroundTime, + diffBetweenCurrentTimeAndForegroundTime, + isForegroundTimeWithInRange, + isForegroundTimeAfterBackground, + dayjs: dayjs().toString(), + }); + if (isForegroundTimeWithInRange) { + if ( + isForegroundTimeAfterBackground || + diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP + ) { + await setItem(StorageKeys.IS_USER_ACTIVE, 'true'); + return; + } + await setItem(StorageKeys.IS_USER_ACTIVE, 'false'); } + await setItem(StorageKeys.IS_USER_ACTIVE, 'false'); + return; }; const tasks: IForegroundTask[] = [ @@ -165,7 +194,7 @@ const TrackingComponent: React.FC = ({ children }) => { { taskId: FOREGROUND_TASKS.UPDATE_AGENT_ACTIVENESS, task: handleUpdateActiveness, - delay: 10 * MILLISECONDS_IN_A_MINUTE, // 10 minutes + delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes onLoop: true, }, ]; @@ -181,15 +210,15 @@ const TrackingComponent: React.FC = ({ children }) => { const handleAppStateChange = async (nextAppState: AppStateStatus) => { // App comes to foreground from background - console.log('next app state', nextAppState); + const now = dayjs().toString(); if (nextAppState === AppStates.ACTIVE) { - setAppForegroundTimestamp(dayjs()); + await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, now); handleGetCaseSyncStatus(); dispatch(getConfigData()); UnstoppableService.start(tasks); } - if (nextAppState === 'background') { - setAppBackgroundTimestamp(dayjs()); + if (nextAppState === AppStates.BACKGROUND) { + await setItem(StorageKeys.APP_BACKGROUND_TIMESTAMP, now); } appState.current = nextAppState; }; diff --git a/src/components/utlis/storageHelper.ts b/src/components/utlis/storageHelper.ts new file mode 100644 index 00000000..5adec04f --- /dev/null +++ b/src/components/utlis/storageHelper.ts @@ -0,0 +1,6 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; + +export const setItem = async (key: string, value: string): Promise => { + await AsyncStorage.setItem(key, value); +}; +export const getItem = async (key: string): Promise => await AsyncStorage.getItem(key); diff --git a/src/hooks/capturingApi.ts b/src/hooks/capturingApi.ts index daaf0fb7..329ca391 100644 --- a/src/hooks/capturingApi.ts +++ b/src/hooks/capturingApi.ts @@ -1,4 +1,4 @@ -import { GeoCoordinates } from 'react-native-geolocation-service'; +import { type GeoCoordinates } from 'react-native-geolocation-service'; import axiosInstance, { ApiKeys, getApiUrl } from '../components/utlis/apiHelper'; export const sendLocationAndActivenessToServer = async ( @@ -14,6 +14,7 @@ export const sendLocationAndActivenessToServer = async ( longitude: location?.longitude, accuracy: location?.accuracy, timestamp: new Date().getTime(), + isUserActive: isActive, }, ], { diff --git a/src/reducer/metadataSlice.ts b/src/reducer/metadataSlice.ts index 3b75b2a4..d099d428 100644 --- a/src/reducer/metadataSlice.ts +++ b/src/reducer/metadataSlice.ts @@ -9,16 +9,12 @@ interface IMetadata { isOnline: boolean; forceUninstall: Record; isWifiOrCellularOn: boolean; - appForegroundTimestamp: string; - appBackgroundTimestamp: string; } const initialState = { isOnline: true, forceUninstall: {}, isWifiOrCellularOn: true, - appForegroundTimestamp: '', - appBackgroundTimestamp: '', } as IMetadata; const MetadataSlice = createSlice({ @@ -34,21 +30,9 @@ const MetadataSlice = createSlice({ setIsWifiOrCellularOn: (state, action) => { state.isWifiOrCellularOn = action.payload; }, - setAppForegroundTimestamp: (state, action) => { - state.appForegroundTimestamp = action.payload; - }, - setAppBackgroundTimestamp: (state, action) => { - state.appBackgroundTimestamp = action.payload; - }, }, }); -export const { - setIsOnline, - setForceUninstallData, - setIsWifiOrCellularOn, - setAppForegroundTimestamp, - setAppBackgroundTimestamp, -} = MetadataSlice.actions; +export const { setIsOnline, setForceUninstallData, setIsWifiOrCellularOn } = MetadataSlice.actions; export default MetadataSlice.reducer; diff --git a/src/reducer/userSlice.ts b/src/reducer/userSlice.ts index 5b335e18..55f3e75c 100644 --- a/src/reducer/userSlice.ts +++ b/src/reducer/userSlice.ts @@ -21,8 +21,6 @@ interface IUserDetails { name: string; createdAt: string; updatedAt: string; - // check weather user is recently active on app or not - isActive: boolean; } export interface IUser { @@ -88,12 +86,9 @@ export const userSlice = createSlice({ state.lock = action.payload; } }, - setIsActiveUser: (state, action) => { - state.user.isActive = action.payload; - }, }, }); -export const { setAuthData, setDeviceId, setLockData, setIsActiveUser } = userSlice.actions; +export const { setAuthData, setDeviceId, setLockData } = userSlice.actions; export default userSlice.reducer; diff --git a/src/types/storageKeys.ts b/src/types/storageKeys.ts new file mode 100644 index 00000000..c18bd31d --- /dev/null +++ b/src/types/storageKeys.ts @@ -0,0 +1,5 @@ +export enum StorageKeys { + APP_FOREGROUND_TIMESTAMP = 'appForegroundTimestamp', + APP_BACKGROUND_TIMESTAMP = 'appBackgroundTimestamp', + IS_USER_ACTIVE = 'isUserActive', +}