@elemental-design/expo-notifications
Version:
73 lines (60 loc) • 2.72 kB
text/typescript
import { EventEmitter, Subscription, CodedError } from '@unimodules/core';
import { Notification, NotificationBehavior } from './Notifications.types';
import NotificationsHandlerModule from './NotificationsHandlerModule';
export class NotificationTimeoutError extends CodedError {
info: { notification: Notification; id: string };
constructor(notificationId: string, notification: Notification) {
super('ERR_NOTIFICATION_TIMEOUT', `Notification handling timed out for ID ${notificationId}.`);
this.info = { id: notificationId, notification };
}
}
export type NotificationHandlingError = NotificationTimeoutError | Error;
export interface NotificationHandler {
handleNotification: (notification: Notification) => Promise<NotificationBehavior>;
handleSuccess?: (notificationId: string) => void;
handleError?: (notificationId: string, error: NotificationHandlingError) => void;
}
type HandleNotificationEvent = {
id: string;
notification: Notification;
};
type HandleNotificationTimeoutEvent = HandleNotificationEvent;
// Web uses SyntheticEventEmitter
const notificationEmitter = new EventEmitter(NotificationsHandlerModule);
const handleNotificationEventName = 'onHandleNotification';
const handleNotificationTimeoutEventName = 'onHandleNotificationTimeout';
let handleSubscription: Subscription | null = null;
let handleTimeoutSubscription: Subscription | null = null;
export function setNotificationHandler(handler: NotificationHandler | null): void {
if (handleSubscription) {
handleSubscription.remove();
handleSubscription = null;
}
if (handleTimeoutSubscription) {
handleTimeoutSubscription.remove();
handleTimeoutSubscription = null;
}
if (handler) {
handleSubscription = notificationEmitter.addListener<HandleNotificationEvent>(
handleNotificationEventName,
async ({ id, notification }) => {
try {
const behavior = await handler.handleNotification(notification);
await NotificationsHandlerModule.handleNotificationAsync(id, behavior);
// TODO: Remove eslint-disable once we upgrade to a version that supports ?. notation.
// eslint-disable-next-line
handler.handleSuccess?.(id);
} catch (error) {
// TODO: Remove eslint-disable once we upgrade to a version that supports ?. notation.
// eslint-disable-next-line
handler.handleError?.(id, error);
}
}
);
handleTimeoutSubscription = notificationEmitter.addListener<HandleNotificationTimeoutEvent>(
handleNotificationTimeoutEventName,
({ id, notification }) =>
handler.handleError?.(id, new NotificationTimeoutError(id, notification))
);
}
}