1import { EventEmitter, Subscription, Platform } from 'expo-modules-core';
2
3import PushTokenManager from './PushTokenManager';
4import { DevicePushToken } from './Tokens.types';
5
6/**
7 * A function accepting a device push token ([`DevicePushToken`](#devicepushtoken)) as an argument.
8 * > **Note:** You should not call `getDevicePushTokenAsync` inside this function, as it triggers the listener and may lead to an infinite loop.
9 * @header fetch
10 */
11export type PushTokenListener = (token: DevicePushToken) => void;
12
13// Web uses SyntheticEventEmitter
14const tokenEmitter = new EventEmitter(PushTokenManager);
15const newTokenEventName = 'onDevicePushToken';
16
17/**
18 * In rare situations, a push token may be changed by the push notification service while the app is running.
19 * When a token is rolled, the old one becomes invalid and sending notifications to it will fail.
20 * A push token listener will let you handle this situation gracefully by registering the new token with your backend right away.
21 * @param listener A function accepting a push token as an argument, it will be called whenever the push token changes.
22 * @return A [`Subscription`](#subscription) object represents the subscription of the provided listener.
23 * @header fetch
24 * @example Registering a push token listener using a React hook.
25 * ```jsx
26 * import React from 'react';
27 * import * as Notifications from 'expo-notifications';
28 *
29 * import { registerDevicePushTokenAsync } from '../api';
30 *
31 * export default function App() {
32 *   React.useEffect(() => {
33 *     const subscription = Notifications.addPushTokenListener(registerDevicePushTokenAsync);
34 *     return () => subscription.remove();
35 *   }, []);
36 *
37 *   return (
38 *     // Your app content
39 *   );
40 * }
41 * ```
42 */
43export function addPushTokenListener(listener: PushTokenListener): Subscription {
44  const wrappingListener = ({ devicePushToken }) =>
45    listener({ data: devicePushToken, type: Platform.OS });
46  return tokenEmitter.addListener(newTokenEventName, wrappingListener);
47}
48
49/**
50 * Removes a push token subscription returned by an `addPushTokenListener` call.
51 * @param subscription A subscription returned by `addPushTokenListener` method.
52 * @header fetch
53 */
54export function removePushTokenSubscription(subscription: Subscription) {
55  tokenEmitter.removeSubscription(subscription);
56}
57