Merge pull request #576 from navi-medici/agent-activity
TP-38613 | Added LOW, MEDIUM HIGH based on agent activity
This commit is contained in:
16
App.tsx
16
App.tsx
@@ -23,7 +23,7 @@ import { toastConfigs, ToastContainer } from './RN-UI-LIB/src/components/toast';
|
||||
|
||||
import { APM_APP_NAME, APM_BASE_URL, ENV } from './src/constants/config';
|
||||
import { COLORS } from './RN-UI-LIB/src/styles/colors';
|
||||
import { LocalStorageKeys } from './src/common/Constants';
|
||||
import { CLICKSTREAM_EVENT_NAMES, LocalStorageKeys } from './src/common/Constants';
|
||||
import Permissions from './src/screens/permissions/Permissions';
|
||||
import { setJsErrorHandler } from './src/services/exception-handler.service';
|
||||
import SuspenseLoader from './RN-UI-LIB/src/components/suspense_loader/SuspenseLoader';
|
||||
@@ -37,8 +37,13 @@ import {
|
||||
} from './src/components/utlis/PermissionUtils';
|
||||
import usePolling from './src/hooks/usePolling';
|
||||
import { MILLISECONDS_IN_A_SECOND } from './RN-UI-LIB/src/utlis/common';
|
||||
import { setItem } from './src/components/utlis/storageHelper';
|
||||
import { StorageKeys } from './src/types/storageKeys';
|
||||
import dayJs from 'dayjs';
|
||||
import { GlobalImageMap, hydrateGlobalImageMap } from './src/common/CachedImage';
|
||||
import analytics from '@react-native-firebase/analytics';
|
||||
import handleUpdatedConfigureValuesFromFirebase from './src/services/firebaseFetchAndUpdate.service';
|
||||
import { addClickstreamEvent } from './src/services/clickstreamEventService';
|
||||
|
||||
initSentry();
|
||||
|
||||
@@ -103,6 +108,12 @@ function App() {
|
||||
return route?.name || '';
|
||||
};
|
||||
|
||||
async function setForegroundTimeStampAndClickstream() {
|
||||
const now = dayJs().toString();
|
||||
await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, now);
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_APP_FOREGROUND, { now });
|
||||
}
|
||||
|
||||
usePolling(askForPermissions, PERMISSION_CHECK_POLL_INTERVAL);
|
||||
|
||||
initApm({
|
||||
@@ -128,6 +139,9 @@ function App() {
|
||||
setIsGlobalDocumentMapLoaded(true);
|
||||
})();
|
||||
checkCodePushAndSync();
|
||||
handleUpdatedConfigureValuesFromFirebase();
|
||||
setForegroundTimeStampAndClickstream();
|
||||
|
||||
return () => {
|
||||
appStateChange.remove();
|
||||
};
|
||||
|
||||
Submodule RN-UI-LIB updated: 4c7f4f6880...5b77f75cb6
@@ -1,39 +1,40 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "60755663443",
|
||||
"project_id": "address-verification-app",
|
||||
"storage_bucket": "address-verification-app.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:60755663443:android:988149d3da3c00d38584a6",
|
||||
"android_client_info": {
|
||||
"package_name": "com.avapp"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyA70_d2M2ke-Mu0OHGZ6iZilBbD6A-_z0c"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
"project_info": {
|
||||
"project_number": "60755663443",
|
||||
"project_id": "address-verification-app",
|
||||
"storage_bucket": "address-verification-app.appspot.com",
|
||||
"firebase_url": "https://address-verification-app-default-rtdb.firebaseio.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:60755663443:android:4a948ee9d0b4e3098584a6",
|
||||
"android_client_info": {
|
||||
"package_name": "com.avapp"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyA70_d2M2ke-Mu0OHGZ6iZilBbD6A-_z0c"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"@react-native-firebase/database": "16.4.6",
|
||||
"@react-native-firebase/firestore": "16.5.0",
|
||||
"@react-native-firebase/messaging": "17.4.0",
|
||||
"@react-native-firebase/remote-config": "16.4.6",
|
||||
"@react-native-google-signin/google-signin": "9.0.2",
|
||||
"@react-navigation/bottom-tabs": "6.5.5",
|
||||
"@react-navigation/native": "6.1.4",
|
||||
|
||||
19
src/common/AgentActivityConfigurableConstants.ts
Normal file
19
src/common/AgentActivityConfigurableConstants.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
let ACTIVITY_TIME_ON_APP: number = 5; //5 seconds
|
||||
let ACTIVITY_TIME_WINDOW_HIGH: number = 10; //10 minutes
|
||||
let ACTIVITY_TIME_WINDOW_MEDIUM: number = 30; //30 minutes
|
||||
|
||||
export const getActivityTimeOnApp = () => ACTIVITY_TIME_ON_APP;
|
||||
export const getActivityTimeWindowHigh = () => ACTIVITY_TIME_WINDOW_HIGH;
|
||||
export const getActivityTimeWindowMedium = () => ACTIVITY_TIME_WINDOW_MEDIUM;
|
||||
|
||||
export const setActivityTimeOnApp = (activityTimeOnApp: number) => {
|
||||
ACTIVITY_TIME_ON_APP = activityTimeOnApp;
|
||||
};
|
||||
|
||||
export const setActivityTimeWindowHigh = (activityTimeWindowHigh: number) => {
|
||||
ACTIVITY_TIME_WINDOW_HIGH = activityTimeWindowHigh;
|
||||
};
|
||||
|
||||
export const setActivityTimeWindowMedium = (activityTimeWindowMedium: number) => {
|
||||
ACTIVITY_TIME_WINDOW_MEDIUM = activityTimeWindowMedium;
|
||||
};
|
||||
@@ -34,8 +34,17 @@ import { setLockData } from '../reducer/userSlice';
|
||||
import { getConfigData } from '../action/configActions';
|
||||
import { AppStates } from '../types/appStates';
|
||||
import { StorageKeys } from '../types/storageKeys';
|
||||
import { AgentActivity } from '../types/agentActivity';
|
||||
import {
|
||||
getActivityTimeOnApp,
|
||||
getActivityTimeWindowMedium,
|
||||
getActivityTimeWindowHigh,
|
||||
} from './AgentActivityConfigurableConstants';
|
||||
import RNFS from 'react-native-fs';
|
||||
import { GlobalImageMap } from './CachedImage';
|
||||
import { get } from 'react-hook-form';
|
||||
import { addClickstreamEvent } from '../services/clickstreamEventService';
|
||||
import { CLICKSTREAM_EVENT_NAMES } from './Constants';
|
||||
|
||||
export enum FOREGROUND_TASKS {
|
||||
GEOLOCATION = 'GEOLOCATION',
|
||||
@@ -43,6 +52,7 @@ export enum FOREGROUND_TASKS {
|
||||
DATA_SYNC = 'DATA_SYNC',
|
||||
FIRESTORE_FALLBACK = 'FIRESTORE_FALLBACK',
|
||||
UPDATE_AGENT_ACTIVENESS = 'UPDATE_AGENT_ACTIVENESS',
|
||||
UPDATE_AGENT_ACTIVITY = 'UPDATE_AGENT_ACTIVITY',
|
||||
DELETE_CACHE = 'DELETE_CACHE',
|
||||
}
|
||||
|
||||
@@ -51,7 +61,6 @@ 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<ITrackingComponent> = ({ children }) => {
|
||||
@@ -94,12 +103,16 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
return;
|
||||
}
|
||||
const isActiveOnApp: string | boolean = (await getItem(StorageKeys.IS_USER_ACTIVE)) || false;
|
||||
const userActivityonApp: string =
|
||||
(await getItem(StorageKeys.USER_ACTIVITY_ON_APP)) || AgentActivity.LOW;
|
||||
|
||||
const geolocation: IGeolocationPayload = {
|
||||
latitude: location.latitude,
|
||||
longitude: location.longitude,
|
||||
accuracy: location.accuracy,
|
||||
timestamp: Date.now(),
|
||||
isActiveOnApp: Boolean(isActiveOnApp),
|
||||
userActivityOnApp: String(userActivityonApp),
|
||||
};
|
||||
dispatch(sendLocationAndActivenessToServer([geolocation]));
|
||||
} catch (e: any) {
|
||||
@@ -169,6 +182,7 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
const isForegroundTimeWithInRange =
|
||||
diffBetweenCurrentTimeAndForegroundTime <= ACTIVITY_TIME_WINDOW;
|
||||
const isForegroundTimeAfterBackground = dayJs(foregroundTimestamp).isAfter(backgroundTimestamp);
|
||||
const ACTIVITY_TIME_ON_APP = getActivityTimeOnApp();
|
||||
|
||||
if (isForegroundTimeWithInRange) {
|
||||
if (
|
||||
@@ -184,6 +198,60 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
return;
|
||||
};
|
||||
|
||||
const handleUpdateActivity = async () => {
|
||||
const foregroundTimestamp = await getItem(StorageKeys.APP_FOREGROUND_TIMESTAMP);
|
||||
const backgroundTimestamp = await getItem(StorageKeys.APP_BACKGROUND_TIMESTAMP);
|
||||
const stateSetTimestamp = await getItem(StorageKeys.STATE_SET_TIMESTAMP);
|
||||
|
||||
if (foregroundTimestamp == null) {
|
||||
console.log('fts set after installation');
|
||||
await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, dayJs().toString());
|
||||
}
|
||||
|
||||
const foregroundTime = dayJs(foregroundTimestamp);
|
||||
const backgroundTime = dayJs(backgroundTimestamp);
|
||||
const stateSetTime = dayJs(stateSetTimestamp);
|
||||
|
||||
const diffBetweenCurrentTimeAndForegroundTime =
|
||||
dayJs().diff(foregroundTime, 'seconds') < 0 ? 0 : dayJs().diff(foregroundTime, 'seconds');
|
||||
const diffBetweenCurrentTimeAndSetStateTime =
|
||||
dayJs().diff(stateSetTime, 'minutes') < 0 ? 0 : dayJs().diff(stateSetTime, 'minutes');
|
||||
|
||||
const ACTIVITY_TIME_ON_APP = getActivityTimeOnApp();
|
||||
const ACTIVITY_TIME_WINDOW_HIGH = getActivityTimeWindowHigh();
|
||||
const ACTIVITY_TIME_WINDOW_MEDIUM = getActivityTimeWindowMedium();
|
||||
|
||||
const isStateSetTimeWithinHighRange =
|
||||
diffBetweenCurrentTimeAndSetStateTime < ACTIVITY_TIME_WINDOW_HIGH;
|
||||
const isStateSetTimeWithinMediumRange =
|
||||
diffBetweenCurrentTimeAndSetStateTime < ACTIVITY_TIME_WINDOW_MEDIUM;
|
||||
const isForegroundTimeAfterBackground = dayJs(foregroundTimestamp).isAfter(backgroundTimestamp);
|
||||
|
||||
if (AppState.currentState === AppStates.ACTIVE) {
|
||||
if (diffBetweenCurrentTimeAndForegroundTime >= ACTIVITY_TIME_ON_APP) {
|
||||
await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isForegroundTimeAfterBackground) {
|
||||
if (diffBetweenCurrentTimeAndForegroundTime >= ACTIVITY_TIME_ON_APP) {
|
||||
await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
} else if (isStateSetTimeWithinHighRange) {
|
||||
return;
|
||||
} else if (isStateSetTimeWithinMediumRange) {
|
||||
await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.MEDIUM);
|
||||
return;
|
||||
} else {
|
||||
await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.LOW);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const deleteCache = () => {
|
||||
const directoryPath = RNFS.CachesDirectoryPath;
|
||||
const currentDate = new Date().getTime();
|
||||
@@ -239,6 +307,12 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes
|
||||
onLoop: true,
|
||||
},
|
||||
{
|
||||
taskId: FOREGROUND_TASKS.UPDATE_AGENT_ACTIVITY,
|
||||
task: handleUpdateActivity,
|
||||
delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes
|
||||
onLoop: true,
|
||||
},
|
||||
{
|
||||
taskId: FOREGROUND_TASKS.DELETE_CACHE,
|
||||
task: deleteCache,
|
||||
@@ -272,17 +346,39 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
});
|
||||
}
|
||||
|
||||
const userActivityUpdateOnBackground = async () => {
|
||||
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 ACTIVITY_TIME_ON_APP = getActivityTimeOnApp();
|
||||
|
||||
if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) {
|
||||
await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH);
|
||||
await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString());
|
||||
return;
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
const handleAppStateChange = async (nextAppState: AppStateStatus) => {
|
||||
// App comes to foreground from background
|
||||
const now = dayJs().toString();
|
||||
if (nextAppState === AppStates.ACTIVE) {
|
||||
await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, now);
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_APP_FOREGROUND, { now });
|
||||
handleGetCaseSyncStatus();
|
||||
dispatch(getConfigData());
|
||||
CosmosForegroundService.start(tasks);
|
||||
}
|
||||
if (nextAppState === AppStates.BACKGROUND) {
|
||||
await setItem(StorageKeys.APP_BACKGROUND_TIMESTAMP, now);
|
||||
userActivityUpdateOnBackground();
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_APP_BACKGROUND, { now });
|
||||
}
|
||||
appState.current = nextAppState;
|
||||
};
|
||||
@@ -306,12 +402,8 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
|
||||
useEffect(() => {
|
||||
let appStateSubscription: NativeEventSubscription;
|
||||
CosmosForegroundService.isRunning().then((isFGSRunning) => {
|
||||
if (!isFGSRunning) {
|
||||
appStateSubscription = AppState.addEventListener('change', handleAppStateChange);
|
||||
CosmosForegroundService.start(tasks);
|
||||
}
|
||||
});
|
||||
appStateSubscription = AppState.addEventListener('change', handleAppStateChange);
|
||||
CosmosForegroundService.start(tasks);
|
||||
return () => {
|
||||
appStateSubscription?.remove();
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface IGeolocationPayload {
|
||||
accuracy: number;
|
||||
timestamp: number;
|
||||
isActiveOnApp: boolean;
|
||||
userActivityOnApp: string;
|
||||
}
|
||||
|
||||
export const sendLocationAndActivenessToServer =
|
||||
|
||||
37
src/services/firebaseFetchAndUpdate.service.ts
Normal file
37
src/services/firebaseFetchAndUpdate.service.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import remoteConfig from '@react-native-firebase/remote-config';
|
||||
import {
|
||||
setActivityTimeOnApp,
|
||||
setActivityTimeWindowHigh,
|
||||
setActivityTimeWindowMedium,
|
||||
} from '../common/AgentActivityConfigurableConstants';
|
||||
|
||||
const FIREBASE_FETCH_TIME = 15 * 60;
|
||||
async function handleUpdatedConfigureValuesFromFirebase() {
|
||||
await remoteConfig().fetch(FIREBASE_FETCH_TIME); //15 minutes
|
||||
remoteConfig()
|
||||
.activate()
|
||||
.then((fetchedRemotely) => {
|
||||
if (fetchedRemotely) {
|
||||
console.log('Configs were fetched.');
|
||||
} else {
|
||||
console.log('No configs were fetched.');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
})
|
||||
.finally(() => {
|
||||
const ACTIVITY_TIME_ON_APP = remoteConfig().getValue('ACTIVITY_TIME_ON_APP').asNumber();
|
||||
const ACTIVITY_TIME_WINDOW_HIGH = remoteConfig()
|
||||
.getValue('ACTIVITY_TIME_WINDOW_HIGH')
|
||||
.asNumber();
|
||||
const ACTIVITY_TIME_WINDOW_MEDIUM = remoteConfig()
|
||||
.getValue('ACTIVITY_TIME_WINDOW_MEDIUM')
|
||||
.asNumber();
|
||||
setActivityTimeOnApp(ACTIVITY_TIME_ON_APP);
|
||||
setActivityTimeWindowHigh(ACTIVITY_TIME_WINDOW_HIGH);
|
||||
setActivityTimeWindowMedium(ACTIVITY_TIME_WINDOW_MEDIUM);
|
||||
});
|
||||
}
|
||||
|
||||
export default handleUpdatedConfigureValuesFromFirebase;
|
||||
5
src/types/agentActivity.ts
Normal file
5
src/types/agentActivity.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export enum AgentActivity {
|
||||
HIGH = 'HIGH',
|
||||
MEDIUM = 'MEDIUM',
|
||||
LOW = 'LOW',
|
||||
}
|
||||
@@ -2,4 +2,6 @@ export enum StorageKeys {
|
||||
APP_FOREGROUND_TIMESTAMP = 'appForegroundTimestamp',
|
||||
APP_BACKGROUND_TIMESTAMP = 'appBackgroundTimestamp',
|
||||
IS_USER_ACTIVE = 'isUserActive',
|
||||
USER_ACTIVITY_ON_APP = 'userActivityOnApp',
|
||||
STATE_SET_TIMESTAMP = 'stateSetTimestamp',
|
||||
}
|
||||
|
||||
@@ -1648,6 +1648,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@react-native-firebase/messaging/-/messaging-17.4.0.tgz#9e1df987183d0ca367d0922a14b14b7a53a140cf"
|
||||
integrity sha512-RSiBBfyJ3K9G6TQfZc09XaGpxB9xlP5m9DYkqjbNIqnnTiahF90770lTAS65L1Ha78vCwVO2swIlk32XbcMcMQ==
|
||||
|
||||
"@react-native-firebase/remote-config@16.4.6":
|
||||
version "16.4.6"
|
||||
resolved "https://registry.yarnpkg.com/@react-native-firebase/remote-config/-/remote-config-16.4.6.tgz#dec215f2448f555cdba893a31f5cdf419b47b33e"
|
||||
integrity sha512-2KPUao9xby+gp+JQUmikx9N0zcCLb0+6GkgI8//sYJ6Z3EaI53kx5kJHJDgYqdjF/zFjv3rm+yhm5LAgARPMHA==
|
||||
|
||||
"@react-native-google-signin/google-signin@9.0.2":
|
||||
version "9.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@react-native-google-signin/google-signin/-/google-signin-9.0.2.tgz#fd9d0cbb58591265c2ea9404b2d2ea7e514b9ea9"
|
||||
|
||||
Reference in New Issue
Block a user