-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(messaging): Adding support for Firebase Messaging via Expo confi…
…g plugin. (#7369) * feat(messaging): Adding support for Firebase Messaging via Expo config plugin. * feat(messaging): Adding expo plugin entry. * perf(messaging): Add NS `xmlns:tools to handle boundary conditions. * chore(messaging): typo. * chore: rebase to main, bump dependencies that moved after posting the PR --------- Co-authored-by: Mike Hardy <[email protected]>
- Loading branch information
Showing
10 changed files
with
216 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('./plugin/build'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { describe, expect, it, jest } from '@jest/globals'; | ||
import { setFireBaseMessagingAndroidManifest } from '../src/android/setupFirebaseNotifationIcon'; | ||
import { ExpoConfig } from '@expo/config-types'; | ||
import expoConfigExample from './fixtures/expo-config-example'; | ||
import manifestApplicationExample from './fixtures/application-example'; | ||
import { ManifestApplication } from '@expo/config-plugins/build/android/Manifest'; | ||
|
||
describe('Config Plugin Android Tests', function () { | ||
it('applies changes to app/src/main/AndroidManifest.xml with color', async function () { | ||
const config: ExpoConfig = JSON.parse(JSON.stringify(expoConfigExample)); | ||
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', | ||
}, | ||
}); | ||
}); | ||
|
||
it('applies changes to app/src/main/AndroidManifest.xml without color', async function () { | ||
const config = JSON.parse(JSON.stringify(expoConfigExample)); | ||
const manifestApplication: ManifestApplication = JSON.parse( | ||
JSON.stringify(manifestApplicationExample), | ||
); | ||
config.notification!.color = 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']).not.toContainEqual({ | ||
$: { | ||
'android:name': 'com.google.firebase.messaging.default_notification_icon', | ||
'android:resource': '@drawable/notification_icon_color', | ||
'tools:replace': 'android:resource', | ||
}, | ||
}); | ||
}); | ||
|
||
it('applies changes to app/src/main/AndroidManifest.xml without notification', async function () { | ||
const warnSpy = jest.spyOn(console, 'warn'); | ||
const config: ExpoConfig = JSON.parse(JSON.stringify(expoConfigExample)); | ||
const manifestApplication: ManifestApplication = JSON.parse( | ||
JSON.stringify(manifestApplicationExample), | ||
); | ||
config.notification = undefined; | ||
setFireBaseMessagingAndroidManifest(config, manifestApplication); | ||
expect(warnSpy).toHaveBeenCalled(); | ||
warnSpy.mockRestore(); | ||
}); | ||
}); |
12 changes: 12 additions & 0 deletions
12
packages/messaging/plugin/__tests__/fixtures/application-example.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { ManifestApplication } from '@expo/config-plugins/build/android/Manifest'; | ||
|
||
/** | ||
* @type {import('"@expo/config-plugins/build/android/Manifest"').ManifestApplication} | ||
*/ | ||
const manifestApplicationExample: ManifestApplication = { | ||
$: { | ||
'android:name': '', | ||
}, | ||
}; | ||
|
||
export default manifestApplicationExample; |
15 changes: 15 additions & 0 deletions
15
packages/messaging/plugin/__tests__/fixtures/expo-config-example.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { ExpoConfig } from '@expo/config-types'; | ||
|
||
/** | ||
* @type {import('@expo/config-types').ExpoConfig} | ||
*/ | ||
const expoConfigExample: ExpoConfig = { | ||
name: 'FirebaseMessagingTest', | ||
slug: 'fire-base-messaging-test', | ||
notification: { | ||
icon: 'IconAsset', | ||
color: '#1D172D', | ||
}, | ||
}; | ||
|
||
export default expoConfigExample; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { withExpoPluginFirebaseNotification } from './setupFirebaseNotifationIcon'; | ||
|
||
export { withExpoPluginFirebaseNotification }; |
77 changes: 77 additions & 0 deletions
77
packages/messaging/plugin/src/android/setupFirebaseNotifationIcon.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { ConfigPlugin, withAndroidManifest } from '@expo/config-plugins'; | ||
import { ManifestApplication } from '@expo/config-plugins/build/android/Manifest'; | ||
import { ExpoConfig } from '@expo/config-types'; | ||
|
||
/** | ||
* Determine whether a ManifestApplication has an attribute. | ||
*/ | ||
const hasMetaData = (application: ManifestApplication, metaData: string) => { | ||
return application['meta-data']?.some(item => item['$']['android:name'] === metaData); | ||
}; | ||
|
||
/** | ||
* Create `com.google.firebase.messaging.default_notification_icon` and `com.google.firebase.messaging.default_notification_color` | ||
*/ | ||
export const withExpoPluginFirebaseNotification: ConfigPlugin = config => { | ||
return withAndroidManifest(config, async config => { | ||
// Add NS `xmlns:tools to handle boundary conditions. | ||
config.modResults.manifest.$ = { | ||
...config.modResults.manifest.$, | ||
'xmlns:tools': 'http://schemas.android.com/tools', | ||
}; | ||
|
||
const application = config.modResults.manifest.application![0]; | ||
setFireBaseMessagingAndroidManifest(config, application); | ||
return config; | ||
}); | ||
}; | ||
|
||
export function setFireBaseMessagingAndroidManifest( | ||
config: ExpoConfig, | ||
application: ManifestApplication, | ||
) { | ||
// If the notification object is not defined, print a friendly warning | ||
if (!config.notification) { | ||
// 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( | ||
'For Android 8.0 and above, it is necessary to set the notification icon to ensure correct display. Otherwise, the notification will not show the correct icon. For more information, visit https://docs.expo.dev/versions/latest/config/app/#notification', | ||
); | ||
return config; | ||
} | ||
|
||
// Defensive code | ||
application['meta-data'] ??= []; | ||
|
||
const metaData = application['meta-data']; | ||
|
||
if ( | ||
config.notification.icon && | ||
!hasMetaData(application, 'com.google.firebase.messaging.default_notification_icon') | ||
) { | ||
// Expo will automatically create '@drawable/notification_icon' resource if you specify config.notification.icon. | ||
metaData.push({ | ||
$: { | ||
'android:name': 'com.google.firebase.messaging.default_notification_icon', | ||
'android:resource': '@drawable/notification_icon', | ||
}, | ||
}); | ||
} | ||
|
||
if ( | ||
config.notification.color && | ||
!hasMetaData(application, 'com.google.firebase.messaging.default_notification_color') | ||
) { | ||
metaData.push({ | ||
$: { | ||
'android:name': 'com.google.firebase.messaging.default_notification_color', | ||
'android:resource': '@color/notification_icon_color', | ||
// @react-native-firebase/messaging will automatically configure the notification color from the 'firebase.json' file, setting 'tools:replace' = 'android:resource' to overwrite it. | ||
// @ts-ignore | ||
'tools:replace': 'android:resource', | ||
}, | ||
}); | ||
} | ||
|
||
return application; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { ConfigPlugin, withPlugins, createRunOncePlugin } from '@expo/config-plugins'; | ||
import { withExpoPluginFirebaseNotification } from './android'; | ||
|
||
/** | ||
* A config plugin for configuring `@react-native-firebase/app` | ||
*/ | ||
const withRnFirebaseApp: ConfigPlugin = config => { | ||
return withPlugins(config, [ | ||
// iOS | ||
|
||
// Android | ||
withExpoPluginFirebaseNotification, | ||
]); | ||
}; | ||
|
||
const pak = require('@react-native-firebase/messaging/package.json'); | ||
export default createRunOncePlugin(withRnFirebaseApp, pak.name, pak.version); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"extends": "@tsconfig/node-lts/tsconfig", | ||
"compilerOptions": { | ||
"outDir": "build", | ||
"rootDir": "src", | ||
"declaration": true | ||
}, | ||
"include": ["./src"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34152ed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
react-native-firebase – ./
react-native-firebase-git-main-invertase.vercel.app
react-native-firebase.vercel.app
react-native-firebase-invertase.vercel.app
rnfirebase.io