TP-35796 | initial commit
This commit is contained in:
@@ -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": {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -12,6 +12,11 @@ export interface User {
|
||||
sessionToken: string;
|
||||
}
|
||||
|
||||
export interface AppState {
|
||||
appForegroundTimestamp: string;
|
||||
appBackgroundTimestamp: string;
|
||||
}
|
||||
|
||||
export interface CommonState {
|
||||
userData: User;
|
||||
clickstreamEvents: IClickstreamEvents[];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
4
src/types/appStates.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export enum AppStates {
|
||||
ACTIVE = 'active',
|
||||
BACKGROUND = 'background',
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user