TP-52572 | resolve comments

This commit is contained in:
Aman Chaturvedi
2024-02-07 21:30:13 +05:30
parent e3901db4a0
commit 4c5d916ff7
10 changed files with 86 additions and 62 deletions

View File

@@ -30,7 +30,6 @@
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />

View File

@@ -23,45 +23,51 @@ import Geolocation from 'react-native-geolocation-service';
import ForegroundService from '@supersami/rn-foreground-service'; import ForegroundService from '@supersami/rn-foreground-service';
import { getItem } from '@components/utlis/storageHelper'; import { getItem } from '@components/utlis/storageHelper';
import { AppState } from 'react-native'; import { AppState } from 'react-native';
import { logError } from '@components/utlis/errorUtils';
if (__DEV__) { if (__DEV__) {
LogBox.ignoreAllLogs(); LogBox.ignoreAllLogs();
} }
const geolocationForegroundTask = async () => { // TODO: Can use this code for starting fgs poc
Geolocation.getCurrentPosition(async (position) => { // const geolocationForegroundTask = async () => {
const { latitude, longitude, accuracy } = position.coords || {}; // Geolocation.getCurrentPosition(async (position) => {
if (!latitude || !longitude || !accuracy) return; // const { latitude, longitude, accuracy } = position.coords || {};
// if (!latitude || !longitude || !accuracy) return;
const isActiveOnApp = (await getItem(StorageKeys.IS_USER_ACTIVE)) || false; // const isActiveOnApp = (await getItem(StorageKeys.IS_USER_ACTIVE)) || false;
const userActivityonApp = // const userActivityonApp =
(await getItem(StorageKeys.USER_ACTIVITY_ON_APP)) || AgentActivity.LOW; // (await getItem(StorageKeys.USER_ACTIVITY_ON_APP)) || AgentActivity.LOW;
const geolocation = [ // const geolocation = [
{ // {
latitude, // latitude,
longitude, // longitude,
accuracy, // accuracy,
timestamp: Date.now(), // timestamp: Date.now(),
isActiveOnApp: Boolean(isActiveOnApp), // isActiveOnApp: Boolean(isActiveOnApp),
userActivityOnApp: String(userActivityonApp), // userActivityOnApp: String(userActivityonApp),
}, // },
]; // ];
axiosInstance.post(getApiUrl(ApiKeys.SEND_LOCATION), geolocation, { // axiosInstance.post(getApiUrl(ApiKeys.SEND_LOCATION), geolocation, {
headers: { // headers: {
donotHandleError: 'true', // donotHandleError: 'true',
}, // },
}); // });
}); // });
}; // };
// Background push notification handler // Background push notification handler
messaging().setBackgroundMessageHandler(async (remoteMessage) => { messaging().setBackgroundMessageHandler(async (remoteMessage) => {
const { data } = remoteMessage || {}; const { data } = remoteMessage || {};
if (data?.payload) { if (data?.payload) {
const notification = JSON.parse(data.payload); try {
if (notification?.showAsPn) { const notification = JSON.parse(data.payload);
handlePushNotification(notification, true); if (notification?.showAsPn) {
handlePushNotification(notification, true);
}
} catch (err) {
logError(err, 'Error in parsing background push notification');
} }
// TODO: Try to start foreground service if not working. // TODO: Try to start foreground service if not working.
// const isForegroundServiceRunning = await ForegroundService.is_running(); // const isForegroundServiceRunning = await ForegroundService.is_running();

View File

@@ -2,6 +2,7 @@ import { StackActions } from '@react-navigation/native';
import React, { RefObject } from 'react'; import React, { RefObject } from 'react';
import { TemplateRoutePrefix } from '../../common/Constants'; import { TemplateRoutePrefix } from '../../common/Constants';
import { CaseAllocationType } from '../../screens/allCases/interface'; import { CaseAllocationType } from '../../screens/allCases/interface';
import { PageRouteEnum } from '@screens/auth/ProtectedRouter';
export const navigationRef: RefObject<any> = React.createRef(); export const navigationRef: RefObject<any> = React.createRef();
@@ -11,9 +12,6 @@ export const getCurrentScreen = () => {
// if screen already exists then navigate to it otherwise push screen // if screen already exists then navigate to it otherwise push screen
export const navigateToScreen = (name: string, params: object = {}) => { export const navigateToScreen = (name: string, params: object = {}) => {
if (navigationRef.current?.getCurrentRoute()?.name === name) {
return;
}
navigationRef.current?.navigate(name, params); navigationRef.current?.navigate(name, params);
}; };
@@ -31,7 +29,7 @@ export const goBack = () => {
navigationRef.current?.goBack(); navigationRef.current?.goBack();
} }
else { else {
navigateToScreen('home') navigateToScreen(PageRouteEnum.HOME)
} }
}; };

View File

@@ -10,6 +10,7 @@ import { addClickstreamEvent } from '@services/clickstreamEventService';
import store from '@store'; import store from '@store';
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from '@react-native-async-storage/async-storage';
import { LAST_INITIAL_NOTIFICATION_ID } from '@components/utlis/deeplinkingUtils'; import { LAST_INITIAL_NOTIFICATION_ID } from '@components/utlis/deeplinkingUtils';
import { PageRouteEnum } from '@screens/auth/ProtectedRouter';
// Actions that can be performed on notification // Actions that can be performed on notification
export enum NotificationAction { export enum NotificationAction {
@@ -142,19 +143,19 @@ export const handleNotificationNavigation = (
if (!caseDetails) return; if (!caseDetails) return;
switch (action) { switch (action) {
case NotificationAction.VIEW_PAID_SCHEDULE: case NotificationAction.VIEW_PAID_SCHEDULE:
navigateToScreen(CaseDetailStackEnum.COLLECTION_CASE_DETAIL, { navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
screen: CaseDetailStackEnum.EMI_SCHEDULE, screen: CaseDetailStackEnum.EMI_SCHEDULE,
params: { caseId, scheduleTabId: EmiSelectedTab.PAID, notificationId }, params: { caseId, scheduleTabId: EmiSelectedTab.PAID, notificationId },
}); });
break; break;
case NotificationAction.VIEW_REPAYMENT: case NotificationAction.VIEW_REPAYMENT:
navigateToScreen(CaseDetailStackEnum.COLLECTION_CASE_DETAIL, { navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
screen: CaseDetailStackEnum.EMI_SCHEDULE, screen: CaseDetailStackEnum.EMI_SCHEDULE,
params: { caseId, tabId: EmiScheduleTabs.REPAYMENTS, notificationId }, params: { caseId, tabId: EmiScheduleTabs.REPAYMENTS, notificationId },
}); });
break; break;
case NotificationAction.CALL_CUSTOMER: case NotificationAction.CALL_CUSTOMER:
navigateToScreen(CaseDetailStackEnum.COLLECTION_CASE_DETAIL, { navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
screen: CaseDetailStackEnum.COLLECTION_CASE_DETAIL, screen: CaseDetailStackEnum.COLLECTION_CASE_DETAIL,
params: { caseId, showPhoneNumberBottomsheet: true, notificationId }, params: { caseId, showPhoneNumberBottomsheet: true, notificationId },
}); });

View File

@@ -68,7 +68,14 @@ export const sendPushNotification = async (notification: any) => {
const notificationContent = getNotificationContent(notification); const notificationContent = getNotificationContent(notification);
if (!notificationContent) return; if (!notificationContent) return;
const { title, body, actions, data } = notificationContent; const { title, body, actions = [], data } = notificationContent;
const defaultPressAction = actions[0]
? actions[0].pressAction
: {
id: NotificationAction.DEFAULT,
mainComponent: 'app',
};
// Display a notification // Display a notification
await notifee.displayNotification({ await notifee.displayNotification({
@@ -82,7 +89,7 @@ export const sendPushNotification = async (notification: any) => {
showTimestamp: true, showTimestamp: true,
actions, actions,
style: { type: AndroidStyle.BIGTEXT, text: body }, style: { type: AndroidStyle.BIGTEXT, text: body },
pressAction: actions[0].pressAction, pressAction: defaultPressAction,
groupSummary: true, groupSummary: true,
importance: AndroidImportance.HIGH, importance: AndroidImportance.HIGH,
sound: 'default', sound: 'default',
@@ -113,12 +120,16 @@ const useFCM = () => {
const handleNotificationMessage = async (remoteMessage: FirebaseMessagingTypes.RemoteMessage) => { const handleNotificationMessage = async (remoteMessage: FirebaseMessagingTypes.RemoteMessage) => {
const { data } = remoteMessage || {}; const { data } = remoteMessage || {};
if (data?.payload) { if (data?.payload) {
const notification: INotification = JSON.parse(data.payload); try {
if (notification?.showAsPn) { const notification: INotification = JSON.parse(data.payload);
handlePushNotification(notification); if (notification?.showAsPn) {
handlePushNotification(notification);
}
dispatch(notificationDelivered({ ids: [notification.id] }));
dispatch(prependNewNotifications({ notification }));
} catch (err) {
logError(err as Error, 'unable to parse notification payload');
} }
dispatch(notificationDelivered({ ids: [notification.id] }));
dispatch(prependNewNotifications({ notification }));
} }
}; };

View File

@@ -35,6 +35,7 @@ import { VisitPlanStatus } from '../../reducer/userSlice';
import { PaymentStatus } from '../caseDetails/interface'; import { PaymentStatus } from '../caseDetails/interface';
import relativeDistanceFormatter from '@screens/addressGeolocation/utils/relativeDistanceFormatter'; import relativeDistanceFormatter from '@screens/addressGeolocation/utils/relativeDistanceFormatter';
import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack'; import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack';
import { PageRouteEnum } from '@screens/auth/ProtectedRouter';
interface IListItem { interface IListItem {
caseListItemDetailObj: ICaseItemCaseDetailObj; caseListItemDetailObj: ICaseItemCaseDetailObj;
@@ -138,7 +139,7 @@ const ListItem: React.FC<IListItem> = (props) => {
}); });
} }
if (isCollectionCaseType) { if (isCollectionCaseType) {
navigateToScreen(CaseDetailStackEnum.COLLECTION_CASE_DETAIL, { navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
screen: CaseDetailStackEnum.COLLECTION_CASE_DETAIL, screen: CaseDetailStackEnum.COLLECTION_CASE_DETAIL,
params: { caseId }, params: { caseId },
}); });

View File

@@ -92,13 +92,16 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
useEffect(() => { useEffect(() => {
// If landed via notification action // If landed via notification action
if (notificationId) { if (notificationId) {
if (showPhoneNumberBottomsheet) {
setShowPhoneNumberSheet(true);
}
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_PUSH_NOTIFICATION_SCREEN_LOADED, { addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_PUSH_NOTIFICATION_SCREEN_LOADED, {
notificationId, notificationId,
caseId, caseId,
screenName: CaseDetailStackEnum.COLLECTION_CASE_DETAIL, screenName: CaseDetailStackEnum.COLLECTION_CASE_DETAIL,
}); });
} }
}, []); }, [notificationId]);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const isFocused = useIsFocused(); const isFocused = useIsFocused();
@@ -380,7 +383,10 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_VIEW_EMI_SCHEDULE_CLICKED, { addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_VIEW_EMI_SCHEDULE_CLICKED, {
lan: loanAccountNumber, lan: loanAccountNumber,
}); });
navigateToScreen(CaseDetailStackEnum.EMI_SCHEDULE, { loanAccountNumber, caseId }); navigateToScreen(CaseDetailStackEnum.EMI_SCHEDULE, {
loanAccountNumber,
caseId,
});
}} }}
> >
<View style={GenericStyles.fill}> <View style={GenericStyles.fill}>

