From 02095aa6280fe7b87af04adac217eec35eef33b8 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Wed, 8 Feb 2023 16:24:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(rn):=20=E5=A2=9E=E5=8A=A0notifee=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E6=9C=AC=E5=9C=B0=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/mobile/ios/Podfile.lock | 9 +++ client/mobile/package.json | 1 + client/mobile/src/AppMain.tsx | 7 +- client/mobile/src/lib/notifications/index.ts | 81 ++++++++++++++++++++ client/mobile/yarn.lock | 5 ++ 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 client/mobile/src/lib/notifications/index.ts diff --git a/client/mobile/ios/Podfile.lock b/client/mobile/ios/Podfile.lock index cdd80d5d..1f78df60 100644 --- a/client/mobile/ios/Podfile.lock +++ b/client/mobile/ios/Podfile.lock @@ -419,6 +419,11 @@ PODS: - React - RNGestureHandler (2.9.0): - React-Core + - RNNotifee (7.4.0): + - React-Core + - RNNotifee/NotifeeCore (= 7.4.0) + - RNNotifee/NotifeeCore (7.4.0): + - React-Core - RNReanimated (2.14.4): - DoubleConversion - FBLazyVector @@ -513,6 +518,7 @@ DEPENDENCIES: - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - ReactNativeUiLib (from `../node_modules/react-native-ui-lib`) - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) + - "RNNotifee (from `../node_modules/@notifee/react-native`)" - RNReanimated (from `../node_modules/react-native-reanimated`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -607,6 +613,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-ui-lib" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" + RNNotifee: + :path: "../node_modules/@notifee/react-native" RNReanimated: :path: "../node_modules/react-native-reanimated" Yoga: @@ -662,6 +670,7 @@ SPEC CHECKSUMS: ReactCommon: f697c0ac52e999aa818e43e2b6f277787c735e2d ReactNativeUiLib: 8d3804947431a465a69f09c5e785c988314612a9 RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39 + RNNotifee: da8dcf09f079ea22f46e239d7c406e10d4525a5f RNReanimated: cc5e3aa479cb9170bcccf8204291a6950a3be128 SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Yoga: 5b0304b3dbef2b52e078052138e23a19c7dacaef diff --git a/client/mobile/package.json b/client/mobile/package.json index 77bf4eb9..7cddb137 100644 --- a/client/mobile/package.json +++ b/client/mobile/package.json @@ -10,6 +10,7 @@ "test": "jest" }, "dependencies": { + "@notifee/react-native": "^7.4.0", "immer": "^9.0.19", "react": "18.2.0", "react-native": "0.71.2", diff --git a/client/mobile/src/AppMain.tsx b/client/mobile/src/AppMain.tsx index f91d85c4..c554b314 100644 --- a/client/mobile/src/AppMain.tsx +++ b/client/mobile/src/AppMain.tsx @@ -1,6 +1,7 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { StyleSheet, View } from 'react-native'; import { WebView } from 'react-native-webview'; +import { initNotificationEnv } from './lib/notifications'; /** * Tailchat的主要内容 @@ -12,6 +13,10 @@ interface Props { host: string; } export const AppMain: React.FC = React.memo((props) => { + useEffect(() => { + initNotificationEnv(); + }, []); + return ( diff --git a/client/mobile/src/lib/notifications/index.ts b/client/mobile/src/lib/notifications/index.ts new file mode 100644 index 00000000..e20b42df --- /dev/null +++ b/client/mobile/src/lib/notifications/index.ts @@ -0,0 +1,81 @@ +import notifee, { EventType } from '@notifee/react-native'; + +interface NotificationInfo { + title: string; + body: string; +} + +// Create a channel (required for Android) +async function createDefaultChannel() { + const channelId = await notifee.createChannel({ + id: 'default', + name: 'Default Channel', + }); + + return channelId; +} + +/** + * 显示本地通知 + */ +export async function showNotification(info: NotificationInfo) { + // Request permissions (required for iOS) + await notifee.requestPermission(); + + const channelId = await createDefaultChannel(); + + // Display a notification + await notifee.displayNotification({ + title: info.title, + body: info.body, + android: { + channelId, + // pressAction is needed if you want the notification to open the app when pressed + pressAction: { + id: 'default', + }, + }, + }); +} + +export async function initNotificationEnv() { + await notifee.requestPermission(); + + await initForegroundService(); +} + +async function initForegroundService() { + notifee.registerForegroundService((_notification) => { + return new Promise(() => { + // 一直pending,因此前台服务会一直存在 + + notifee.onForegroundEvent(async ({ type, detail }) => { + if ( + type === EventType.ACTION_PRESS && + detail.pressAction?.id === 'stop' + ) { + await notifee.stopForegroundService(); + } + }); + }); + }); + + const channelId = await createDefaultChannel(); + + notifee.displayNotification({ + title: 'Foreground service', + body: 'This notification will exist for the lifetime of the service runner', + android: { + channelId, + asForegroundService: true, + actions: [ + { + title: '停止前台服务', + pressAction: { + id: 'stop', + }, + }, + ], + }, + }); +} diff --git a/client/mobile/yarn.lock b/client/mobile/yarn.lock index aec5e629..c04b9014 100644 --- a/client/mobile/yarn.lock +++ b/client/mobile/yarn.lock @@ -1436,6 +1436,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@notifee/react-native@^7.4.0": + version "7.4.0" + resolved "https://registry.npmmirror.com/@notifee/react-native/-/react-native-7.4.0.tgz#0f20744307bf3b800f7b56eb2d0bbdd474748d09" + integrity sha512-c8pkxDQFRbw0JlUmTb07OTG/4LQHRj8MBodMLwEcO+SvqIxK8ya8zSUEzfdcdWsSVqdoym0v3zpSNroR3Quj/w== + "@react-native-community/cli-clean@^10.1.1": version "10.1.1" resolved "https://registry.npmmirror.com/@react-native-community/cli-clean/-/cli-clean-10.1.1.tgz#4c73ce93a63a24d70c0089d4025daac8184ff504"