Skip to content

Commit

Permalink
DMAPP-115: Integrate foreground notification for channels (#147)
Browse files Browse the repository at this point in the history
* DMAPP-115: Add Foreground Notification for Channel Module

- Added app logo as notification icon on Android
- Display foreground notification for Channel module
- Begin handling notification events (WIP)

* DMAPP-115: Implement channel notification handling (with static data)

- Update inbox and spam feed data when a notification is received while the app is in the foreground and the home screen is open.
- Navigate to the appropriate tab and auto-select it when a notification banner is pressed.

* DMAPP-115: Notification handling WIP

- Added a function to root navigation to get current route params
- Updated getRecentMessageNotifications function to get already received notification data in mobile app

* DMAPP-115: Channel notification handling WIP

* feat(DMAPP-115): integrate Channel Foreground notification for iOS and Android

- Display notification banner when the app is in the foreground state.
- Handle data updates when the home screen is open in the foreground.
- Implement notification banner press handling to navigate or update views as needed.
- Fix iOS notification sound issue to ensure proper audio playback for notifications.

* DMAPP-115: Review Changes

- Added a utility function for displaying notifications using Notifee to streamline notification handling.
- Removed the `channelInboxNotificationAcknowledgement` object state from `homeSlice` to simplify state management
  • Loading branch information
meKushdeepSingh authored Dec 11, 2024
1 parent c973bf8 commit 67a6250
Show file tree
Hide file tree
Showing 25 changed files with 354 additions and 284 deletions.
5 changes: 5 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,10 @@
<data android:scheme="app.push.org"/>
</intent-filter>
</activity>

<!-- Notification icon -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_notification" />
</application>
</manifest>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 26 additions & 33 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import notifee, {EventType} from '@notifee/react-native';
import messaging from '@react-native-firebase/messaging';
import React, {useEffect} from 'react';
import {AppRegistry, Platform} from 'react-native';
import {AppState} from 'react-native';
import {Alert, AppRegistry, AppState, Platform} from 'react-native';
import RNCallKeep from 'react-native-callkeep';
import 'react-native-crypto';
import 'react-native-get-random-values';
Expand All @@ -12,6 +10,7 @@ import {NotifeClearBadge} from 'src/notifee';
import {getUUID} from 'src/push_video/payloads/helpers';
import MetaStorage from 'src/singletons/MetaStorage';
import 'text-encoding';
import {stringify} from 'uuid';

import App from './App';
import {name as appName} from './app.json';
Expand Down Expand Up @@ -53,43 +52,37 @@ function HeadlessCheck({isHeadless}) {
// RNCallKeep.setAvailable(true);
// }

/************************************************/
/** Listeners used to display notifee **/
/** and native notification **/
/************************************************/
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
if (Platform.OS === 'android' && CallKeepHelper.isVideoCall(remoteMessage)) {
const caller = CallKeepHelper.getCaller(remoteMessage);
const addressTrimmed = CallKeepHelper.formatEthAddress(caller);
const uuid = getUUID();
RNCallKeep.displayIncomingCall(
uuid,
addressTrimmed,
addressTrimmed,
'generic',
true,
);
} else {
await NotificationHelper.resolveNotification(remoteMessage);
}
// console.log('Message handled in the background!', remoteMessage);
/***************************************************/
/** Uncomment below commented code if video call **/
/** feature is enabled in the app **/
/***************************************************/
// if (Platform.OS === 'android' && CallKeepHelper.isVideoCall(remoteMessage)) {
// const caller = CallKeepHelper.getCaller(remoteMessage);
// const addressTrimmed = CallKeepHelper.formatEthAddress(caller);
// const uuid = getUUID();
// RNCallKeep.displayIncomingCall(
// uuid,
// addressTrimmed,
// addressTrimmed,
// 'generic',
// true,
// );
// }
});

messaging().onMessage(async remoteMessage => {
console.log('Message handled in the foreground!', remoteMessage);
await NotificationHelper.resolveNotification(remoteMessage);
});