View File

@@ -66,13 +66,18 @@ const EmiSchedule: React.FC<IEmiSchedule> = (props) => {
useEffect(() => { useEffect(() => {
// If the user came to the screen via notification. // If the user came to the screen via notification.
if (notificationId) { if (notificationId) {
if (tabId !== currentTab) {
setCurrentTab(tabId || currentTab);
}
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_PUSH_NOTIFICATION_SCREEN_LOADED, { addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_PUSH_NOTIFICATION_SCREEN_LOADED, {
notificationId, notificationId,
caseId, caseId,
tabId: tabId || currentTab,
scheduleTabId,
screenName: CaseDetailStackEnum.EMI_SCHEDULE, screenName: CaseDetailStackEnum.EMI_SCHEDULE,
}); });
} }
}, []); }, [notificationId]);
const { refreshing, onRefresh } = useRefresh(() => { const { refreshing, onRefresh } = useRefresh(() => {
isOnline isOnline
@@ -100,10 +105,9 @@ const EmiSchedule: React.FC<IEmiSchedule> = (props) => {
onRefresh(); onRefresh();
} }
}, [isOnline]); }, [isOnline]);
useEffect(() => { useEffect(() => {
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_TOTAL_OUTSTANDING_BREAKUP_LOADED); addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_TOTAL_OUTSTANDING_BREAKUP_LOADED);
},[]); }, []);
if (!isOnline && !emiData) { if (!isOnline && !emiData) {
return ( return (

View File

@@ -3,11 +3,7 @@ import React from 'react';
import Text from '../../../RN-UI-LIB/src/components/Text'; import Text from '../../../RN-UI-LIB/src/components/Text';
import { GenericStyles } from '../../../RN-UI-LIB/src/styles'; import { GenericStyles } from '../../../RN-UI-LIB/src/styles';
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
import { import { NotificationIconsMap, NotificationTypes, WidgetStatus } from './constants';
NotificationIconsMap,
NotificationTypes,
WidgetStatus,
} from './constants';
import Heading from '../../../RN-UI-LIB/src/components/Heading'; import Heading from '../../../RN-UI-LIB/src/components/Heading';
import { getTimeDifference } from '../../../RN-UI-LIB/src/utlis/common'; import { getTimeDifference } from '../../../RN-UI-LIB/src/utlis/common';
import { useAppDispatch, useAppSelector } from '../../hooks'; import { useAppDispatch, useAppSelector } from '../../hooks';
@@ -26,6 +22,7 @@ import {
handleNotificationNavigation, handleNotificationNavigation,
} from '@hooks/useFCM/notificationHelperFunctions'; } from '@hooks/useFCM/notificationHelperFunctions';
import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack'; import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack';
import { PageRouteEnum } from '@screens/auth/ProtectedRouter';
export interface INotification { export interface INotification {
id: string; id: string;
@@ -142,7 +139,7 @@ const NotificationItem: React.FC<INotificationProps> = ({ data }) => {
handleNotificationNavigation(notificationAction, collectionCaseId); handleNotificationNavigation(notificationAction, collectionCaseId);
return; return;
} }
navigateToScreen(CaseDetailStackEnum.COLLECTION_CASE_DETAIL, { navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
screen: CaseDetailStackEnum.COLLECTION_CASE_DETAIL, screen: CaseDetailStackEnum.COLLECTION_CASE_DETAIL,
params: { caseId: collectionCaseId }, params: { caseId: collectionCaseId },
}); });

View File

@@ -18,6 +18,7 @@ import {
import { APP_NAME, DISABLE_API_EVENTS_URL } from '../common/Constants'; import { APP_NAME, DISABLE_API_EVENTS_URL } from '../common/Constants';
import { JANUS_SERVICE_URL } from '../constants/config'; import { JANUS_SERVICE_URL } from '../constants/config';
import { getBatteryLevel } from 'react-native-device-info'; import { getBatteryLevel } from 'react-native-device-info';
import { getItem } from '@components/utlis/storageHelper';
const MAX_BUFFER_SIZE_FOR_API = 10; const MAX_BUFFER_SIZE_FOR_API = 10;
const MAX_BUFFER_SIZE_FOR_DB_WRITE = 20; const MAX_BUFFER_SIZE_FOR_DB_WRITE = 20;
@@ -74,15 +75,15 @@ export const addClickstreamEvent = async (
const eventDetails = { const eventDetails = {
event_name: name, event_name: name,
description, description,
deviceId, deviceId: deviceId || (await getItem('deviceId')),
agentId, agentId: agentId || (await getItem('agentId')),
attributes: eventAttributes, attributes: eventAttributes,
timestamp: new Date().getTime(), timestamp: new Date().getTime(),
...defaultAttributes, ...defaultAttributes,
}; };
if (fireInstantly) { if (fireInstantly) {
const payload = getPayload([eventDetails]); const payload = await getPayload([eventDetails]);
axiosInstance.post(JANUS_SERVICE_URL, payload, { headers: { donotHandleError: true } }); axiosInstance.post(JANUS_SERVICE_URL, payload, { headers: { donotHandleError: true } });
return; return;
} }
@@ -91,19 +92,19 @@ export const addClickstreamEvent = async (
addEvent(networkStatus); addEvent(networkStatus);
}; };
const getPayload = (events: IClickstreamEvent[]) => { const getPayload = async (events: IClickstreamEvent[]) => {
const { agentId, deviceId } = events[events.length - 1]; const { agentId, deviceId } = events[events.length - 1];
return { return {
app: { name: APP_NAME }, app: { name: APP_NAME },
events, events,
metadata: { metadata: {
agentId, agentId: agentId || (await getItem('agentId')),
deviceId, deviceId: deviceId || (await getItem('deviceId')),
}, },
client_ts: new Date().getTime(), client_ts: new Date().getTime(),
source: APP_NAME, source: APP_NAME,
user: { user: {
customer_id: agentId, customer_id: agentId || (await getItem('agentId')),
}, },
}; };
}; };
@@ -141,7 +142,7 @@ const fireClickstreamEvents = async () => {
}; };
}) })
.concat(bufferEventsList); .concat(bufferEventsList);
const payload = getPayload(events); const payload = await getPayload(events);
axiosInstance axiosInstance
.post(url, payload, { headers: { donotHandleError: true } }) .post(url, payload, { headers: { donotHandleError: true } })