From 0aa213780ceea10323a61ca1235c03977012f263 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Wed, 13 Sep 2023 22:33:51 +0530 Subject: [PATCH 01/17] TP-38613 | Added LOW, MEDIUM HIGH based on agent activity --- RN-UI-LIB | 2 +- android/app/google-services.json | 73 +++++++++++++------------- src/common/TrackingComponent.tsx | 90 +++++++++++++++++++++++++++++++- src/constants/config.js | 2 +- src/hooks/capturingApi.ts | 1 + src/types/agentActivity.ts | 5 ++ src/types/storageKeys.ts | 1 + yarn.lock | 2 +- 8 files changed, 136 insertions(+), 40 deletions(-) create mode 100644 src/types/agentActivity.ts diff --git a/RN-UI-LIB b/RN-UI-LIB index 3ab183e5..1c8615e7 160000 --- a/RN-UI-LIB +++ b/RN-UI-LIB @@ -1 +1 @@ -Subproject commit 3ab183e53214b6ac198f0376f7723cac2da96d83 +Subproject commit 1c8615e726218872a3be354e4bce621f3bf9d317 diff --git a/android/app/google-services.json b/android/app/google-services.json index 9d2a90ba..1df006c6 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -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" - } \ No newline at end of file + } + ], + "configuration_version": "1" +} diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index 580ea393..b8386a45 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -34,6 +34,7 @@ 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'; export enum FOREGROUND_TASKS { GEOLOCATION = 'GEOLOCATION', @@ -41,6 +42,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', } interface ITrackingComponent { @@ -51,6 +53,9 @@ let LAST_SYNC_STATUS = 'SKIP'; const ACTIVITY_TIME_ON_APP = 5; // 5 seconds const ACTIVITY_TIME_WINDOW = 10; // 10 minutes +const ACTIVITY_TIME_WINDOW_HIGH = 10; // 10 minutes +const ACTIVITY_TIME_WINDOW_MEDIUM = 30; // 30 minutes + const TrackingComponent: React.FC = ({ children }) => { const isOnline = useIsOnline(); const dispatch = useAppDispatch(); @@ -90,12 +95,16 @@ const TrackingComponent: React.FC = ({ 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) { @@ -180,6 +189,77 @@ const TrackingComponent: React.FC = ({ children }) => { return; }; + const handleUpdateActivity = async () => { + //ft==>app opened in foreground + //bt==>app is minimized or closed + const foregroundTimestamp = await getItem(StorageKeys.APP_FOREGROUND_TIMESTAMP); + const backgroundTimestamp = await getItem(StorageKeys.APP_BACKGROUND_TIMESTAMP); + + if (AppState.currentState === AppStates.ACTIVE) { + if (foregroundTimestamp == null) { + console.log('fts set after installation'); + await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, dayJs().toString()); + } + console.log('App State Active HIGH'); + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + return; + } + + 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 diffBetweenCurrentTimeAndBackgroundTime = + dayJs().diff(backgroundTime, 'minutes') < 0 ? 0 : dayJs().diff(backgroundTime, 'minutes'); + + // const isForegroundTimeWithInHighRange = diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_HIGH; + // const isForegroundTimeWithInMediumRange = diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_MEDIUM; + + const isBackgroundTimeWithInHighRange = diffBetweenCurrentTimeAndBackgroundTime < 2; + const isBackgroundTimeWithInMediumRange = diffBetweenCurrentTimeAndBackgroundTime < 4; + const isForegroundTimeAfterBackground = dayJs(foregroundTimestamp).isAfter(backgroundTimestamp); + + console.log('handleUpdateActivity'); + console.log(foregroundTimestamp); + console.log(backgroundTimestamp); + console.log(foregroundTime); + console.log(backgroundTime); + console.log(diffBetweenBackgroundAndForegroundTime); + console.log(diffBetweenCurrentTimeAndForegroundTime); + console.log(diffBetweenCurrentTimeAndBackgroundTime); + console.log(isBackgroundTimeWithInHighRange); + console.log(isBackgroundTimeWithInMediumRange); + console.log(isForegroundTimeAfterBackground); + + if (isForegroundTimeAfterBackground) { + console.log('isForegroundTimeAfterBackground HIGH'); + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + return; + } else if (isBackgroundTimeWithInHighRange) { + if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { + console.log('isBackgroundTimeWithInHighRange HIGH'); + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + return; + } + return; + } else if (isBackgroundTimeWithInMediumRange) { + if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { + console.log('isBackgroundTimeWithInMediumRange MEDIUM'); + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.MEDIUM); + return; + } + return; + } else { + console.log('isBackgroundTimeWithInLowRange LOW'); + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.LOW); + return; + } + }; + const tasks: IForegroundTask[] = [ { taskId: FOREGROUND_TASKS.TIME_SYNC, @@ -202,7 +282,15 @@ const TrackingComponent: React.FC = ({ children }) => { { taskId: FOREGROUND_TASKS.UPDATE_AGENT_ACTIVENESS, task: handleUpdateActiveness, - delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes + //delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes + delay: MILLISECONDS_IN_A_MINUTE / 3, // 20 seconds + onLoop: true, + }, + { + taskId: FOREGROUND_TASKS.UPDATE_AGENT_ACTIVITY, + task: handleUpdateActivity, + //delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes + delay: MILLISECONDS_IN_A_MINUTE / 3, // 20 seconds onLoop: true, }, ]; diff --git a/src/constants/config.js b/src/constants/config.js index 94018508..6fa05aeb 100644 --- a/src/constants/config.js +++ b/src/constants/config.js @@ -11,4 +11,4 @@ export const APM_BASE_URL = 'https://qa-longhorn-portal.np.navi-tech.in/apm-even export const IS_DATA_SYNC_REQUIRED = true; export const DATA_SYNC_TIME_INTERVAL = 2 * MINUTES_IN_AN_HOUR * MILLISECONDS_IN_A_MINUTE; // 2hr export const GOOGLE_SSO_CLIENT_ID = - '60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com'; \ No newline at end of file + '60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com'; diff --git a/src/hooks/capturingApi.ts b/src/hooks/capturingApi.ts index df42af7a..4c32cc1b 100644 --- a/src/hooks/capturingApi.ts +++ b/src/hooks/capturingApi.ts @@ -13,6 +13,7 @@ export interface IGeolocationPayload { accuracy: number; timestamp: number; isActiveOnApp: boolean; + userActivityOnApp: string; } export const sendLocationAndActivenessToServer = diff --git a/src/types/agentActivity.ts b/src/types/agentActivity.ts new file mode 100644 index 00000000..0184175b --- /dev/null +++ b/src/types/agentActivity.ts @@ -0,0 +1,5 @@ +export enum AgentActivity { + HIGH = 'HIGH', + MEDIUM = 'MEDIUM', + LOW = 'LOW', +} diff --git a/src/types/storageKeys.ts b/src/types/storageKeys.ts index c18bd31d..24a2469d 100644 --- a/src/types/storageKeys.ts +++ b/src/types/storageKeys.ts @@ -2,4 +2,5 @@ export enum StorageKeys { APP_FOREGROUND_TIMESTAMP = 'appForegroundTimestamp', APP_BACKGROUND_TIMESTAMP = 'appBackgroundTimestamp', IS_USER_ACTIVE = 'isUserActive', + USER_ACTIVITY_ON_APP = 'userActivityOnApp', } diff --git a/yarn.lock b/yarn.lock index 20dab82a..f48d5563 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3404,7 +3404,7 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -dayjs@^1.11.9: +dayjs@1.11.9: version "1.11.9" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a" integrity sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA== From 6f6b5733645be5b6fb999a7acd9fa0f09da34b09 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Fri, 15 Sep 2023 01:45:42 +0530 Subject: [PATCH 02/17] TP-38613 | Shri Prakash Bajpai | Added LOW MEDIUM HIGH for agent activity and made parameters configurable --- App.tsx | 26 ++++++++ package.json | 1 + src/common/TrackingComponent.tsx | 106 ++++++++++++++++++++++++------- src/reducer/commonSlice.ts | 30 ++++++++- src/reducer/configSlice.ts | 6 ++ src/store/store.ts | 2 + src/types/appStates.ts | 1 + yarn.lock | 5 ++ 8 files changed, 154 insertions(+), 23 deletions(-) diff --git a/App.tsx b/App.tsx index 07a85922..70f4fbbe 100644 --- a/App.tsx +++ b/App.tsx @@ -37,7 +37,11 @@ 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 analytics from '@react-native-firebase/analytics'; +import remoteConfig from '@react-native-firebase/remote-config'; initSentry(); @@ -102,6 +106,25 @@ function App() { return route?.name || ''; }; + async function setForegroundTimeStamp() { + const now = dayJs().toString(); + await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, now); + } + + async function handleUpdatedConfigureValuesFromFirebase() { + await remoteConfig().fetch(10); + + remoteConfig() + .fetchAndActivate() + .then((fetchedRemotely) => { + if (fetchedRemotely) { + console.log('Configs were fetched.'); + } else { + console.log('No configs were fetched.'); + } + }); + } + usePolling(askForPermissions, PERMISSION_CHECK_POLL_INTERVAL); initApm({ @@ -126,6 +149,9 @@ function App() { setIsGlobalDocumentMapLoaded(true); })(); checkCodePushAndSync(); + handleUpdatedConfigureValuesFromFirebase(); + setForegroundTimeStamp(); + return () => { appStateChange.remove(); }; diff --git a/package.json b/package.json index 54c608a2..bd425c45 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index b8386a45..a393ef69 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -35,6 +35,12 @@ import { getConfigData } from '../action/configActions'; import { AppStates } from '../types/appStates'; import { StorageKeys } from '../types/storageKeys'; import { AgentActivity } from '../types/agentActivity'; +import remoteConfig, { FirebaseRemoteConfigTypes } from '@react-native-firebase/remote-config'; +import { + setActivityTimeOnApp, + setActivityTimeWindowHigh, + setActivityTimeWindowMedium, +} from '../reducer/commonSlice'; export enum FOREGROUND_TASKS { GEOLOCATION = 'GEOLOCATION', @@ -43,6 +49,7 @@ export enum FOREGROUND_TASKS { FIRESTORE_FALLBACK = 'FIRESTORE_FALLBACK', UPDATE_AGENT_ACTIVENESS = 'UPDATE_AGENT_ACTIVENESS', UPDATE_AGENT_ACTIVITY = 'UPDATE_AGENT_ACTIVITY', + GET_AGENT_ACTIVITY_CONFIG_VARIABLES = 'GET_AGENT_ACTIVITY_CONFIG_VARIABLES', } interface ITrackingComponent { @@ -50,11 +57,14 @@ interface ITrackingComponent { } let LAST_SYNC_STATUS = 'SKIP'; -const ACTIVITY_TIME_ON_APP = 5; // 5 seconds +// const ACTIVITY_TIME_ON_APP = 5; // 5 seconds const ACTIVITY_TIME_WINDOW = 10; // 10 minutes -const ACTIVITY_TIME_WINDOW_HIGH = 10; // 10 minutes -const ACTIVITY_TIME_WINDOW_MEDIUM = 30; // 30 minutes +// const ACTIVITY_TIME_WINDOW_HIGH = 10; // 10 minutes +// const ACTIVITY_TIME_WINDOW_MEDIUM = 30; // 30 minutes + +// const ACTIVITY_TIME_WINDOW_HIGH = 2; // 2 minutes +// const ACTIVITY_TIME_WINDOW_MEDIUM = 4; // 4 minutes const TrackingComponent: React.FC = ({ children }) => { const isOnline = useIsOnline(); @@ -66,11 +76,17 @@ const TrackingComponent: React.FC = ({ children }) => { pendingList = [], pinnedList = [], geolocations = [], + // ACTIVITY_TIME_ON_APP, + // ACTIVITY_TIME_WINDOW_HIGH, + // ACTIVITY_TIME_WINDOW_MEDIUM, } = useAppSelector((state) => ({ referenceId: state.user.user?.referenceId!, pendingList: state.allCases.pendingList, pinnedList: state.allCases.pinnedList, geolocations: state.foregroundService.deviceGeolocationsBuffer, + // ACTIVITY_TIME_ON_APP: state.common.activityTimeOnApp, + // ACTIVITY_TIME_WINDOW_HIGH: state.common.activityTimeWindowHigh, + // ACTIVITY_TIME_WINDOW_MEDIUM: state.common.activityTimeWindowMedium, })); const handleTimeSync = async () => { @@ -174,6 +190,7 @@ const TrackingComponent: React.FC = ({ children }) => { const isForegroundTimeWithInRange = diffBetweenCurrentTimeAndForegroundTime <= ACTIVITY_TIME_WINDOW; const isForegroundTimeAfterBackground = dayJs(foregroundTimestamp).isAfter(backgroundTimestamp); + const ACTIVITY_TIME_ON_APP = remoteConfig().getValue('ACTIVITY_TIME_ON_APP').asNumber(); if (isForegroundTimeWithInRange) { if ( @@ -195,16 +212,6 @@ const TrackingComponent: React.FC = ({ children }) => { const foregroundTimestamp = await getItem(StorageKeys.APP_FOREGROUND_TIMESTAMP); const backgroundTimestamp = await getItem(StorageKeys.APP_BACKGROUND_TIMESTAMP); - if (AppState.currentState === AppStates.ACTIVE) { - if (foregroundTimestamp == null) { - console.log('fts set after installation'); - await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, dayJs().toString()); - } - console.log('App State Active HIGH'); - await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); - return; - } - const foregroundTime = dayJs(foregroundTimestamp); const backgroundTime = dayJs(backgroundTimestamp); const diffBetweenBackgroundAndForegroundTime = dayJs(backgroundTime).diff( @@ -212,17 +219,40 @@ const TrackingComponent: React.FC = ({ children }) => { 'seconds' ); const diffBetweenCurrentTimeAndForegroundTime = - dayJs().diff(foregroundTime, 'minutes') < 0 ? 0 : dayJs().diff(foregroundTime, 'minutes'); + dayJs().diff(foregroundTime, 'seconds') < 0 ? 0 : dayJs().diff(foregroundTime, 'seconds'); const diffBetweenCurrentTimeAndBackgroundTime = dayJs().diff(backgroundTime, 'minutes') < 0 ? 0 : dayJs().diff(backgroundTime, 'minutes'); + 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(); + // const isForegroundTimeWithInHighRange = diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_HIGH; // const isForegroundTimeWithInMediumRange = diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_MEDIUM; - const isBackgroundTimeWithInHighRange = diffBetweenCurrentTimeAndBackgroundTime < 2; - const isBackgroundTimeWithInMediumRange = diffBetweenCurrentTimeAndBackgroundTime < 4; + const isBackgroundTimeWithInHighRange = + diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_HIGH; + const isBackgroundTimeWithInMediumRange = + diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_MEDIUM; const isForegroundTimeAfterBackground = dayJs(foregroundTimestamp).isAfter(backgroundTimestamp); + if (AppState.currentState === AppStates.ACTIVE) { + if (foregroundTimestamp == null) { + console.log('fts set after installation'); + await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, dayJs().toString()); + } + if (diffBetweenCurrentTimeAndForegroundTime >= ACTIVITY_TIME_ON_APP) { + console.log('App State Active HIGH'); + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + return; + } + return; + } + console.log('handleUpdateActivity'); console.log(foregroundTimestamp); console.log(backgroundTimestamp); @@ -234,10 +264,16 @@ const TrackingComponent: React.FC = ({ children }) => { console.log(isBackgroundTimeWithInHighRange); console.log(isBackgroundTimeWithInMediumRange); console.log(isForegroundTimeAfterBackground); + console.log(ACTIVITY_TIME_ON_APP); + console.log(ACTIVITY_TIME_WINDOW_HIGH); + console.log(ACTIVITY_TIME_WINDOW_MEDIUM); if (isForegroundTimeAfterBackground) { - console.log('isForegroundTimeAfterBackground HIGH'); - await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + if (diffBetweenCurrentTimeAndForegroundTime >= ACTIVITY_TIME_ON_APP) { + console.log('isForegroundTimeAfterBackground HIGH'); + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + return; + } return; } else if (isBackgroundTimeWithInHighRange) { if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { @@ -311,17 +347,41 @@ const TrackingComponent: React.FC = ({ 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 = remoteConfig().getValue('ACTIVITY_TIME_ON_APP').asNumber(); + + if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + return; + } + return; + }; + const handleAppStateChange = async (nextAppState: AppStateStatus) => { + console.log(nextAppState); + // App comes to foreground from background const now = dayJs().toString(); if (nextAppState === AppStates.ACTIVE) { + console.log('App State Active'); await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, now); handleGetCaseSyncStatus(); dispatch(getConfigData()); CosmosForegroundService.start(tasks); } if (nextAppState === AppStates.BACKGROUND) { + console.log('App State Background'); await setItem(StorageKeys.APP_BACKGROUND_TIMESTAMP, now); + userActivityUpdateOnBackground(); } appState.current = nextAppState; }; @@ -346,10 +406,12 @@ const TrackingComponent: React.FC = ({ children }) => { useEffect(() => { let appStateSubscription: NativeEventSubscription; CosmosForegroundService.isRunning().then((isFGSRunning) => { - if (!isFGSRunning) { - appStateSubscription = AppState.addEventListener('change', handleAppStateChange); - CosmosForegroundService.start(tasks); - } + // if (!isFGSRunning) { + // appStateSubscription = AppState.addEventListener('change', handleAppStateChange); + // CosmosForegroundService.start(tasks); + // } + appStateSubscription = AppState.addEventListener('change', handleAppStateChange); + CosmosForegroundService.start(tasks); }); return () => { appStateSubscription?.remove(); diff --git a/src/reducer/commonSlice.ts b/src/reducer/commonSlice.ts index 511c6d9a..6856669b 100644 --- a/src/reducer/commonSlice.ts +++ b/src/reducer/commonSlice.ts @@ -20,6 +20,9 @@ export interface AppState { export interface CommonState { userData: User; clickstreamEvents: IClickstreamEvents[]; + activityTimeOnApp: number; + activityTimeWindowHigh: number; + activityTimeWindowMedium: number; } const initialState = { @@ -29,6 +32,9 @@ const initialState = { deviceId: GLOBAL.DEVICE_ID || '', } as User, clickstreamEvents: [], + activityTimeOnApp: 0, + activityTimeWindowHigh: 0, + activityTimeWindowMedium: 0, } as CommonState; export const commonSlice = createSlice({ @@ -50,9 +56,31 @@ export const commonSlice = createSlice({ resetClickstreamEvents: (state) => { state.clickstreamEvents = []; }, + setActivityTimeOnApp: (state, action) => { + if (action.payload) { + state.activityTimeOnApp = action.payload; + } + }, + setActivityTimeWindowHigh: (state, action) => { + if (action.payload) { + state.activityTimeWindowHigh = action.payload; + } + }, + setActivityTimeWindowMedium: (state, action) => { + if (action.payload) { + state.activityTimeWindowMedium = action.payload; + } + }, }, }); -export const { setAuthData, setClickstreamEvents, resetClickstreamEvents } = commonSlice.actions; +export const { + setAuthData, + setClickstreamEvents, + resetClickstreamEvents, + setActivityTimeOnApp, + setActivityTimeWindowHigh, + setActivityTimeWindowMedium, +} = commonSlice.actions; export default commonSlice.reducer; diff --git a/src/reducer/configSlice.ts b/src/reducer/configSlice.ts index a5ada487..12641215 100644 --- a/src/reducer/configSlice.ts +++ b/src/reducer/configSlice.ts @@ -1,4 +1,5 @@ import { createSlice } from '@reduxjs/toolkit'; +import { GenericType } from '../common/GenericTypes'; interface IConfigData { supportLink: ''; @@ -6,6 +7,7 @@ interface IConfigData { interface IConfigSlice { data: IConfigData; loading: boolean; + firebaseRemoteConfig: GenericType; } export const initialConfigData = { @@ -15,6 +17,7 @@ export const initialConfigData = { const initialState = { data: initialConfigData, loading: false, + firebaseRemoteConfig: {}, } as IConfigSlice; const ConfigSlice = createSlice({ @@ -28,6 +31,9 @@ const ConfigSlice = createSlice({ state.loading = action.payload; }, resetConfig: () => initialState, + setFirebaseRemoteConfig: (state, action) => { + state.firebaseRemoteConfig = action.payload; + }, }, }); diff --git a/src/store/store.ts b/src/store/store.ts index d925b460..f9a2e3ad 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -30,6 +30,7 @@ import foregroundServiceSlice from '../reducer/foregroundServiceSlice'; import feedbackImagesSlice from '../reducer/feedbackImagesSlice'; import configSlice from '../reducer/configSlice'; import profileSlice from '../reducer/profileSlice'; +import commonSlice from '../reducer/commonSlice'; const rootReducer = combineReducers({ case: caseReducer, @@ -50,6 +51,7 @@ const rootReducer = combineReducers({ feedbackImages: feedbackImagesSlice, config: configSlice, profile: profileSlice, + common: commonSlice, }); const persistConfig = { diff --git a/src/types/appStates.ts b/src/types/appStates.ts index 54f1a10a..61c6d4dd 100644 --- a/src/types/appStates.ts +++ b/src/types/appStates.ts @@ -1,4 +1,5 @@ export enum AppStates { ACTIVE = 'active', BACKGROUND = 'background', + INACTIVE = 'inactive', } diff --git a/yarn.lock b/yarn.lock index f48d5563..1ff97bb5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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.7.0" + resolved "https://registry.yarnpkg.com/@react-native-firebase/remote-config/-/remote-config-16.7.0.tgz#45135d039ca9e7d8b90f1885034e33f67abc8443" + integrity sha512-jsoaQM9F2/fOUIhIJNmX/8blMlDRwDLiDd07qNFFCTc00gFrR7VN9x81BDKiLNKMMo/0WcSMTrGHj/Pb41MoYA== + "@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" From 05bd0bed6f5fe49166abaa683a03405a01534efe Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Fri, 15 Sep 2023 12:48:20 +0530 Subject: [PATCH 03/17] TP-38613 | Shri Prakash Bajpai | Added LOW MEDIUM HIGH for agent activity and made parameters configurable --- App.tsx | 16 +------- package.json | 2 +- .../AgentActivityConfigurableConstants.ts | 19 +++++++++ src/common/TrackingComponent.tsx | 40 +++++-------------- src/reducer/commonSlice.ts | 30 +------------- src/reducer/configSlice.ts | 6 --- .../firebaseFetchAndUpdate.service.ts | 36 +++++++++++++++++ src/store/store.ts | 2 - 8 files changed, 67 insertions(+), 84 deletions(-) create mode 100644 src/common/AgentActivityConfigurableConstants.ts create mode 100644 src/services/firebaseFetchAndUpdate.service.ts diff --git a/App.tsx b/App.tsx index 70f4fbbe..fd9114dd 100644 --- a/App.tsx +++ b/App.tsx @@ -41,7 +41,7 @@ import { setItem } from './src/components/utlis/storageHelper'; import { StorageKeys } from './src/types/storageKeys'; import dayJs from 'dayjs'; import analytics from '@react-native-firebase/analytics'; -import remoteConfig from '@react-native-firebase/remote-config'; +import handleUpdatedConfigureValuesFromFirebase from './src/services/firebaseFetchAndUpdate.service'; initSentry(); @@ -111,20 +111,6 @@ function App() { await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, now); } - async function handleUpdatedConfigureValuesFromFirebase() { - await remoteConfig().fetch(10); - - remoteConfig() - .fetchAndActivate() - .then((fetchedRemotely) => { - if (fetchedRemotely) { - console.log('Configs were fetched.'); - } else { - console.log('No configs were fetched.'); - } - }); - } - usePolling(askForPermissions, PERMISSION_CHECK_POLL_INTERVAL); initApm({ diff --git a/package.json b/package.json index bd425c45..62e2df8f 100644 --- a/package.json +++ b/package.json @@ -37,7 +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-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", diff --git a/src/common/AgentActivityConfigurableConstants.ts b/src/common/AgentActivityConfigurableConstants.ts new file mode 100644 index 00000000..07976239 --- /dev/null +++ b/src/common/AgentActivityConfigurableConstants.ts @@ -0,0 +1,19 @@ +let ACTIVITY_TIME_ON_APP: number = 5; +let ACTIVITY_TIME_WINDOW_HIGH: number = 2; +let ACTIVITY_TIME_WINDOW_MEDIUM: number = 4; + +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; +}; diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index a393ef69..82f800e6 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -35,12 +35,11 @@ import { getConfigData } from '../action/configActions'; import { AppStates } from '../types/appStates'; import { StorageKeys } from '../types/storageKeys'; import { AgentActivity } from '../types/agentActivity'; -import remoteConfig, { FirebaseRemoteConfigTypes } from '@react-native-firebase/remote-config'; import { - setActivityTimeOnApp, - setActivityTimeWindowHigh, - setActivityTimeWindowMedium, -} from '../reducer/commonSlice'; + getActivityTimeOnApp, + getActivityTimeWindowMedium, + getActivityTimeWindowHigh, +} from './AgentActivityConfigurableConstants'; export enum FOREGROUND_TASKS { GEOLOCATION = 'GEOLOCATION', @@ -49,7 +48,6 @@ export enum FOREGROUND_TASKS { FIRESTORE_FALLBACK = 'FIRESTORE_FALLBACK', UPDATE_AGENT_ACTIVENESS = 'UPDATE_AGENT_ACTIVENESS', UPDATE_AGENT_ACTIVITY = 'UPDATE_AGENT_ACTIVITY', - GET_AGENT_ACTIVITY_CONFIG_VARIABLES = 'GET_AGENT_ACTIVITY_CONFIG_VARIABLES', } interface ITrackingComponent { @@ -57,15 +55,8 @@ interface ITrackingComponent { } let LAST_SYNC_STATUS = 'SKIP'; -// const ACTIVITY_TIME_ON_APP = 5; // 5 seconds const ACTIVITY_TIME_WINDOW = 10; // 10 minutes -// const ACTIVITY_TIME_WINDOW_HIGH = 10; // 10 minutes -// const ACTIVITY_TIME_WINDOW_MEDIUM = 30; // 30 minutes - -// const ACTIVITY_TIME_WINDOW_HIGH = 2; // 2 minutes -// const ACTIVITY_TIME_WINDOW_MEDIUM = 4; // 4 minutes - const TrackingComponent: React.FC = ({ children }) => { const isOnline = useIsOnline(); const dispatch = useAppDispatch(); @@ -76,17 +67,11 @@ const TrackingComponent: React.FC = ({ children }) => { pendingList = [], pinnedList = [], geolocations = [], - // ACTIVITY_TIME_ON_APP, - // ACTIVITY_TIME_WINDOW_HIGH, - // ACTIVITY_TIME_WINDOW_MEDIUM, } = useAppSelector((state) => ({ referenceId: state.user.user?.referenceId!, pendingList: state.allCases.pendingList, pinnedList: state.allCases.pinnedList, geolocations: state.foregroundService.deviceGeolocationsBuffer, - // ACTIVITY_TIME_ON_APP: state.common.activityTimeOnApp, - // ACTIVITY_TIME_WINDOW_HIGH: state.common.activityTimeWindowHigh, - // ACTIVITY_TIME_WINDOW_MEDIUM: state.common.activityTimeWindowMedium, })); const handleTimeSync = async () => { @@ -190,7 +175,7 @@ const TrackingComponent: React.FC = ({ children }) => { const isForegroundTimeWithInRange = diffBetweenCurrentTimeAndForegroundTime <= ACTIVITY_TIME_WINDOW; const isForegroundTimeAfterBackground = dayJs(foregroundTimestamp).isAfter(backgroundTimestamp); - const ACTIVITY_TIME_ON_APP = remoteConfig().getValue('ACTIVITY_TIME_ON_APP').asNumber(); + const ACTIVITY_TIME_ON_APP = 5; // 5 seconds if (isForegroundTimeWithInRange) { if ( @@ -223,16 +208,9 @@ const TrackingComponent: React.FC = ({ children }) => { const diffBetweenCurrentTimeAndBackgroundTime = dayJs().diff(backgroundTime, 'minutes') < 0 ? 0 : dayJs().diff(backgroundTime, 'minutes'); - 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(); - - // const isForegroundTimeWithInHighRange = diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_HIGH; - // const isForegroundTimeWithInMediumRange = diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_MEDIUM; + const ACTIVITY_TIME_ON_APP = getActivityTimeOnApp(); + const ACTIVITY_TIME_WINDOW_HIGH = getActivityTimeWindowHigh(); + const ACTIVITY_TIME_WINDOW_MEDIUM = getActivityTimeWindowMedium(); const isBackgroundTimeWithInHighRange = diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_HIGH; @@ -357,7 +335,7 @@ const TrackingComponent: React.FC = ({ children }) => { foregroundTime, 'seconds' ); - const ACTIVITY_TIME_ON_APP = remoteConfig().getValue('ACTIVITY_TIME_ON_APP').asNumber(); + const ACTIVITY_TIME_ON_APP = getActivityTimeOnApp(); if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); diff --git a/src/reducer/commonSlice.ts b/src/reducer/commonSlice.ts index 6856669b..511c6d9a 100644 --- a/src/reducer/commonSlice.ts +++ b/src/reducer/commonSlice.ts @@ -20,9 +20,6 @@ export interface AppState { export interface CommonState { userData: User; clickstreamEvents: IClickstreamEvents[]; - activityTimeOnApp: number; - activityTimeWindowHigh: number; - activityTimeWindowMedium: number; } const initialState = { @@ -32,9 +29,6 @@ const initialState = { deviceId: GLOBAL.DEVICE_ID || '', } as User, clickstreamEvents: [], - activityTimeOnApp: 0, - activityTimeWindowHigh: 0, - activityTimeWindowMedium: 0, } as CommonState; export const commonSlice = createSlice({ @@ -56,31 +50,9 @@ export const commonSlice = createSlice({ resetClickstreamEvents: (state) => { state.clickstreamEvents = []; }, - setActivityTimeOnApp: (state, action) => { - if (action.payload) { - state.activityTimeOnApp = action.payload; - } - }, - setActivityTimeWindowHigh: (state, action) => { - if (action.payload) { - state.activityTimeWindowHigh = action.payload; - } - }, - setActivityTimeWindowMedium: (state, action) => { - if (action.payload) { - state.activityTimeWindowMedium = action.payload; - } - }, }, }); -export const { - setAuthData, - setClickstreamEvents, - resetClickstreamEvents, - setActivityTimeOnApp, - setActivityTimeWindowHigh, - setActivityTimeWindowMedium, -} = commonSlice.actions; +export const { setAuthData, setClickstreamEvents, resetClickstreamEvents } = commonSlice.actions; export default commonSlice.reducer; diff --git a/src/reducer/configSlice.ts b/src/reducer/configSlice.ts index 12641215..a5ada487 100644 --- a/src/reducer/configSlice.ts +++ b/src/reducer/configSlice.ts @@ -1,5 +1,4 @@ import { createSlice } from '@reduxjs/toolkit'; -import { GenericType } from '../common/GenericTypes'; interface IConfigData { supportLink: ''; @@ -7,7 +6,6 @@ interface IConfigData { interface IConfigSlice { data: IConfigData; loading: boolean; - firebaseRemoteConfig: GenericType; } export const initialConfigData = { @@ -17,7 +15,6 @@ export const initialConfigData = { const initialState = { data: initialConfigData, loading: false, - firebaseRemoteConfig: {}, } as IConfigSlice; const ConfigSlice = createSlice({ @@ -31,9 +28,6 @@ const ConfigSlice = createSlice({ state.loading = action.payload; }, resetConfig: () => initialState, - setFirebaseRemoteConfig: (state, action) => { - state.firebaseRemoteConfig = action.payload; - }, }, }); diff --git a/src/services/firebaseFetchAndUpdate.service.ts b/src/services/firebaseFetchAndUpdate.service.ts new file mode 100644 index 00000000..6bfd81bd --- /dev/null +++ b/src/services/firebaseFetchAndUpdate.service.ts @@ -0,0 +1,36 @@ +import remoteConfig from '@react-native-firebase/remote-config'; +import { + setActivityTimeOnApp, + setActivityTimeWindowHigh, + setActivityTimeWindowMedium, +} from '../common/AgentActivityConfigurableConstants'; + +async function handleUpdatedConfigureValuesFromFirebase() { + await remoteConfig().fetch(10); + remoteConfig() + .fetchAndActivate() + .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; diff --git a/src/store/store.ts b/src/store/store.ts index f9a2e3ad..d925b460 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -30,7 +30,6 @@ import foregroundServiceSlice from '../reducer/foregroundServiceSlice'; import feedbackImagesSlice from '../reducer/feedbackImagesSlice'; import configSlice from '../reducer/configSlice'; import profileSlice from '../reducer/profileSlice'; -import commonSlice from '../reducer/commonSlice'; const rootReducer = combineReducers({ case: caseReducer, @@ -51,7 +50,6 @@ const rootReducer = combineReducers({ feedbackImages: feedbackImagesSlice, config: configSlice, profile: profileSlice, - common: commonSlice, }); const persistConfig = { From 7b63299f00b6c3b34c86006e58457ae0a9c8f835 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Fri, 15 Sep 2023 12:54:16 +0530 Subject: [PATCH 04/17] Inactive State removed --- src/types/appStates.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/types/appStates.ts b/src/types/appStates.ts index 61c6d4dd..54f1a10a 100644 --- a/src/types/appStates.ts +++ b/src/types/appStates.ts @@ -1,5 +1,4 @@ export enum AppStates { ACTIVE = 'active', BACKGROUND = 'background', - INACTIVE = 'inactive', } From dc40a3c54f147c340280b7aac5e30c940512ee68 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Sun, 17 Sep 2023 16:41:41 +0530 Subject: [PATCH 05/17] logic changed for edge case --- src/common/TrackingComponent.tsx | 61 ++++++++++++++++++++------------ src/types/storageKeys.ts | 1 + 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index 0de56af3..832f71dd 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -42,6 +42,7 @@ import { } from './AgentActivityConfigurableConstants'; import RNFS from 'react-native-fs'; import { GlobalImageMap } from './CachedImage'; +import { get } from 'react-hook-form'; export enum FOREGROUND_TASKS { GEOLOCATION = 'GEOLOCATION', @@ -200,9 +201,12 @@ const TrackingComponent: React.FC = ({ children }) => { //bt==>app is minimized or closed const foregroundTimestamp = await getItem(StorageKeys.APP_FOREGROUND_TIMESTAMP); const backgroundTimestamp = await getItem(StorageKeys.APP_BACKGROUND_TIMESTAMP); + const stateSetTimestamp = await getItem(StorageKeys.STATE_SET_TIMESTAMP); const foregroundTime = dayJs(foregroundTimestamp); const backgroundTime = dayJs(backgroundTimestamp); + const stateSetTime = dayJs(stateSetTimestamp); + const diffBetweenBackgroundAndForegroundTime = dayJs(backgroundTime).diff( foregroundTime, 'seconds' @@ -211,15 +215,18 @@ const TrackingComponent: React.FC = ({ children }) => { dayJs().diff(foregroundTime, 'seconds') < 0 ? 0 : dayJs().diff(foregroundTime, 'seconds'); const diffBetweenCurrentTimeAndBackgroundTime = dayJs().diff(backgroundTime, 'minutes') < 0 ? 0 : dayJs().diff(backgroundTime, 'minutes'); + 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 isBackgroundTimeWithInHighRange = - diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_HIGH; - const isBackgroundTimeWithInMediumRange = - diffBetweenCurrentTimeAndBackgroundTime < ACTIVITY_TIME_WINDOW_MEDIUM; + const isStateSetTimeMoreThanHighRangeAndLessThanMediumRange = + diffBetweenCurrentTimeAndSetStateTime >= ACTIVITY_TIME_WINDOW_HIGH; + const isStateSetTimeMoreThanMediumRange = + diffBetweenCurrentTimeAndSetStateTime >= + ACTIVITY_TIME_WINDOW_MEDIUM - ACTIVITY_TIME_WINDOW_HIGH; const isForegroundTimeAfterBackground = dayJs(foregroundTimestamp).isAfter(backgroundTimestamp); if (AppState.currentState === AppStates.ACTIVE) { @@ -238,13 +245,15 @@ const TrackingComponent: React.FC = ({ children }) => { console.log('handleUpdateActivity'); console.log(foregroundTimestamp); console.log(backgroundTimestamp); + console.log(stateSetTimestamp); console.log(foregroundTime); console.log(backgroundTime); + console.log(stateSetTime); console.log(diffBetweenBackgroundAndForegroundTime); console.log(diffBetweenCurrentTimeAndForegroundTime); console.log(diffBetweenCurrentTimeAndBackgroundTime); - console.log(isBackgroundTimeWithInHighRange); - console.log(isBackgroundTimeWithInMediumRange); + console.log(isStateSetTimeMoreThanHighRangeAndLessThanMediumRange); + console.log(isStateSetTimeMoreThanMediumRange); console.log(isForegroundTimeAfterBackground); console.log(ACTIVITY_TIME_ON_APP); console.log(ACTIVITY_TIME_WINDOW_HIGH); @@ -252,28 +261,31 @@ const TrackingComponent: React.FC = ({ children }) => { if (isForegroundTimeAfterBackground) { if (diffBetweenCurrentTimeAndForegroundTime >= ACTIVITY_TIME_ON_APP) { + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); console.log('isForegroundTimeAfterBackground HIGH'); - await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + console.log('High State Set Time' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP))); return; } return; - } else if (isBackgroundTimeWithInHighRange) { - if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { - console.log('isBackgroundTimeWithInHighRange HIGH'); - await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); - return; - } + } else if ( + isStateSetTimeMoreThanHighRangeAndLessThanMediumRange && + (await getItem(StorageKeys.USER_ACTIVITY_ON_APP)) == AgentActivity.HIGH + ) { + await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.MEDIUM); + await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(2, 'minutes').toString()); + console.log('isStateSetTimeWithInMediumRange MEDIUM'); + console.log('Medium State Set Time' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP))); return; - } else if (isBackgroundTimeWithInMediumRange) { - if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { - console.log('isBackgroundTimeWithInMediumRange MEDIUM'); - await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.MEDIUM); - return; - } - return; - } else { - console.log('isBackgroundTimeWithInLowRange LOW'); + } else if ( + isStateSetTimeMoreThanMediumRange && + (await getItem(StorageKeys.USER_ACTIVITY_ON_APP)) == AgentActivity.MEDIUM + ) { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.LOW); + await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(2, 'minutes').toString()); + console.log('isStateSetTimeWithInLowRange LOW'); + console.log('Low State Set Time' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP))); + } else { return; } }; @@ -388,6 +400,11 @@ const TrackingComponent: React.FC = ({ children }) => { if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); + console.log('AppGoesBackgroundState HIGH'); + console.log( + 'High State Set Time on Background' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP)) + ); return; } return; diff --git a/src/types/storageKeys.ts b/src/types/storageKeys.ts index 24a2469d..bb480c6a 100644 --- a/src/types/storageKeys.ts +++ b/src/types/storageKeys.ts @@ -3,4 +3,5 @@ export enum StorageKeys { APP_BACKGROUND_TIMESTAMP = 'appBackgroundTimestamp', IS_USER_ACTIVE = 'isUserActive', USER_ACTIVITY_ON_APP = 'userActivityOnApp', + STATE_SET_TIMESTAMP = 'stateSetTimestamp', } From bc5e51c4bd3e955c13555d386e878c65fbd0614e Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Mon, 18 Sep 2023 20:46:35 +0530 Subject: [PATCH 06/17] saved changes --- src/common/TrackingComponent.tsx | 52 ++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index 832f71dd..8b72a6b9 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -199,10 +199,16 @@ const TrackingComponent: React.FC = ({ children }) => { const handleUpdateActivity = async () => { //ft==>app opened in foreground //bt==>app is minimized or closed + 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); @@ -222,21 +228,20 @@ const TrackingComponent: React.FC = ({ children }) => { const ACTIVITY_TIME_WINDOW_HIGH = getActivityTimeWindowHigh(); const ACTIVITY_TIME_WINDOW_MEDIUM = getActivityTimeWindowMedium(); - const isStateSetTimeMoreThanHighRangeAndLessThanMediumRange = - diffBetweenCurrentTimeAndSetStateTime >= ACTIVITY_TIME_WINDOW_HIGH; - const isStateSetTimeMoreThanMediumRange = - diffBetweenCurrentTimeAndSetStateTime >= - ACTIVITY_TIME_WINDOW_MEDIUM - ACTIVITY_TIME_WINDOW_HIGH; + 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 (foregroundTimestamp == null) { - console.log('fts set after installation'); - await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, dayJs().toString()); - } if (diffBetweenCurrentTimeAndForegroundTime >= ACTIVITY_TIME_ON_APP) { console.log('App State Active HIGH'); await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); + //await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); + console.log( + 'High State Set Time for Active User' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP)) + ); return; } return; @@ -252,8 +257,8 @@ const TrackingComponent: React.FC = ({ children }) => { console.log(diffBetweenBackgroundAndForegroundTime); console.log(diffBetweenCurrentTimeAndForegroundTime); console.log(diffBetweenCurrentTimeAndBackgroundTime); - console.log(isStateSetTimeMoreThanHighRangeAndLessThanMediumRange); - console.log(isStateSetTimeMoreThanMediumRange); + console.log(isStateSetTimeWithinHighRange); + console.log(isStateSetTimeWithinMediumRange); console.log(isForegroundTimeAfterBackground); console.log(ACTIVITY_TIME_ON_APP); console.log(ACTIVITY_TIME_WINDOW_HIGH); @@ -264,30 +269,31 @@ const TrackingComponent: React.FC = ({ children }) => { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); console.log('isForegroundTimeAfterBackground HIGH'); - console.log('High State Set Time' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP))); + console.log( + 'High State Set Time on Foreground>Background' + + (await getItem(StorageKeys.STATE_SET_TIMESTAMP)) + ); return; } return; - } else if ( - isStateSetTimeMoreThanHighRangeAndLessThanMediumRange && - (await getItem(StorageKeys.USER_ACTIVITY_ON_APP)) == AgentActivity.HIGH - ) { + } else if (isStateSetTimeWithinHighRange) { + console.log('isStateSetTimeWithinHighRange HIGH and state is not set right now'); + return; + } else if (isStateSetTimeWithinMediumRange) { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.MEDIUM); - await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(2, 'minutes').toString()); + //await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(2, 'minutes').toString()); console.log('isStateSetTimeWithInMediumRange MEDIUM'); console.log('Medium State Set Time' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP))); return; - } else if ( - isStateSetTimeMoreThanMediumRange && - (await getItem(StorageKeys.USER_ACTIVITY_ON_APP)) == AgentActivity.MEDIUM - ) { + } else { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.LOW); - await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(2, 'minutes').toString()); + //await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(4, 'minutes').toString()); console.log('isStateSetTimeWithInLowRange LOW'); console.log('Low State Set Time' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP))); - } else { return; } + + console.log('Never here'); }; const deleteCache = () => { From f0c67fd1e9af70911fa89017b68c8a8194fe19b2 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Tue, 19 Sep 2023 12:49:35 +0530 Subject: [PATCH 07/17] Logic for calculating activity updated --- App.tsx | 8 +++++--- src/common/TrackingComponent.tsx | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/App.tsx b/App.tsx index f03877a2..5539ee6b 100644 --- a/App.tsx +++ b/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'; @@ -43,6 +43,7 @@ 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(); @@ -107,9 +108,10 @@ function App() { return route?.name || ''; }; - async function setForegroundTimeStamp() { + 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); @@ -138,7 +140,7 @@ function App() { })(); checkCodePushAndSync(); handleUpdatedConfigureValuesFromFirebase(); - setForegroundTimeStamp(); + setForegroundTimeStampAndClickstream(); return () => { appStateChange.remove(); diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index 8b72a6b9..eabb73f6 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -43,6 +43,8 @@ import { 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', @@ -283,13 +285,13 @@ const TrackingComponent: React.FC = ({ children }) => { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.MEDIUM); //await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(2, 'minutes').toString()); console.log('isStateSetTimeWithInMediumRange MEDIUM'); - console.log('Medium State Set Time' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP))); + console.log('Medium State Set with High Timestamp at ' + stateSetTimestamp); return; } else { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.LOW); //await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(4, 'minutes').toString()); console.log('isStateSetTimeWithInLowRange LOW'); - console.log('Low State Set Time' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP))); + console.log('Low State Set with High Timestamp at' + stateSetTimestamp); return; } @@ -395,7 +397,6 @@ const TrackingComponent: React.FC = ({ 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( @@ -407,7 +408,6 @@ const TrackingComponent: React.FC = ({ children }) => { if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); - console.log('AppGoesBackgroundState HIGH'); console.log( 'High State Set Time on Background' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP)) ); @@ -424,6 +424,7 @@ const TrackingComponent: React.FC = ({ children }) => { if (nextAppState === AppStates.ACTIVE) { console.log('App State Active'); await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, now); + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_APP_FOREGROUND, { now }); handleGetCaseSyncStatus(); dispatch(getConfigData()); CosmosForegroundService.start(tasks); @@ -432,6 +433,7 @@ const TrackingComponent: React.FC = ({ children }) => { console.log('App State Background'); await setItem(StorageKeys.APP_BACKGROUND_TIMESTAMP, now); userActivityUpdateOnBackground(); + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_APP_BACKGROUND, { now }); } appState.current = nextAppState; }; From cbd07c6f889c9f3450b88682262e9ab092917e6c Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Tue, 19 Sep 2023 12:49:53 +0530 Subject: [PATCH 08/17] Logic for calculating activity updated --- src/common/TrackingComponent.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index eabb73f6..93154415 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -269,12 +269,9 @@ const TrackingComponent: React.FC = ({ children }) => { if (isForegroundTimeAfterBackground) { if (diffBetweenCurrentTimeAndForegroundTime >= ACTIVITY_TIME_ON_APP) { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); - await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); + //await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); console.log('isForegroundTimeAfterBackground HIGH'); - console.log( - 'High State Set Time on Foreground>Background' + - (await getItem(StorageKeys.STATE_SET_TIMESTAMP)) - ); + console.log('High State Set Time on Foreground>Background' + stateSetTimestamp); return; } return; From 0383b71c730f1348c193cfb239690099771beed2 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Tue, 19 Sep 2023 15:09:37 +0530 Subject: [PATCH 09/17] Comments resolved --- .../AgentActivityConfigurableConstants.ts | 6 +- src/common/TrackingComponent.tsx | 67 ++----------------- .../firebaseFetchAndUpdate.service.ts | 4 +- 3 files changed, 10 insertions(+), 67 deletions(-) diff --git a/src/common/AgentActivityConfigurableConstants.ts b/src/common/AgentActivityConfigurableConstants.ts index 07976239..015db2b6 100644 --- a/src/common/AgentActivityConfigurableConstants.ts +++ b/src/common/AgentActivityConfigurableConstants.ts @@ -1,6 +1,6 @@ -let ACTIVITY_TIME_ON_APP: number = 5; -let ACTIVITY_TIME_WINDOW_HIGH: number = 2; -let ACTIVITY_TIME_WINDOW_MEDIUM: number = 4; +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; diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index 93154415..98ddba66 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -182,7 +182,7 @@ const TrackingComponent: React.FC = ({ children }) => { const isForegroundTimeWithInRange = diffBetweenCurrentTimeAndForegroundTime <= ACTIVITY_TIME_WINDOW; const isForegroundTimeAfterBackground = dayJs(foregroundTimestamp).isAfter(backgroundTimestamp); - const ACTIVITY_TIME_ON_APP = 5; // 5 seconds + const ACTIVITY_TIME_ON_APP = getActivityTimeOnApp(); if (isForegroundTimeWithInRange) { if ( @@ -199,9 +199,6 @@ const TrackingComponent: React.FC = ({ children }) => { }; const handleUpdateActivity = async () => { - //ft==>app opened in foreground - //bt==>app is minimized or closed - const foregroundTimestamp = await getItem(StorageKeys.APP_FOREGROUND_TIMESTAMP); const backgroundTimestamp = await getItem(StorageKeys.APP_BACKGROUND_TIMESTAMP); const stateSetTimestamp = await getItem(StorageKeys.STATE_SET_TIMESTAMP); @@ -215,14 +212,8 @@ const TrackingComponent: React.FC = ({ children }) => { const backgroundTime = dayJs(backgroundTimestamp); const stateSetTime = dayJs(stateSetTimestamp); - const diffBetweenBackgroundAndForegroundTime = dayJs(backgroundTime).diff( - foregroundTime, - 'seconds' - ); const diffBetweenCurrentTimeAndForegroundTime = dayJs().diff(foregroundTime, 'seconds') < 0 ? 0 : dayJs().diff(foregroundTime, 'seconds'); - const diffBetweenCurrentTimeAndBackgroundTime = - dayJs().diff(backgroundTime, 'minutes') < 0 ? 0 : dayJs().diff(backgroundTime, 'minutes'); const diffBetweenCurrentTimeAndSetStateTime = dayJs().diff(stateSetTime, 'minutes') < 0 ? 0 : dayJs().diff(stateSetTime, 'minutes'); @@ -238,61 +229,27 @@ const TrackingComponent: React.FC = ({ children }) => { if (AppState.currentState === AppStates.ACTIVE) { if (diffBetweenCurrentTimeAndForegroundTime >= ACTIVITY_TIME_ON_APP) { - console.log('App State Active HIGH'); await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); - //await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); - console.log( - 'High State Set Time for Active User' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP)) - ); return; } return; } - console.log('handleUpdateActivity'); - console.log(foregroundTimestamp); - console.log(backgroundTimestamp); - console.log(stateSetTimestamp); - console.log(foregroundTime); - console.log(backgroundTime); - console.log(stateSetTime); - console.log(diffBetweenBackgroundAndForegroundTime); - console.log(diffBetweenCurrentTimeAndForegroundTime); - console.log(diffBetweenCurrentTimeAndBackgroundTime); - console.log(isStateSetTimeWithinHighRange); - console.log(isStateSetTimeWithinMediumRange); - console.log(isForegroundTimeAfterBackground); - console.log(ACTIVITY_TIME_ON_APP); - console.log(ACTIVITY_TIME_WINDOW_HIGH); - console.log(ACTIVITY_TIME_WINDOW_MEDIUM); - if (isForegroundTimeAfterBackground) { if (diffBetweenCurrentTimeAndForegroundTime >= ACTIVITY_TIME_ON_APP) { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); - //await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); - console.log('isForegroundTimeAfterBackground HIGH'); - console.log('High State Set Time on Foreground>Background' + stateSetTimestamp); return; } return; } else if (isStateSetTimeWithinHighRange) { - console.log('isStateSetTimeWithinHighRange HIGH and state is not set right now'); return; } else if (isStateSetTimeWithinMediumRange) { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.MEDIUM); - //await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(2, 'minutes').toString()); - console.log('isStateSetTimeWithInMediumRange MEDIUM'); - console.log('Medium State Set with High Timestamp at ' + stateSetTimestamp); return; } else { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.LOW); - //await setItem(StorageKeys.STATE_SET_TIMESTAMP, stateSetTime.add(4, 'minutes').toString()); - console.log('isStateSetTimeWithInLowRange LOW'); - console.log('Low State Set with High Timestamp at' + stateSetTimestamp); return; } - - console.log('Never here'); }; const deleteCache = () => { @@ -347,15 +304,14 @@ const TrackingComponent: React.FC = ({ children }) => { { taskId: FOREGROUND_TASKS.UPDATE_AGENT_ACTIVENESS, task: handleUpdateActiveness, - //delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes + // delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes delay: MILLISECONDS_IN_A_MINUTE / 3, // 20 seconds onLoop: true, }, { taskId: FOREGROUND_TASKS.UPDATE_AGENT_ACTIVITY, task: handleUpdateActivity, - //delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes - delay: MILLISECONDS_IN_A_MINUTE / 3, // 20 seconds + delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes onLoop: true, }, { @@ -405,21 +361,15 @@ const TrackingComponent: React.FC = ({ children }) => { if (diffBetweenBackgroundAndForegroundTime >= ACTIVITY_TIME_ON_APP) { await setItem(StorageKeys.USER_ACTIVITY_ON_APP, AgentActivity.HIGH); await setItem(StorageKeys.STATE_SET_TIMESTAMP, dayJs().toString()); - console.log( - 'High State Set Time on Background' + (await getItem(StorageKeys.STATE_SET_TIMESTAMP)) - ); return; } return; }; const handleAppStateChange = async (nextAppState: AppStateStatus) => { - console.log(nextAppState); - // App comes to foreground from background const now = dayJs().toString(); if (nextAppState === AppStates.ACTIVE) { - console.log('App State Active'); await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, now); addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_APP_FOREGROUND, { now }); handleGetCaseSyncStatus(); @@ -427,7 +377,6 @@ const TrackingComponent: React.FC = ({ children }) => { CosmosForegroundService.start(tasks); } if (nextAppState === AppStates.BACKGROUND) { - console.log('App State Background'); await setItem(StorageKeys.APP_BACKGROUND_TIMESTAMP, now); userActivityUpdateOnBackground(); addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_APP_BACKGROUND, { now }); @@ -454,14 +403,8 @@ const TrackingComponent: React.FC = ({ 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); - }); + appStateSubscription = AppState.addEventListener('change', handleAppStateChange); + CosmosForegroundService.start(tasks); return () => { appStateSubscription?.remove(); }; diff --git a/src/services/firebaseFetchAndUpdate.service.ts b/src/services/firebaseFetchAndUpdate.service.ts index 6bfd81bd..0659b478 100644 --- a/src/services/firebaseFetchAndUpdate.service.ts +++ b/src/services/firebaseFetchAndUpdate.service.ts @@ -6,9 +6,9 @@ import { } from '../common/AgentActivityConfigurableConstants'; async function handleUpdatedConfigureValuesFromFirebase() { - await remoteConfig().fetch(10); + await remoteConfig().fetch(15 * 60 * 1000); //15 minutes remoteConfig() - .fetchAndActivate() + .activate() .then((fetchedRemotely) => { if (fetchedRemotely) { console.log('Configs were fetched.'); From dbfa6834889e16c9f6add3bfdc602ba522f4d160 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Tue, 19 Sep 2023 15:33:16 +0530 Subject: [PATCH 10/17] Comments resolved --- src/common/TrackingComponent.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/common/TrackingComponent.tsx b/src/common/TrackingComponent.tsx index 98ddba66..9d8e448f 100644 --- a/src/common/TrackingComponent.tsx +++ b/src/common/TrackingComponent.tsx @@ -304,8 +304,7 @@ const TrackingComponent: React.FC = ({ children }) => { { taskId: FOREGROUND_TASKS.UPDATE_AGENT_ACTIVENESS, task: handleUpdateActiveness, - // delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes - delay: MILLISECONDS_IN_A_MINUTE / 3, // 20 seconds + delay: ACTIVITY_TIME_WINDOW * MILLISECONDS_IN_A_MINUTE, // 10 minutes onLoop: true, }, { From 5a373f35f6ef5f75d33761f01d7d8e8d3d35123e Mon Sep 17 00:00:00 2001 From: Aman Chaturvedi Date: Wed, 20 Sep 2023 13:58:55 +0530 Subject: [PATCH 11/17] TP-0 | Alias resolver --- babel.config.js | 18 +++++++++++++++++- tsconfig.json | 30 +++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/babel.config.js b/babel.config.js index 5bff64bf..a9ea82f9 100644 --- a/babel.config.js +++ b/babel.config.js @@ -8,7 +8,23 @@ module.exports = { cwd: 'babelrc', extensions: ['.ts', '.tsx', '.js', '.ios.js', '.android.js'], alias: { - '@cuteapp': './app', + '@components': './src/components', + '@hooks': './src/hooks', + '@actions': './src/action', + '@reducers': './src/reducer', + '@constants': './src/constants', + '@screens': './src/screens', + '@services': './src/services', + '@types': './src/types', + '@common': './src/common', + '@assets': './src/assets', + '@store': './src/store/store', + '@utils': './src/utlis', + '@rn-ui-lib/components': './RN-UI-LIB/src/components', + '@rn-ui-lib/icons': './RN-UI-LIB/src/Icons', + '@rn-ui-lib/styles': './RN-UI-LIB/src/styles/index', + '@rn-ui-lib/colors': './RN-UI-LIB/src/styles/colors', + '@rn-ui-lib/utils': './RN-UI-LIB/src/utlis', }, }, ], diff --git a/tsconfig.json b/tsconfig.json index bc394ebd..82cea311 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,9 +5,33 @@ /* Visit https://aka.ms/tsconfig.json to read more about this file */ "emitDecoratorMetadata": true, "experimentalDecorators": true, - "lib": ["dom","es5","es2020"], - + "lib": [ + "dom", + "es5", + "es2020" + ], /* Completeness */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "baseUrl": ".", + "paths": { + "@components/*": ["src/components/*"], + "@hooks": ["src/hooks/index"], + "@hooks/*": ["src/hooks/*"], + "@actions/*": ["src/action/*"], + "@reducers/*": ["src/reducer/*"], + "@constants/*": ["src/constants/*"], + "@screens/*": ["src/screens/*"], + "@services/*": ["src/services/*"], + "@types/*": ["src/types/*"], + "@common/*": ["src/common/*"], + "@assets/*": ["src/assets/*"], + "@store": ["src/store/store"], + "@utils/*": ["src/utlis/*"], + "@rn-ui-lib/components/*": ["RN-UI-LIB/src/components/*"], + "@rn-ui-lib/icons/*": ["RN-UI-LIB/src/Icons/*"], + "@rn-ui-lib/styles": ["RN-UI-LIB/src/styles/index"], + "@rn-ui-lib/colors": ["RN-UI-LIB/src/styles/colors"], + "@rn-ui-lib/utils/*": ["RN-UI-LIB/src/utlis/*"], + } }, } From 20cbec2b80be42f1362a651661b1e6ffdc203766 Mon Sep 17 00:00:00 2001 From: Aman Chaturvedi Date: Wed, 20 Sep 2023 16:05:41 +0530 Subject: [PATCH 12/17] TP-0 | alias resolver fix --- babel.config.js | 2 +- src/screens/allCases/index.tsx | 26 +++++++++++++------------- tsconfig.json | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/babel.config.js b/babel.config.js index a9ea82f9..4b6206a9 100644 --- a/babel.config.js +++ b/babel.config.js @@ -19,7 +19,7 @@ module.exports = { '@common': './src/common', '@assets': './src/assets', '@store': './src/store/store', - '@utils': './src/utlis', + '@utils': './src/components/utlis', '@rn-ui-lib/components': './RN-UI-LIB/src/components', '@rn-ui-lib/icons': './RN-UI-LIB/src/Icons', '@rn-ui-lib/styles': './RN-UI-LIB/src/styles/index', diff --git a/src/screens/allCases/index.tsx b/src/screens/allCases/index.tsx index 0fc99dff..2ec22de5 100644 --- a/src/screens/allCases/index.tsx +++ b/src/screens/allCases/index.tsx @@ -1,27 +1,27 @@ import React, { useEffect, useMemo } from 'react'; -import { useAppDispatch, useAppSelector } from '../../hooks'; +import { useAppDispatch, useAppSelector } from '@hooks'; import CasesList from './CasesList'; -import { RootState } from '../../store/store'; -import { initCrashlytics } from '../../components/utlis/firebaseUtils'; +import { RootState } from '@store'; +import { initCrashlytics } from '@utils/firebaseUtils'; import Layout from '../layout/Layout'; -import BottomNavigator, { ITabScreen } from '../../../RN-UI-LIB/src/components/bottomNavigator'; -import CasesIcon from '../../../RN-UI-LIB/src/Icons/CasesIcon'; +import BottomNavigator, { ITabScreen } from '@rn-ui-lib/components/bottomNavigator'; +import CasesIcon from '@rn-ui-lib/icons/CasesIcon'; import Profile from '../Profile'; -import ProfileIcon from '../../../RN-UI-LIB/src/Icons/ProfileIcon'; -import VisitPlanIcon from '../../../RN-UI-LIB/src/Icons/VisitPlanIcon'; +import ProfileIcon from '@rn-ui-lib/icons/ProfileIcon'; +import VisitPlanIcon from '@rn-ui-lib/icons/VisitPlanIcon'; import CasesActionButtons from './CasesActionButtons'; -import FullScreenLoader from '../../../RN-UI-LIB/src/components/FullScreenLoader'; -import { getCurrentScreen } from '../../components/utlis/navigationUtlis'; +import FullScreenLoader from '@rn-ui-lib/components/FullScreenLoader'; +import { getCurrentScreen } from '@utils/navigationUtlis'; import { resetSelectedTodoList, resetTodoList, setLoading, setVisitPlansUpdating, -} from '../../reducer/allCasesSlice'; -import { addClickstreamEvent } from '../../services/clickstreamEventService'; -import { CLICKSTREAM_EVENT_NAMES } from '../../common/Constants'; +} from '@reducers/allCasesSlice'; +import { addClickstreamEvent } from '@services/clickstreamEventService'; +import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants'; import { BOTTOM_TAB_ROUTES } from './constants'; -import { getSelfieDocument } from '../../action/profileActions'; +import { getSelfieDocument } from '@actions/profileActions'; const AllCasesMain = () => { const { pendingList, pinnedList, completedList, loading } = useAppSelector( diff --git a/tsconfig.json b/tsconfig.json index 82cea311..da6b376f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,7 @@ "@common/*": ["src/common/*"], "@assets/*": ["src/assets/*"], "@store": ["src/store/store"], - "@utils/*": ["src/utlis/*"], + "@utils/*": ["src/components/utlis/*"], "@rn-ui-lib/components/*": ["RN-UI-LIB/src/components/*"], "@rn-ui-lib/icons/*": ["RN-UI-LIB/src/Icons/*"], "@rn-ui-lib/styles": ["RN-UI-LIB/src/styles/index"], From 9a15e8158d58abfc975e92cf39c022802bc3cef0 Mon Sep 17 00:00:00 2001 From: Aman Chaturvedi Date: Fri, 22 Sep 2023 12:22:19 +0530 Subject: [PATCH 13/17] TP-0 | Root alias added --- babel.config.js | 1 + tsconfig.json | 1 + 2 files changed, 2 insertions(+) diff --git a/babel.config.js b/babel.config.js index 4b6206a9..ae7561b4 100644 --- a/babel.config.js +++ b/babel.config.js @@ -8,6 +8,7 @@ module.exports = { cwd: 'babelrc', extensions: ['.ts', '.tsx', '.js', '.ios.js', '.android.js'], alias: { + '@root': './src', '@components': './src/components', '@hooks': './src/hooks', '@actions': './src/action', diff --git a/tsconfig.json b/tsconfig.json index da6b376f..d9248cf8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,6 +14,7 @@ "skipLibCheck": true, /* Skip type checking all .d.ts files. */ "baseUrl": ".", "paths": { + "@root/*": ["."], "@components/*": ["src/components/*"], "@hooks": ["src/hooks/index"], "@hooks/*": ["src/hooks/*"], From b7fc6c134d5262ba54ee6d151d236cd8ee0a7650 Mon Sep 17 00:00:00 2001 From: Shri Prakash Bajpai Date: Wed, 27 Sep 2023 19:19:23 +0530 Subject: [PATCH 14/17] Update firebaseFetchAndUpdate.service.ts --- src/services/firebaseFetchAndUpdate.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/firebaseFetchAndUpdate.service.ts b/src/services/firebaseFetchAndUpdate.service.ts index 0659b478..3034e053 100644 --- a/src/services/firebaseFetchAndUpdate.service.ts +++ b/src/services/firebaseFetchAndUpdate.service.ts @@ -6,7 +6,7 @@ import { } from '../common/AgentActivityConfigurableConstants'; async function handleUpdatedConfigureValuesFromFirebase() { - await remoteConfig().fetch(15 * 60 * 1000); //15 minutes + await remoteConfig().fetch(15 * 60 ); //15 minutes remoteConfig() .activate() .then((fetchedRemotely) => { From cfd5f4970e98a3b85c4206b8db9eefdc622fbfed Mon Sep 17 00:00:00 2001 From: Shri Prakash Bajpai Date: Wed, 27 Sep 2023 19:32:59 +0530 Subject: [PATCH 15/17] Update firebaseFetchAndUpdate.service.ts Make fetch time as constant --- src/services/firebaseFetchAndUpdate.service.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/firebaseFetchAndUpdate.service.ts b/src/services/firebaseFetchAndUpdate.service.ts index 3034e053..1816fb35 100644 --- a/src/services/firebaseFetchAndUpdate.service.ts +++ b/src/services/firebaseFetchAndUpdate.service.ts @@ -5,8 +5,9 @@ import { setActivityTimeWindowMedium, } from '../common/AgentActivityConfigurableConstants'; +const FIREBASE_FETCH_TIME = 15 * 60; async function handleUpdatedConfigureValuesFromFirebase() { - await remoteConfig().fetch(15 * 60 ); //15 minutes + await remoteConfig().fetch(FIREBASE_FETCH_TIME); //15 minutes remoteConfig() .activate() .then((fetchedRemotely) => { From 1f022c0b98f22e01d0bd3e13a954af6ed693f420 Mon Sep 17 00:00:00 2001 From: yashmantri Date: Wed, 27 Sep 2023 23:22:51 +0530 Subject: [PATCH 16/17] TP-41688 | Screenshot Tracking + Hard release changes --- android/app/build.gradle | 6 -- .../main/java/com/avapp/MainApplication.java | 1 + .../com/avapp/ScreenshotBlockerModule.java | 101 ++++++++++++++++++ .../avapp/ScreenshotBlockerModulePackage.java | 27 +++++ package.json | 1 + src/common/Constants.ts | 4 + src/components/utlis/ScreenshotBlocker.tsx | 5 + src/hooks/useScreenshotTracking.ts | 39 +++++++ src/reducer/allCasesSlice.ts | 6 ++ src/screens/auth/AuthRouter.tsx | 2 + .../caseDetails/CollectionCaseDetail.tsx | 9 ++ yarn.lock | 5 + 12 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 android/app/src/main/java/com/avapp/ScreenshotBlockerModule.java create mode 100644 android/app/src/main/java/com/avapp/ScreenshotBlockerModulePackage.java create mode 100644 src/components/utlis/ScreenshotBlocker.tsx create mode 100644 src/hooks/useScreenshotTracking.ts diff --git a/android/app/build.gradle b/android/app/build.gradle index e940905d..ed3335b2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -135,12 +135,6 @@ def VERSION_CODE = 85 def VERSION_NAME = "2.4.1" android { - packagingOptions { - pickFirst 'lib/x86/libc++_shared.so' - pickFirst 'lib/x86_64/libc++_shared.so' - pickFirst 'lib/armeabi-v7a/libc++_shared.so' - pickFirst 'lib/arm64-v8a/libc++_shared.so' - } ndkVersion rootProject.ext.ndkVersion compileSdkVersion rootProject.ext.compileSdkVersion diff --git a/android/app/src/main/java/com/avapp/MainApplication.java b/android/app/src/main/java/com/avapp/MainApplication.java index 809273f1..d051ff98 100644 --- a/android/app/src/main/java/com/avapp/MainApplication.java +++ b/android/app/src/main/java/com/avapp/MainApplication.java @@ -37,6 +37,7 @@ public class MainApplication extends Application implements ReactApplication { List packages = new PackageList(this).getPackages(); // Packages that cannot be autolinked yet can be added manually here, for example: packages.add(new DeviceUtilsModulePackage()); + packages.add(new ScreenshotBlockerModulePackage()); return packages; } diff --git a/android/app/src/main/java/com/avapp/ScreenshotBlockerModule.java b/android/app/src/main/java/com/avapp/ScreenshotBlockerModule.java new file mode 100644 index 00000000..37cd1b86 --- /dev/null +++ b/android/app/src/main/java/com/avapp/ScreenshotBlockerModule.java @@ -0,0 +1,101 @@ +package com.avapp; + +import android.app.Activity; +import android.view.WindowManager; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.modules.core.DeviceEventManagerModule; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.Arguments; + +import android.os.Handler; +import android.os.Looper; +import android.content.ContentResolver; +import android.database.ContentObserver; +import android.net.Uri; +import android.provider.MediaStore; + +public class ScreenshotBlockerModule extends ReactContextBaseJavaModule { + private ReactApplicationContext reactContext; + private ContentObserver contentObserver; + private boolean isTracking = false; + + public ScreenshotBlockerModule(ReactApplicationContext reactContext) { + super(reactContext); + this.reactContext = reactContext; + } + + @Override + public String getName() { + return "ScreenshotBlocker"; + } + + @ReactMethod + public void blockScreenshots() { + new Handler(Looper.getMainLooper()).post(new Runnable() { + Activity activity = getCurrentActivity(); + + @Override + public void run() { + if (activity != null) { + activity.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_SECURE, + WindowManager.LayoutParams.FLAG_SECURE + ); + } + } + }); + } + + @ReactMethod + public void unblockScreenshots() { + new Handler(Looper.getMainLooper()).post(new Runnable() { + Activity activity = getCurrentActivity(); + + @Override + public void run() { + if (activity != null) { + activity.getWindow().clearFlags( + WindowManager.LayoutParams.FLAG_SECURE + ); + } + } + }); + } + + @ReactMethod + public void startScreenshotTracking() { + if (!isTracking) { + isTracking = true; + ContentResolver contentResolver = getCurrentActivity().getContentResolver(); + contentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { + long lastEventTimestamp = 0; + + @Override + public void onChange(boolean selfChange, Uri uri) { + long currentTimeMillis = System.currentTimeMillis(); + + if (currentTimeMillis - lastEventTimestamp > 1000) { + sendScreenshotEvent(); + lastEventTimestamp = currentTimeMillis; + } + } + }; + + contentResolver.registerContentObserver( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + true, + contentObserver + ); + } + } + + private void sendScreenshotEvent() { + WritableMap params = Arguments.createMap(); + params.putBoolean("isScreenshotDetected", true); + reactContext + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit("screenshotTaken", params); + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/avapp/ScreenshotBlockerModulePackage.java b/android/app/src/main/java/com/avapp/ScreenshotBlockerModulePackage.java new file mode 100644 index 00000000..b62a1e78 --- /dev/null +++ b/android/app/src/main/java/com/avapp/ScreenshotBlockerModulePackage.java @@ -0,0 +1,27 @@ +package com.avapp; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class ScreenshotBlockerModulePackage implements ReactPackage { + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createNativeModules( + ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + + modules.add(new ScreenshotBlockerModule(reactContext)); + + return modules; + } +} \ No newline at end of file diff --git a/package.json b/package.json index ccc82a6b..0f2a4850 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "react-native-gzip": "1.0.0", "react-native-image-picker": "4.10.2", "react-native-pager-view": "6.1.2", + "react-native-pdf-renderer": "1.1.1", "react-native-permissions": "3.6.1", "react-native-qrcode-svg": "^6.2.0", "react-native-safe-area-context": "4.4.1", diff --git a/src/common/Constants.ts b/src/common/Constants.ts index 8cf8ca88..d3d1d46a 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -95,6 +95,10 @@ export const CLICKSTREAM_EVENT_NAMES = { name: 'FA_LOGIN_SCREEN_SEND_OTP_API_FAILED', description: 'Send OTP API failed', }, + FA_SCREENSHOT_TAKEN: { + name: 'FA_SCREENSHOT_TAKEN', + description: 'Screenshot atempt detected', + }, // OTP screen AV_OTP_SCREEN_LOAD: { name: 'FA_OTP_SCREEN_LOAD', description: 'OTP screen loaded' }, diff --git a/src/components/utlis/ScreenshotBlocker.tsx b/src/components/utlis/ScreenshotBlocker.tsx new file mode 100644 index 00000000..d0269405 --- /dev/null +++ b/src/components/utlis/ScreenshotBlocker.tsx @@ -0,0 +1,5 @@ +import { NativeModules } from 'react-native'; + +const { ScreenshotBlocker } = NativeModules; + +export default ScreenshotBlocker; diff --git a/src/hooks/useScreenshotTracking.ts b/src/hooks/useScreenshotTracking.ts new file mode 100644 index 00000000..4a8a34fa --- /dev/null +++ b/src/hooks/useScreenshotTracking.ts @@ -0,0 +1,39 @@ +import { useEffect, useMemo } from 'react'; +import { NativeEventEmitter } from 'react-native'; +import { useAppSelector } from '.'; +import { CLICKSTREAM_EVENT_NAMES } from '../common/Constants'; +import { getCurrentScreen } from '../components/utlis/navigationUtlis'; +import ScreenshotBlocker from '../components/utlis/ScreenshotBlocker'; +import { addClickstreamEvent } from '../services/clickstreamEventService'; + +const useScreenshotTracking = () => { + const { user, allCases } = useAppSelector((state) => ({ + user: state.user, + allCases: state.allCases, + })); + + const screenshotEventEmitter = useMemo(() => new NativeEventEmitter(ScreenshotBlocker), []); + useEffect(() => { + ScreenshotBlocker.startScreenshotTracking(); + + const screenshotTakenSubscription = screenshotEventEmitter.addListener( + 'screenshotTaken', + (event) => { + if (event?.isScreenshotDetected) { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SCREENSHOT_TAKEN, { + userId: user?.user?.referenceId ?? '', + caseId: allCases.selectedCaseId ?? '', + page: getCurrentScreen()?.name, + }); + return; + } + } + ); + + return () => { + if (screenshotTakenSubscription) screenshotTakenSubscription.remove(); + }; + }, [allCases?.selectedCaseId, user?.user?.referenceId]); +}; + +export default useScreenshotTracking; diff --git a/src/reducer/allCasesSlice.ts b/src/reducer/allCasesSlice.ts index bf1ffab6..fae5f5f4 100644 --- a/src/reducer/allCasesSlice.ts +++ b/src/reducer/allCasesSlice.ts @@ -44,6 +44,7 @@ interface IAllCasesSlice { completedList: ICaseItem[]; pinnedList: ICaseItem[]; newVisitedCases: string[]; + selectedCaseId: string; } const initialState: IAllCasesSlice = { @@ -67,6 +68,7 @@ const initialState: IAllCasesSlice = { completedList: [], pinnedList: [], newVisitedCases: [], + selectedCaseId: '', }; const getCaseListComponents = (casesList: ICaseItem[], caseDetails: Record) => { @@ -563,6 +565,9 @@ const allCasesSlice = createSlice({ } }); }, + setSelectedCaseId: (state, action) => { + state.selectedCaseId = action.payload; + }, }, }); @@ -584,6 +589,7 @@ export const { resetNewVisitedCases, syncCasesByFallback, setCasesImageUri, + setSelectedCaseId, } = allCasesSlice.actions; export default allCasesSlice.reducer; diff --git a/src/screens/auth/AuthRouter.tsx b/src/screens/auth/AuthRouter.tsx index a3ab5e9c..26d5ae47 100644 --- a/src/screens/auth/AuthRouter.tsx +++ b/src/screens/auth/AuthRouter.tsx @@ -15,6 +15,7 @@ import useFCM from '../../hooks/useFCM'; import { NetworkStatusService } from '../../services/network-monitoring.service'; import BlockerScreen from '../../common/BlockerScreen'; import CosmosForegroundService from '../../services/foregroundServices/foreground.service'; +import useScreenshotTracking from '../../hooks/useScreenshotTracking'; const AuthRouter = () => { const dispatch = useAppDispatch(); @@ -61,6 +62,7 @@ const AuthRouter = () => { // Firebase cloud messaging listener useFCM(); + useScreenshotTracking(); return isLoggedIn ? ( diff --git a/src/screens/caseDetails/CollectionCaseDetail.tsx b/src/screens/caseDetails/CollectionCaseDetail.tsx index fbeb55c8..3131fcf1 100644 --- a/src/screens/caseDetails/CollectionCaseDetail.tsx +++ b/src/screens/caseDetails/CollectionCaseDetail.tsx @@ -42,6 +42,7 @@ import { getLoanAccountNumber } from '../../components/utlis/commonFunctions'; import EmiBreakupBottomSheet from '../emiSchedule/EmiBreakupBottomSheet'; import { CollectionCaseWidgetId } from '../../types/template.types'; import { useIsFocused } from '@react-navigation/native'; +import { setSelectedCaseId } from '../../reducer/allCasesSlice'; interface ICaseDetails { route: { @@ -78,6 +79,14 @@ const CollectionCaseDetails: React.FC = (props) => { }, } = props; + useEffect(() => { + if (caseId) dispatch(setSelectedCaseId(caseId)); + + return () => { + dispatch(setSelectedCaseId('')); + }; + }, [caseId]); + const dispatch = useAppDispatch(); const isFocused = useIsFocused(); const isOnline = useIsOnline(); diff --git a/yarn.lock b/yarn.lock index 2f13bddd..5fe23084 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7775,6 +7775,11 @@ react-native-pager-view@6.1.2: resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.1.2.tgz#3522079b9a9d6634ca5e8d153bc0b4d660254552" integrity sha512-qs2KSFc+7N7B+UZ6SG2sTvCkppagm5fVyRclv1KFKc7lDtrhXLzN59tXJw575LDP/dRJoXsNwqUAhZJdws6ABQ== +react-native-pdf-renderer@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/react-native-pdf-renderer/-/react-native-pdf-renderer-1.1.1.tgz#73a5428c034a7c76bc5fe3435e584cd6493bdfb2" + integrity sha512-XNtSwtMKvH90YcJxZfUu0HRE/DjiXxXIaSa0PCAPPROFOXB5bQPTgZ5n70w98tzjQ5smKMJnMYDFJQV5/pA01w== + react-native-permissions@3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/react-native-permissions/-/react-native-permissions-3.6.1.tgz#73adcc1cef8cd57a9ef167b4507405f4ff5749c4" From ccc8793c23fd64266caca64e54a8bcc95958b401 Mon Sep 17 00:00:00 2001 From: yashmantri Date: Wed, 27 Sep 2023 23:23:31 +0530 Subject: [PATCH 17/17] TP-41688 | Version Bump --- android/app/build.gradle | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index ed3335b2..822c8e2d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -131,8 +131,8 @@ def reactNativeArchitectures() { return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } -def VERSION_CODE = 85 -def VERSION_NAME = "2.4.1" +def VERSION_CODE = 86 +def VERSION_NAME = "2.4.2" android { ndkVersion rootProject.ext.ndkVersion diff --git a/package.json b/package.json index 0f2a4850..081e9e1e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "AV_APP", - "version": "2.4.1", + "version": "2.4.2", "private": true, "scripts": { "android:dev": "yarn move:dev && react-native run-android",