UNPKG

@talkjs/expo

Version:

Official TalkJS SDK for React Native (Expo)

256 lines (254 loc) 9.61 kB
"use strict"; import Notifee, { EventType } from '@notifee/react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { AndroidImportance, AndroidVisibility } from './Notification'; import { TokenHandler } from './Notification'; import { ExpoNotificationsContext, FirebaseMessagingContext } from './Imports'; var AndroidStyle = /*#__PURE__*/function (AndroidStyle) { AndroidStyle[AndroidStyle["BIGPICTURE"] = 0] = "BIGPICTURE"; AndroidStyle[AndroidStyle["BIGTEXT"] = 1] = "BIGTEXT"; AndroidStyle[AndroidStyle["INBOX"] = 2] = "INBOX"; AndroidStyle[AndroidStyle["MESSAGING"] = 3] = "MESSAGING"; return AndroidStyle; }(AndroidStyle || {}); export class AndroidNotificationHandler extends TokenHandler { #channelIdStorageKey = 'TalkJS_channel_id'; #activeNotifications = {}; #wasStopped = true; constructor() { super('fcm'); } #onBackgroundMessage = async data => { const channelId = await AsyncStorage.getItem(this.#channelIdStorageKey); if (!channelId) { return; } if (typeof data?.talkjs === 'string') { let notification; const androidSettings = { channelId, importance: AndroidImportance.HIGH, sound: 'default', showTimestamp: true, pressAction: { id: 'default' } }; const talkjsData = JSON.parse(data.talkjs); if (talkjsData.sender.photoUrl) { androidSettings['largeIcon'] = talkjsData.sender.photoUrl; } const notificationId = talkjsData.conversation.id; const commonData = { id: notificationId, data: { talkjs: data.talkjs }, android: { timestamp: talkjsData.timestamp, ...androidSettings } }; let sender = { id: talkjsData.sender.id, name: talkjsData.sender.name }; if (talkjsData.sender.photoUrl) { sender['icon'] = talkjsData.sender.photoUrl; } let activeNotifications = this.#activeNotifications[notificationId]; if (!activeNotifications) { const attachment = talkjsData.message.attachment; if (attachment) { commonData.android.style = { type: AndroidStyle.BIGPICTURE, picture: attachment.url }; } else { const participants = talkjsData.conversation.participants; commonData.android.style = { type: AndroidStyle.MESSAGING, person: { name: 'me' }, group: Object.keys(participants).length > 2, messages: [{ person: sender, text: talkjsData.message.text, timestamp: talkjsData.timestamp }] }; } notification = { title: data.title, body: data.message, ...commonData }; this.#activeNotifications[notificationId] = [{ sender: talkjsData.sender, message: talkjsData.message }]; } else { const messages = []; for (let { sender, message } of activeNotifications) { let person = { id: sender.id, name: sender.name }; if (sender.photoUrl) { person['icon'] = sender.photoUrl; } messages.push({ person, text: message.text, timestamp: message.createdAt }); } messages.push({ person: sender, text: talkjsData.message.text, timestamp: talkjsData.timestamp }); const participants = talkjsData.conversation.participants; commonData.android.style = { type: AndroidStyle.MESSAGING, person: { name: 'me' }, group: Object.keys(participants).length > 2, messages }; notification = { ...commonData }; activeNotifications.push({ sender: talkjsData.sender, message: talkjsData.message }); } Notifee.displayNotification(notification); } }; removeActiveNotification = talkjsString => { if (talkjsString) { const talkjsData = JSON.parse(talkjsString); delete this.#activeNotifications[talkjsData.conversation.id]; } }; #setupExpoHandlers = async () => { try { const ExpoNotifications = ExpoNotificationsContext('./index.js'); if (ExpoNotifications) { if (!this.pushTokenListenerSubscription) { this.pushTokenListenerSubscription = ExpoNotifications.addPushTokenListener(token => this.setPushRegistrationId(token.data)); } const token = await ExpoNotifications.getDevicePushTokenAsync(); this.setPushRegistrationId(token.data); // Setup background task to handle background notifications const expoTaskManagerContext = require.context('../../../../expo-task-manager/build', false, /\.js$/); const ExpoTaskManager = expoTaskManagerContext('./TaskManager.js'); if (ExpoTaskManager) { const BACKGROUND_TASK = 'BACKGROUND-NOTIFICATION-TASK'; ExpoTaskManager.defineTask(BACKGROUND_TASK, ({ data }) => this.#onBackgroundMessage(data.notification?.data)); ExpoNotifications.registerTaskAsync(BACKGROUND_TASK); } else { console.error('Module: expo-task-manager could not be imported. Background notification Listener could not be setup'); } } else { console.error('Module: expo-notifications could not be imported'); } } catch (e) { console.error('Could not setup Expo Notifications. Ensure expo-notifications and expo-task-manager are properly installed', e); } }; #setupFirebaseHandlers = async () => { const errorMessage = 'Could not setup Firebase Messaging. Ensure @react-native-firebase/messaging is properly installed: '; try { const FirebaseMessaging = FirebaseMessagingContext('./index.js'); if (FirebaseMessaging) { const messaging = FirebaseMessaging.getMessaging(); FirebaseMessaging.onTokenRefresh(messaging, token => this.setPushRegistrationId(token)); FirebaseMessaging.setBackgroundMessageHandler(messaging, message => this.#onBackgroundMessage(message.data)); this.setPushRegistrationId(await FirebaseMessaging.getToken(messaging)); } else { console.error(errorMessage); } } catch (e) { console.error(errorMessage, e); } }; async setup(androidSettings, _) { Notifee.onBackgroundEvent(async event => { const talkjsString = event.detail.notification?.data?.talkjs; if (event.type === EventType.PRESS) { this.removeActiveNotification(talkjsString); this.notificationPressed(event, false); } else if (event.type === EventType.DISMISSED) { this.removeActiveNotification(talkjsString); } }); Notifee.onForegroundEvent(async event => { const talkjsString = event.detail.notification?.data?.talkjs; if (event.type === EventType.PRESS) { this.removeActiveNotification(talkjsString); this.notificationPressed(event, true); } else if (event.type === EventType.DISMISSED) { this.removeActiveNotification(talkjsString); } }); if (FirebaseMessagingContext.keys().length === 1) { await this.#setupFirebaseHandlers(); } else if (ExpoNotificationsContext.keys().length === 1) { await this.#setupExpoHandlers(); } else { console.error('Neither expo-notifications nor @react-native-firebase/messaging are installed. Push notifications will not work.'); } const channelId = await AsyncStorage.getItem(this.#channelIdStorageKey); if (androidSettings && androidSettings.channelId !== channelId) { await Notifee.createChannel({ id: androidSettings.channelId, name: androidSettings.channelName, badge: androidSettings.badge ?? true, description: androidSettings.channelDescription ?? '', lights: androidSettings.lights ?? true, lightColor: androidSettings.lightColor ?? 'white', bypassDnd: androidSettings.bypassDnd ?? false, sound: androidSettings.playSound ?? 'default', importance: androidSettings.importance ?? AndroidImportance.HIGH, visibility: androidSettings.visibility ?? AndroidVisibility.PRIVATE, vibration: androidSettings.vibrate ?? true, vibrationPattern: androidSettings.vibrationPattern }); await AsyncStorage.setItem(this.#channelIdStorageKey, androidSettings.channelId); } if (this.#wasStopped) { const notifications = await Notifee.getDisplayedNotifications(); for (let displayedNotification of notifications) { const notification = displayedNotification.notification; if (JSON.stringify(notification.data) !== '{}') { let activeNotifications = this.#activeNotifications[notification.id]; if (!activeNotifications) { activeNotifications = []; this.#activeNotifications[notification.id] = activeNotifications; } const data = notification.data; if (data.talkjs) { const talkjs = JSON.parse(data.talkjs); activeNotifications.push({ sender: talkjs.sender, message: talkjs.message }); } } } this.#wasStopped = false; } return this; } } //# sourceMappingURL=AndroidNotification.js.map