Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,27 +1,64 @@
import type RNFBMessaging from '@react-native-firebase/messaging';
import type { FirebaseMessagingTypes } from '@react-native-firebase/messaging';
import { Platform } from 'react-native';
import type * as Permissions from 'react-native-permissions';

import type { NotificationServiceInterface } from './types';

// Type definitions for Firebase Messaging Module instance
// This represents the instance returned by messaging() or getMessaging()
// We use a type alias to handle both v14 and v22+ types
type MessagingInstance = ReturnType<typeof RNFBMessaging>;

// Type definitions for modular API support (Firebase v22+)
// The modular API provides standalone functions that accept a messaging instance
type ModularMessagingType = {
getMessaging: () => MessagingInstance;
getAPNSToken: (messaging: MessagingInstance) => Promise<string | null>;
getToken: (messaging: MessagingInstance) => Promise<string>;
hasPermission: (messaging: MessagingInstance) => Promise<FirebaseMessagingTypes.AuthorizationStatus>;
requestPermission: (
messaging: MessagingInstance,
iosPermissions?: FirebaseMessagingTypes.IOSPermissions,
) => Promise<FirebaseMessagingTypes.AuthorizationStatus>;
onTokenRefresh: (messaging: MessagingInstance, listener: (token: string) => void) => () => void;
AuthorizationStatus: typeof RNFBMessaging.AuthorizationStatus;
};

// Create a flexible type that can handle both v14 and v22+ Firebase modules
type FirebaseMessagingModule = typeof RNFBMessaging | ModularMessagingType;

const isModularAPI = (module: FirebaseMessagingModule): module is ModularMessagingType => {
return typeof (module as ModularMessagingType).getMessaging === 'function';
};

const createNativeNotificationService = ({
messagingModule,
permissionModule,
}: {
messagingModule: typeof RNFBMessaging;
messagingModule: FirebaseMessagingModule;
permissionModule: typeof Permissions;
}): NotificationServiceInterface => {
const module = messagingModule();
const isModular = isModularAPI(messagingModule);
const modularMessaging = isModular ? (messagingModule as ModularMessagingType) : null;
const messaging = isModular ? modularMessaging!.getMessaging() : (messagingModule as typeof RNFBMessaging)();

const authorizedStatus = [
messagingModule.AuthorizationStatus.AUTHORIZED,
messagingModule.AuthorizationStatus.PROVISIONAL,
];
return {
getAPNSToken(): Promise<string | null> {
return module.getAPNSToken();
if (modularMessaging) {
return modularMessaging.getAPNSToken(messaging);
}
return messaging.getAPNSToken();
},
getFCMToken(): Promise<string | null> {
return module.getToken();
if (modularMessaging) {
return modularMessaging.getToken(messaging);
}
return messaging.getToken();
},
async hasPushPermission(): Promise<boolean> {
if (Platform.OS === 'android') {
Expand All @@ -30,7 +67,9 @@ const createNativeNotificationService = ({
}

if (Platform.OS === 'ios') {
const status = await module.hasPermission();
const status = modularMessaging
? await modularMessaging.hasPermission(messaging)
: await messaging.hasPermission();
return authorizedStatus.includes(status);
}

Expand All @@ -43,14 +82,21 @@ const createNativeNotificationService = ({
}

if (Platform.OS === 'ios') {
const status = await module.requestPermission();
const status = modularMessaging
? await modularMessaging.requestPermission(messaging)
: await messaging.requestPermission();
return authorizedStatus.includes(status);
}

return false;
},
onTokenRefresh(handler: (token: string) => void): () => void | undefined {
return module.onTokenRefresh((token) => {
if (modularMessaging) {
return modularMessaging.onTokenRefresh(messaging, (token: string) => {
if (Platform.OS === 'android') handler(token);
});
}
return messaging.onTokenRefresh((token: string) => {
if (Platform.OS === 'android') handler(token);
});
},
Expand Down