TP-35796 | initial commit

This commit is contained in:
Varnit Goyal
2023-08-01 17:43:25 +05:30
parent 10737819b6
commit 5c0fb462b5
8 changed files with 96 additions and 25 deletions

View File

@@ -48,11 +48,13 @@
"appcenter-analytics": "^4.4.5",
"appcenter-crashes": "^4.4.5",
"axios": "1.2.1",
"dayjs": "^1.11.9",
"fuzzysort": "2.0.4",
"lottie-react-native": "5.1.4",
"react": "18.1.0",
"react-hook-form": "7.40.0",
"react-native": "0.70.6",
"react-native-blob-util": "0.17.3",
"react-native-call-log": "2.1.2",
"react-native-code-push": "7.1.0",
"react-native-contacts": "7.0.5",
@@ -74,11 +76,10 @@
"react-native-toast-message": "2.1.5",
"react-native-vector-icons": "9.2.0",
"react-native-version-number": "0.3.6",
"react-native-webview": "12.0.2",
"react-redux": "8.0.5",
"redux": "4.2.0",
"redux-persist": "6.0.0",
"react-native-webview": "12.0.2",
"react-native-blob-util": "0.17.3"
"redux-persist": "6.0.0"
},
"devDependencies": {
"@babel/core": "7.12.9",
@@ -102,6 +103,7 @@
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "17.0.0",
"eslint-config-prettier": "^8.8.0",
"eslint-config-prettier-react": "0.0.24",
"eslint-config-standard-with-typescript": "^34.0.1",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-jsx-a11y": "6.6.1",
@@ -117,7 +119,6 @@
"miragejs": "0.1.47",
"prettier": "^2.8.7",
"react-test-renderer": "18.1.0",
"eslint-config-prettier-react": "0.0.24",
"typescript": "4.8.3"
},
"jest": {

View File

@@ -1,22 +1,24 @@
import { ReactNode, useEffect, useRef } from 'react';
import { NativeEventSubscription } from 'react-native';
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 UnstoppableService, {
IForegroundTask,
type IForegroundTask,
} from '../services/foregroundServices/foreground.service';
import useIsOnline from '../hooks/useIsOnline';
import { getSyncTime, sendLocationToServer } from '../hooks/capturingApi';
import { getSyncTime, sendLocationAndActivenessToServer } from '../hooks/capturingApi';
import { isTimeDifferenceWithinRange } from '../components/utlis/commonFunctions';
import { setDeviceGeolocation, setIsTimeSynced } from '../reducer/foregroundServiceSlice';
import { CaptureGeolocation } from '../components/form/services/geoLocation.service';
import { AppState, AppStateStatus } from 'react-native';
import { logError } from '../components/utlis/errorUtils';
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 {
ISyncCaseIdPayload,
ISyncedCases,
type ISyncCaseIdPayload,
type ISyncedCases,
SyncStatus,
fetchCasesToSync,
getCasesSyncStatus,
@@ -25,14 +27,16 @@ 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 { setLockData } from '../reducer/userSlice';
import { setIsActiveUser, setLockData } from '../reducer/userSlice';
import { getConfigData } from '../action/configActions';
import { AppStates } from '../types/appStates';
export enum FOREGROUND_TASKS {
GEOLOCATION = 'GEOLOCATION',
TIME_SYNC = 'TIME_SYNC',
DATA_SYNC = 'DATA_SYNC',
FIRESTORE_FALLBACK = 'FIRESTORE_FALLBACK',
UPDATE_AGENT_ACTIVENESS = 'UPDATE_AGENT_ACTIVENESS',
}
interface ITrackingComponent {
@@ -46,13 +50,16 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
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 {
referenceId,
pendingList = [],
pinnedList = [],
} = useAppSelector((state) => ({
referenceId: state.user.user?.referenceId!!,
referenceId: state.user.user?.referenceId!,
pendingList: state.allCases.pendingList,
pinnedList: state.allCases.pinnedList,
}));
@@ -71,8 +78,8 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
const handleSendGeolocation = async () => {
try {
const location = await CaptureGeolocation.fetchLocation(Date.now() + '', 0, appState.current);
if (location) {
const location = await CaptureGeolocation.fetchLocation(`${Date.now()}`, 0, appState.current);
if (location != null) {
dispatch(
setDeviceGeolocation({
latitude: location.latitude,
@@ -81,7 +88,7 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
})
);
if (user.isLoggedIn) {
await sendLocationToServer(location);
await sendLocationAndActivenessToServer(location, isActive);
}
}
} catch (e: any) {
@@ -121,6 +128,15 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
}
};
const handleUpdateActiveness = async () => {
const foregroundTime = foregroundTimestamp;
const backgroundTime = backgroundTimestamp;
const diff = dayjs(foregroundTime).diff(dayjs(backgroundTime), 'minute');
if (diff <= 10) {
setIsActiveUser(true);
}
};
const tasks: IForegroundTask[] = [
{
taskId: FOREGROUND_TASKS.TIME_SYNC,
@@ -140,6 +156,18 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
delay: 5 * MILLISECONDS_IN_A_MINUTE, // 5 minutes
onLoop: true,
},
{
taskId: FOREGROUND_TASKS.FIRESTORE_FALLBACK,
task: handleGetCaseSyncStatus,
delay: 5 * MILLISECONDS_IN_A_MINUTE, // 5 minutes
onLoop: true,
},
{
taskId: FOREGROUND_TASKS.UPDATE_AGENT_ACTIVENESS,
task: handleUpdateActiveness,
delay: 10 * MILLISECONDS_IN_A_MINUTE, // 10 minutes
onLoop: true,
},
];
if (IS_DATA_SYNC_REQUIRED) {
@@ -153,11 +181,16 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
const handleAppStateChange = async (nextAppState: AppStateStatus) => {
// App comes to foreground from background
if (nextAppState === 'active') {
console.log('next app state', nextAppState);
if (nextAppState === AppStates.ACTIVE) {
setAppForegroundTimestamp(dayjs());
handleGetCaseSyncStatus();
dispatch(getConfigData());
UnstoppableService.start(tasks);
}
if (nextAppState === 'background') {
setAppBackgroundTimestamp(dayjs());
}
appState.current = nextAppState;
};
@@ -183,10 +216,8 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
if (isOnline) {
appStateSubscription = AppState.addEventListener('change', handleAppStateChange);
UnstoppableService.start(tasks);
} else {
if (UnstoppableService.isRunning()) {
UnstoppableService.stopAll();
}
} else if (UnstoppableService.isRunning()) {
UnstoppableService.stopAll();
}
return () => {
appStateSubscription?.remove();

View File

@@ -1,7 +1,10 @@
import { GeoCoordinates } from 'react-native-geolocation-service';
import axiosInstance, { ApiKeys, getApiUrl } from '../components/utlis/apiHelper';
export const sendLocationToServer = async (location: GeoCoordinates) => {
export const sendLocationAndActivenessToServer = async (
location: GeoCoordinates,
isActive: boolean
) => {
try {
const response = await axiosInstance.post(
getApiUrl(ApiKeys.SEND_LOCATION),

View File

@@ -12,6 +12,11 @@ export interface User {
sessionToken: string;
}
export interface AppState {
appForegroundTimestamp: string;
appBackgroundTimestamp: string;
}
export interface CommonState {
userData: User;
clickstreamEvents: IClickstreamEvents[];

View File

@@ -1,4 +1,5 @@
import { createSlice } from '@reduxjs/toolkit';
export interface UninstallInformation {
last_operational_time: any;
reinstall_endpoint: string;
@@ -8,12 +9,16 @@ interface IMetadata {
isOnline: boolean;
forceUninstall: Record<string, UninstallInformation>;
isWifiOrCellularOn: boolean;
appForegroundTimestamp: string;
appBackgroundTimestamp: string;
}
const initialState = {
isOnline: true,
forceUninstall: {},
isWifiOrCellularOn: true,
appForegroundTimestamp: '',
appBackgroundTimestamp: '',
} as IMetadata;
const MetadataSlice = createSlice({
@@ -29,9 +34,21 @@ 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 } = MetadataSlice.actions;
export const {
setIsOnline,
setForceUninstallData,
setIsWifiOrCellularOn,
setAppForegroundTimestamp,
setAppBackgroundTimestamp,
} = MetadataSlice.actions;
export default MetadataSlice.reducer;

View File

@@ -16,11 +16,13 @@ interface IUserDetails {
referenceId: string;
phoneNumber: string;
realms: string[];
roles: Array<IUserRole>;
roles: IUserRole[];
groups: string[];
name: string;
createdAt: string;
updatedAt: string;
// check weather user is recently active on app or not
isActive: boolean;
}
export interface IUser {
@@ -86,9 +88,12 @@ export const userSlice = createSlice({
state.lock = action.payload;
}
},
setIsActiveUser: (state, action) => {
state.user.isActive = action.payload;
},
},
});
export const { setAuthData, setDeviceId, setLockData } = userSlice.actions;
export const { setAuthData, setDeviceId, setLockData, setIsActiveUser } = userSlice.actions;
export default userSlice.reducer;

4
src/types/appStates.ts Normal file
View File

@@ -0,0 +1,4 @@
export enum AppStates {
ACTIVE = 'active',
BACKGROUND = 'background',
}

View File

@@ -3399,6 +3399,11 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
dayjs@^1.11.9:
version "1.11.9"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a"
integrity sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==
dayjs@^1.8.15:
version "1.11.7"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2"