diff --git a/packages/messaging/plugin/__tests__/androidPlugin.test.ts b/packages/messaging/plugin/__tests__/androidPlugin.test.ts index f2c333212b..194016b8fe 100644 --- a/packages/messaging/plugin/__tests__/androidPlugin.test.ts +++ b/packages/messaging/plugin/__tests__/androidPlugin.test.ts @@ -1,7 +1,10 @@ import { describe, expect, it } from '@jest/globals'; import { setFireBaseMessagingAndroidManifest } from '../src/android/setupFirebaseNotifationIcon'; import { ExpoConfig } from '@expo/config-types'; -import expoConfigExample from './fixtures/expo-config-example'; +import { + expoConfigExample, + expoConfigExampleWithExpoNotificationsPlugins, +} from './fixtures/expo-config-example'; import manifestApplicationExample from './fixtures/application-example'; import { ManifestApplication } from '@expo/config-plugins/build/android/Manifest'; @@ -67,4 +70,51 @@ describe('Config Plugin Android Tests', function () { // eslint-disable-next-line no-console console.warn = warnOrig; }); + + it('applies changes to app/src/main/AndroidManifest.xml with expo-notifications plugin config when app.json notification is undefined', async function () { + const config: ExpoConfig = JSON.parse( + JSON.stringify(expoConfigExampleWithExpoNotificationsPlugins), + ); + const manifestApplication: ManifestApplication = JSON.parse( + JSON.stringify(manifestApplicationExample), + ); + config.notification = undefined; + setFireBaseMessagingAndroidManifest(config, manifestApplication); + expect(manifestApplication['meta-data']).toContainEqual({ + $: { + 'android:name': 'com.google.firebase.messaging.default_notification_icon', + 'android:resource': '@drawable/notification_icon', + }, + }); + expect(manifestApplication['meta-data']).toContainEqual({ + $: { + 'android:name': 'com.google.firebase.messaging.default_notification_color', + 'android:resource': '@color/notification_icon_color', + 'tools:replace': 'android:resource', + }, + }); + }); + + it('applies changes to app/src/main/AndroidManifest.xml with app.json notification config when both configs are defined', async function () { + const config: ExpoConfig = JSON.parse( + JSON.stringify(expoConfigExampleWithExpoNotificationsPlugins), + ); + const manifestApplication: ManifestApplication = JSON.parse( + JSON.stringify(manifestApplicationExample), + ); + setFireBaseMessagingAndroidManifest(config, manifestApplication); + expect(manifestApplication['meta-data']).toContainEqual({ + $: { + 'android:name': 'com.google.firebase.messaging.default_notification_icon', + 'android:resource': '@drawable/notification_icon', + }, + }); + expect(manifestApplication['meta-data']).toContainEqual({ + $: { + 'android:name': 'com.google.firebase.messaging.default_notification_color', + 'android:resource': '@color/notification_icon_color', + 'tools:replace': 'android:resource', + }, + }); + }); }); diff --git a/packages/messaging/plugin/__tests__/fixtures/expo-config-example.ts b/packages/messaging/plugin/__tests__/fixtures/expo-config-example.ts index c9aa9e1e27..c214371558 100644 --- a/packages/messaging/plugin/__tests__/fixtures/expo-config-example.ts +++ b/packages/messaging/plugin/__tests__/fixtures/expo-config-example.ts @@ -1,15 +1,29 @@ import { ExpoConfig } from '@expo/config-types'; +const notificationConfig = { + icon: 'IconAsset', + color: '#1D172D', +}; + /** * @type {import('@expo/config-types').ExpoConfig} */ -const expoConfigExample: ExpoConfig = { +export const expoConfigExample: ExpoConfig = { name: 'FirebaseMessagingTest', slug: 'fire-base-messaging-test', - notification: { - icon: 'IconAsset', - color: '#1D172D', - }, + notification: notificationConfig, }; -export default expoConfigExample; +/** + * @type {import('@expo/config-types').ExpoConfig} + */ +export const expoConfigExampleWithExpoNotificationsPlugins: ExpoConfig = { + name: 'FirebaseMessagingTest', + slug: 'fire-base-messaging-test', + notification: notificationConfig, + plugins: [ + ['expo-notifications', notificationConfig], + '../test-plugin', + ['expo-camera'], + ], +}; diff --git a/packages/messaging/plugin/src/android/setupFirebaseNotifationIcon.ts b/packages/messaging/plugin/src/android/setupFirebaseNotifationIcon.ts index 7a226e7a53..2ccac4ebbd 100644 --- a/packages/messaging/plugin/src/android/setupFirebaseNotifationIcon.ts +++ b/packages/messaging/plugin/src/android/setupFirebaseNotifationIcon.ts @@ -26,12 +26,38 @@ export const withExpoPluginFirebaseNotification: ConfigPlugin = config => { }); }; +interface NotificationConfig { + icon: string | null; + color: string | null; +} + export function setFireBaseMessagingAndroidManifest( config: ExpoConfig, application: ManifestApplication, ) { + const notificationConfig: NotificationConfig = { + icon: null, + color: null, + }; + + const notificationConfigFromPlugin = config.plugins?.find( + plugin => Array.isArray(plugin) && plugin[0] === 'expo-notifications', + )?.[1]; + + // check if the notification config is defined in the expo-notifications plugin first + if (notificationConfigFromPlugin?.icon || notificationConfigFromPlugin?.color) { + notificationConfig.icon = notificationConfigFromPlugin?.icon || null; + notificationConfig.color = notificationConfigFromPlugin?.color || null; + } + + // then check if the notification config is defined in the app.json notification object and override the plugin config if it is defined + if (config.notification) { + notificationConfig.icon = config.notification.icon || notificationConfig?.icon || null; + notificationConfig.color = config.notification.color || notificationConfig?.color || null; + } + // If the notification object is not defined, print a friendly warning - if (!config.notification) { + if (!notificationConfig.icon && !notificationConfig.color) { // This warning is important because the notification icon can only use pure white on Android. By default, the system uses the app icon as the notification icon, but the app icon is usually not pure white, so you need to set the notification icon // eslint-disable-next-line no-console console.warn( @@ -46,10 +72,10 @@ export function setFireBaseMessagingAndroidManifest( const metaData = application['meta-data']; if ( - config.notification.icon && + notificationConfig.icon && !hasMetaData(application, 'com.google.firebase.messaging.default_notification_icon') ) { - // Expo will automatically create '@drawable/notification_icon' resource if you specify config.notification.icon. + // Expo will automatically create '@drawable/notification_icon' resource if you specify config.notification.icon or expo-notifications plugin.icon. metaData.push({ $: { 'android:name': 'com.google.firebase.messaging.default_notification_icon', @@ -59,7 +85,7 @@ export function setFireBaseMessagingAndroidManifest( } if ( - config.notification.color && + notificationConfig.color && !hasMetaData(application, 'com.google.firebase.messaging.default_notification_color') ) { metaData.push({