notifee.onForegroundEvent(async ({type, detail}) => {
if (type === EventType.PRESS) {
await NotificationHelper.openDeeplink(detail.notification?.data?.type);
}
});

notifee.onBackgroundEvent(async ({type, detail}) => {
if (type === EventType.PRESS) {
await NotificationHelper.openDeeplink(detail.notification?.data?.type);
// console.log('Message handled in the foreground!', remoteMessage);
if (remoteMessage.notification) {
await NotificationHelper.resolveNotification(remoteMessage);
}
});

NotificationHelper.handleChatNotification();

if (isCallAccepted) {
AppRegistry.registerComponent(appName, () => HeadlessCheck);
} else {
Expand Down
3 changes: 3 additions & 0 deletions src/Globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ export default {
BG_PUSHNOTIFY: '#FCF2E3',
BG_ALLSET: '#F8ECFF',
BG_OBSLIDER: '#F8ECFF',

// Notification
IC_NOTIFICATION: '#e20880',
},
SCREENS: {
WELCOME: 'Welcome',
Expand Down
3 changes: 0 additions & 3 deletions src/components/ui/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {StyleSheet, Text, View} from 'react-native';
import {connect} from 'react-redux';
import GLOBALS from 'src/Globals';
import {switchUser} from 'src/redux/authSlice';
import {clearFeed, fetchFeedData} from 'src/redux/feedSlice';

import HeaderBanner from './HeaderBanner';
import UserProfile from './UserProfile';
Expand Down Expand Up @@ -64,6 +63,4 @@ const mapStateToProps = state => ({

export default connect(mapStateToProps, {
switchUser,
fetchFeedData,
clearFeed,
})(Header);
22 changes: 22 additions & 0 deletions src/components/ui/HomeFeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@ import {
View,
} from 'react-native';
import ImageView from 'react-native-image-viewing';
import {useDispatch, useSelector} from 'react-redux';
import {ToasterOptions} from 'src/components/indicators/Toaster';
import EPNSActivity from 'src/components/loaders/EPNSActivity';
import ImagePreviewFooter from 'src/components/ui/ImagePreviewFooter';
import {usePushApi} from 'src/contexts/PushApiContext';
import AppBadgeHelper from 'src/helpers/AppBadgeHelper';
import {
selectNotificationOpened,
selectNotificationReceived,
updateNotificationOpened,
updateNotificationReceived,
} from 'src/redux/homeSlice';

import EmptyFeed from './EmptyFeed';
import NotificationItem from './NotificationItem';
Expand All @@ -34,6 +41,12 @@ export default function InboxFeed(props) {
const [renderGallery, setRenderGallery] = useState(false);
const [startFromIndex, setStartFromIndex] = useState(0);

// GET REDUX STATES AND DISPATCH ACTIONS
const notificationOpened = useSelector(selectNotificationOpened);
const notificationReceived = useSelector(selectNotificationReceived);

const dispatch = useDispatch();

// SET REFS
const FlatListFeedsRef = useRef(null);

Expand All @@ -44,6 +57,14 @@ export default function InboxFeed(props) {
}
}, [initialized, userPushSDKInstance]);

useEffect(() => {
if (notificationReceived || notificationOpened) {
fetchFeed(true, true);
dispatch(updateNotificationOpened(false));
dispatch(updateNotificationReceived(false));
}
}, [notificationOpened, notificationReceived]);

useEffect(() => {
if (Platform.OS === 'android') {
messaging()
Expand All @@ -54,6 +75,7 @@ export default function InboxFeed(props) {
notifee.createChannel({
id: 'default',
name: 'Default Channel',
sound: 'default',
});
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function Tabs() {

return (
<Tab.Navigator
initialRouteName={GLOBALS.SCREENS.FEED}
initialRouteName={GLOBALS.SCREENS.NOTIF_TABS}
screenOptions={{
tabBarStyle: {
position: 'absolute',
Expand Down
Loading

0 comments on commit 67a6250

Please sign in to comment.