UNPKG

@bigin/ns-firebase

Version:
445 lines (444 loc) 17.2 kB
import { SharedNotificationDelegate } from '@nativescript/shared-notification-delegate'; import { Application, ApplicationSettings, Device } from '@nativescript/core'; import { firebase } from '../firebase-common'; import { firebaseUtils } from '../utils'; let _notificationActionTakenCallback; let _pendingNotifications = []; let _pendingActionTakenNotifications = []; let _pushToken; let _receivedPushTokenCallback; let _receivedNotificationCallback; let _registerForRemoteNotificationsRanThisSession = false; let _userNotificationCenterDelegateObserver; let _firebaseRemoteMessageDelegate; let _showNotifications = true; let _showNotificationsWhenInForeground = false; let _autoClearBadge = true; let _resolveWhenDidRegisterForNotifications; let _rejectWhenDidFailToRegisterForNotifications; const NOTIFICATIONS_REGISTRATION_KEY = 'Firebase-RegisterForRemoteNotifications'; export function initFirebaseMessaging(options) { if (!options) { return; } _showNotifications = options.showNotifications === undefined ? _showNotifications : !!options.showNotifications; _showNotificationsWhenInForeground = options.showNotificationsWhenInForeground === undefined ? _showNotificationsWhenInForeground : !!options.showNotificationsWhenInForeground; _autoClearBadge = options.autoClearBadge === undefined ? _autoClearBadge : !!options.autoClearBadge; if (options.onMessageReceivedCallback !== undefined) { addOnMessageReceivedCallback(options.onMessageReceivedCallback); } if (options.onPushTokenReceivedCallback !== undefined) { addOnPushTokenReceivedCallback(options.onPushTokenReceivedCallback); } } export function addOnMessageReceivedCallback(callback) { return new Promise((resolve, reject) => { try { ApplicationSettings.setBoolean(NOTIFICATIONS_REGISTRATION_KEY, true); _receivedNotificationCallback = callback; _registerForRemoteNotifications(resolve, reject); _processPendingNotifications(); resolve(); } catch (ex) { console.log('Error in messaging.addOnMessageReceivedCallback: ' + ex); reject(ex); } }); } export function getCurrentPushToken() { return new Promise((resolve, reject) => { try { if (typeof FIRMessaging !== 'undefined') { resolve(FIRMessaging.messaging().FCMToken); } else { resolve(_pushToken); } } catch (ex) { console.log('Error in messaging.getCurrentPushToken: ' + ex); reject(ex); } }); } export function registerForPushNotifications(options) { return new Promise((resolve, reject) => { try { initFirebaseMessaging(options); _registerForRemoteNotificationsRanThisSession = false; _registerForRemoteNotifications(resolve, reject); } catch (ex) { console.log('Error in messaging.registerForPushNotifications: ' + ex); reject(ex); } }); } export function unregisterForPushNotifications() { return new Promise((resolve, reject) => { try { UIApplication.sharedApplication.unregisterForRemoteNotifications(); resolve(); } catch (ex) { console.log('Error in messaging.unregisterForPushNotifications: ' + ex); reject(ex); } }); } export function handleRemoteNotification(app, userInfo) { const userInfoJSON = firebaseUtils.toJsObject(userInfo); const aps = userInfo.objectForKey('aps'); if (aps !== null) { const alrt = aps.objectForKey('alert'); if (alrt !== null && alrt.objectForKey) { userInfoJSON.title = alrt.objectForKey('title'); userInfoJSON.body = alrt.objectForKey('body'); } } userInfoJSON.foreground = app.applicationState === 0; updateUserInfo(userInfoJSON); _pendingNotifications.push(userInfoJSON); if (_receivedNotificationCallback) { _processPendingNotifications(); } } export function addOnPushTokenReceivedCallback(callback) { return new Promise((resolve, reject) => { try { _receivedPushTokenCallback = callback; if (_pushToken) { callback(_pushToken); } ApplicationSettings.setBoolean(NOTIFICATIONS_REGISTRATION_KEY, true); _registerForRemoteNotifications(); _processPendingNotifications(); resolve(); } catch (ex) { console.log('Error in messaging.addOnPushTokenReceivedCallback: ' + ex); reject(ex); } }); } export function addBackgroundRemoteNotificationHandler(appDelegate) { appDelegate.prototype.applicationDidRegisterForRemoteNotificationsWithDeviceToken = (application, deviceToken) => { if (areNotificationsEnabled()) { _resolveWhenDidRegisterForNotifications && _resolveWhenDidRegisterForNotifications(); } else { _rejectWhenDidFailToRegisterForNotifications && _rejectWhenDidFailToRegisterForNotifications(); } if (typeof FIRMessaging !== 'undefined') { FIRMessaging.messaging().APNSToken = deviceToken; } else { const token = deviceToken.debugDescription.replace(/[< >]/g, ''); _pushToken = token; if (_receivedPushTokenCallback) { _receivedPushTokenCallback(token); } } }; appDelegate.prototype.applicationDidFailToRegisterForRemoteNotificationsWithError = (application, error) => { if (error.localizedDescription.indexOf('not supported in the simulator') > -1) { _resolveWhenDidRegisterForNotifications && _resolveWhenDidRegisterForNotifications(); } else { _rejectWhenDidFailToRegisterForNotifications && _rejectWhenDidFailToRegisterForNotifications(error.localizedDescription); } }; appDelegate.prototype.applicationDidReceiveRemoteNotificationFetchCompletionHandler = (app, notification, completionHandler) => { if (typeof FIRAuth !== 'undefined') { if (firebase._configured && FIRAuth.auth().canHandleNotification(notification)) { completionHandler(1); return; } } completionHandler(0); handleRemoteNotification(app, notification); }; } export function registerForInteractivePush(model) { let nativeActions = []; model.iosSettings.interactiveSettings.actions.forEach((action) => { let notificationActionOptions = action.options ? action.options.valueOf() : UNNotificationActionOptionNone; let actionType = action.type || 'button'; let nativeAction; if (actionType === 'input') { nativeAction = UNTextInputNotificationAction.actionWithIdentifierTitleOptionsTextInputButtonTitleTextInputPlaceholder(action.identifier, action.title, notificationActionOptions, action.submitLabel || 'Submit', action.placeholder); } else if (actionType === 'button') { nativeAction = UNNotificationAction.actionWithIdentifierTitleOptions(action.identifier, action.title, notificationActionOptions); } else { console.log('Unsupported action type: ' + action.type); } nativeActions.push(nativeAction); }); let actions = NSArray.arrayWithArray(nativeActions); let nativeCategories = []; model.iosSettings.interactiveSettings.categories.forEach((category) => { let nativeCategory = UNNotificationCategory.categoryWithIdentifierActionsIntentIdentifiersOptions(category.identifier, actions, null, null); nativeCategories.push(nativeCategory); }); const nsSetCategories = new NSSet(nativeCategories); UNUserNotificationCenter.currentNotificationCenter().setNotificationCategories(nsSetCategories); if (model.onNotificationActionTakenCallback) { _addOnNotificationActionTakenCallback(model.onNotificationActionTakenCallback); } } export function prepAppDelegate() { _addObserver('com.firebase.iid.notif.refresh-token', (notification) => onTokenRefreshNotification(notification.object)); _addObserver(UIApplicationDidFinishLaunchingNotification, (appNotification) => { if (ApplicationSettings.getBoolean(NOTIFICATIONS_REGISTRATION_KEY, false)) { _registerForRemoteNotifications(); } }); _addObserver(UIApplicationDidBecomeActiveNotification, (appNotification) => { _processPendingNotifications(); }); } export function subscribeToTopic(topicName) { return new Promise((resolve, reject) => { try { if (typeof FIRMessaging === 'undefined') { reject('Enable FIRMessaging in Podfile first'); return; } FIRMessaging.messaging().subscribeToTopicCompletion(topicName, (error) => { error ? reject(error.localizedDescription) : resolve(); }); } catch (ex) { console.log('Error in messaging.subscribeToTopic: ' + ex); reject(ex); } }); } export function unsubscribeFromTopic(topicName) { return new Promise((resolve, reject) => { try { if (typeof FIRMessaging === 'undefined') { reject('Enable FIRMessaging in Podfile first'); return; } FIRMessaging.messaging().unsubscribeFromTopicCompletion(topicName, (error) => { error ? reject(error.localizedDescription) : resolve(); }); } catch (ex) { console.log('Error in messaging.unsubscribeFromTopic: ' + ex); reject(ex); } }); } export const onTokenRefreshNotification = (token) => { _pushToken = token; if (_receivedPushTokenCallback) { _receivedPushTokenCallback(token); } }; export class IosInteractivePushSettings {} export var IosInteractiveNotificationActionOptions; (function (IosInteractiveNotificationActionOptions) { IosInteractiveNotificationActionOptions[(IosInteractiveNotificationActionOptions['authenticationRequired'] = 1)] = 'authenticationRequired'; IosInteractiveNotificationActionOptions[(IosInteractiveNotificationActionOptions['destructive'] = 2)] = 'destructive'; IosInteractiveNotificationActionOptions[(IosInteractiveNotificationActionOptions['foreground'] = 4)] = 'foreground'; })(IosInteractiveNotificationActionOptions || (IosInteractiveNotificationActionOptions = {})); export class IosPushSettings {} export class PushNotificationModel {} export class NotificationActionResponse {} export function areNotificationsEnabled() { return UIApplication.sharedApplication.currentUserNotificationSettings.types > 0; } const updateUserInfo = (userInfoJSON) => { if (userInfoJSON.aps && userInfoJSON.aps.alert) { userInfoJSON.title = userInfoJSON.aps.alert.title; userInfoJSON.body = userInfoJSON.aps.alert.body; } if (!userInfoJSON.hasOwnProperty('data')) { userInfoJSON.data = {}; } Object.keys(userInfoJSON).forEach((key) => { if (key !== 'data') userInfoJSON.data[key] = userInfoJSON[key]; }); userInfoJSON.aps = undefined; }; function _registerForRemoteNotifications(resolve, reject) { let app = UIApplication.sharedApplication; if (!app) { Application.on(Application.launchEvent, () => _registerForRemoteNotifications(resolve, reject)); return; } if (_registerForRemoteNotificationsRanThisSession) { resolve && resolve(); return; } _registerForRemoteNotificationsRanThisSession = true; _resolveWhenDidRegisterForNotifications = resolve; _rejectWhenDidFailToRegisterForNotifications = reject; if (parseInt(Device.osVersion) >= 10) { const authorizationOptions = 4 | 2 | 1; UNUserNotificationCenter.currentNotificationCenter().requestAuthorizationWithOptionsCompletionHandler(authorizationOptions, (granted, error) => { if (!error) { if (app === null) { app = UIApplication.sharedApplication; } if (app !== null) { firebaseUtils.invokeOnRunLoop(() => app.registerForRemoteNotifications()); } } else { console.log('Error requesting push notification auth: ' + error); reject && reject(error.localizedDescription); } }); if (_showNotifications) { _userNotificationCenterDelegateObserver = new FirebaseNotificationDelegateObserverImpl((unnotification, actionIdentifier, inputText) => { const userInfo = unnotification.request.content.userInfo; const userInfoJSON = firebaseUtils.toJsObject(userInfo); updateUserInfo(userInfoJSON); if (actionIdentifier) { _pendingActionTakenNotifications.push({ actionIdentifier, userInfoJSON, inputText, }); if (_notificationActionTakenCallback) { _processPendingActionTakenNotifications(); } userInfoJSON.notificationTapped = actionIdentifier === UNNotificationDefaultActionIdentifier; } else { userInfoJSON.notificationTapped = false; } userInfoJSON.foreground = UIApplication.sharedApplication.applicationState === 0; _pendingNotifications.push(userInfoJSON); if (_receivedNotificationCallback) { _processPendingNotifications(); } }); SharedNotificationDelegate.addObserver(_userNotificationCenterDelegateObserver); } if (typeof FIRMessaging !== 'undefined') { _firebaseRemoteMessageDelegate = FIRMessagingDelegateImpl.new().initWithCallback((appDataDictionary) => { const userInfoJSON = firebaseUtils.toJsObject(appDataDictionary); updateUserInfo(userInfoJSON); _pendingNotifications.push(userInfoJSON); const asJs = firebaseUtils.toJsObject(appDataDictionary.objectForKey('notification')); if (asJs) { userInfoJSON.title = asJs.title; userInfoJSON.body = asJs.body; } const app = UIApplication.sharedApplication; if (app.applicationState === 0) { userInfoJSON.foreground = true; if (_receivedNotificationCallback) { _processPendingNotifications(); } } else { userInfoJSON.foreground = false; } }); FIRMessaging.messaging().delegate = _firebaseRemoteMessageDelegate; } } else { const notificationTypes = 4 | 1 | 2 | 1; const notificationSettings = UIUserNotificationSettings.settingsForTypesCategories(notificationTypes, null); firebaseUtils.invokeOnRunLoop(() => { app.registerForRemoteNotifications(); }); app.registerUserNotificationSettings(notificationSettings); } } function _addOnNotificationActionTakenCallback(callback) { return new Promise((resolve, reject) => { try { _notificationActionTakenCallback = callback; _processPendingActionTakenNotifications(); resolve(); } catch (ex) { console.log('Error in messaging._addOnNotificationActionTakenCallback: ' + ex); reject(ex); } }); } function _processPendingNotifications() { const app = UIApplication.sharedApplication; if (!app) { Application.on('launch', () => _processPendingNotifications()); return; } if (_receivedNotificationCallback) { for (let p in _pendingNotifications) { _receivedNotificationCallback(_pendingNotifications[p]); } _pendingNotifications = []; if (app.applicationState === 0 && _autoClearBadge) { app.applicationIconBadgeNumber = 0; } } } function _processPendingActionTakenNotifications() { const app = UIApplication.sharedApplication; if (!app) { Application.on('launch', () => _processPendingNotifications()); return; } if (_notificationActionTakenCallback) { for (let p in _pendingActionTakenNotifications) { _notificationActionTakenCallback(_pendingActionTakenNotifications[p].actionIdentifier, _pendingActionTakenNotifications[p].userInfoJSON, _pendingActionTakenNotifications[p].inputText); } _pendingActionTakenNotifications = []; if (app.applicationState === 0 && _autoClearBadge) { app.applicationIconBadgeNumber = 0; } } } function _addObserver(eventName, callback) { return NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(eventName, null, NSOperationQueue.mainQueue, callback); } class FirebaseNotificationDelegateObserverImpl { constructor(callback) { this.observerUniqueKey = 'firebase-messaging'; this.callback = callback; } userNotificationCenterWillPresentNotificationWithCompletionHandler(center, notification, completionHandler, next) { const userInfo = notification.request.content.userInfo; const userInfoJSON = firebaseUtils.toJsObject(userInfo); if (!(notification.request.trigger instanceof UNPushNotificationTrigger)) { next(); return; } if (_showNotificationsWhenInForeground || userInfoJSON['gcm.notification.showWhenInForeground'] === 'true' || userInfoJSON['showWhenInForeground'] === true || (userInfoJSON.aps && userInfoJSON.aps.showWhenInForeground === true)) { completionHandler(4 | 2 | 1); } else { completionHandler(0); } this.callback(notification); } userNotificationCenterDidReceiveNotificationResponseWithCompletionHandler(center, response, completionHandler, next) { if (!(response.notification.request.trigger instanceof UNPushNotificationTrigger)) { next(); return; } if (response && response.actionIdentifier === UNNotificationDismissActionIdentifier) { completionHandler(); return; } this.callback(response.notification, response.actionIdentifier, response.userText); completionHandler(); } } var FIRMessagingDelegateImpl = /** @class */ (function (_super) { __extends(FIRMessagingDelegateImpl, _super); function FIRMessagingDelegateImpl() { return (_super !== null && _super.apply(this, arguments)) || this; } FIRMessagingDelegateImpl.new = function () { if (FIRMessagingDelegateImpl.ObjCProtocols.length === 0 && typeof FIRMessagingDelegate !== 'undefined') { FIRMessagingDelegateImpl.ObjCProtocols.push(FIRMessagingDelegate); } return _super.new.call(this); }; FIRMessagingDelegateImpl.prototype.initWithCallback = function (callback) { this.callback = callback; return this; }; FIRMessagingDelegateImpl.prototype.messagingDidReceiveMessage = function (messaging, remoteMessage) { this.callback(remoteMessage.appData); }; FIRMessagingDelegateImpl.prototype.messagingDidReceiveRegistrationToken = function (messaging, fcmToken) { onTokenRefreshNotification(fcmToken); }; FIRMessagingDelegateImpl.ObjCProtocols = []; return FIRMessagingDelegateImpl; })(NSObject); //# sourceMappingURL=messaging.ios.js.map