diff --git a/apps/common-app/src/demos/Record/Record.tsx b/apps/common-app/src/demos/Record/Record.tsx index 90c9775d0..9f3f1b6b3 100644 --- a/apps/common-app/src/demos/Record/Record.tsx +++ b/apps/common-app/src/demos/Record/Record.tsx @@ -1,5 +1,8 @@ import React, { FC, useCallback, useEffect, useState } from 'react'; -import { AudioManager, RecordingNotificationManager } from 'react-native-audio-api'; +import { + AudioManager, + RecordingNotificationManager, +} from 'react-native-audio-api'; import { Alert, StyleSheet, View } from 'react-native'; import { Container } from '../../components'; @@ -10,7 +13,6 @@ import RecordingTime from './RecordingTime'; import RecordingVisualization from './RecordingVisualization'; import Status from './Status'; import { RecordingState } from './types'; -import { AudioEventSubscription } from 'react-native-audio-api/lib/typescript/events'; AudioManager.setAudioSessionOptions({ iosCategory: 'playAndRecord', @@ -22,30 +24,6 @@ const Record: FC = () => { const [state, setState] = useState(RecordingState.Idle); const [hasPermissions, setHasPermissions] = useState(false); - useEffect(() => { - const pauseListener = RecordingNotificationManager.addEventListener( - 'recordingNotificationPause', - () => { - console.log('Notification pause action received'); - onPauseRecording(); - } - ); - - const resumeListener = RecordingNotificationManager.addEventListener( - 'recordingNotificationResume', - () => { - console.log('Notification resume action received'); - onResumeRecording(); - } - ); - - return () => { - pauseListener.remove(); - resumeListener.remove(); - RecordingNotificationManager.hide(); - }; - }, []); - const setNotification = (paused: boolean) => { RecordingNotificationManager.show({ title: 'Recording Demo', @@ -180,6 +158,30 @@ const Record: FC = () => { })(); }, []); + useEffect(() => { + const pauseListener = RecordingNotificationManager.addEventListener( + 'recordingNotificationPause', + () => { + console.log('Notification pause action received'); + onPauseRecording(); + } + ); + + const resumeListener = RecordingNotificationManager.addEventListener( + 'recordingNotificationResume', + () => { + console.log('Notification resume action received'); + onResumeRecording(); + } + ); + + return () => { + pauseListener.remove(); + resumeListener.remove(); + RecordingNotificationManager.hide(); + }; + }, [onPauseRecording, onResumeRecording]); + useEffect(() => { Recorder.enableFileOutput(); diff --git a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/notification/NotificationRegistry.kt b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/notification/NotificationRegistry.kt index 58cbcc87c..0ab29555d 100644 --- a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/notification/NotificationRegistry.kt +++ b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/notification/NotificationRegistry.kt @@ -125,6 +125,7 @@ class NotificationRegistry( "audio_playback", ) } + "recording" -> { RecordingNotification( reactContext, @@ -133,7 +134,10 @@ class NotificationRegistry( "audio_recording4", ) } - else -> throw IllegalArgumentException("Unknown notification type: $type") + + else -> { + throw IllegalArgumentException("Unknown notification type: $type") + } } notifications[key] = notification diff --git a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/notification/RecordingNotificationReceiver.kt b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/notification/RecordingNotificationReceiver.kt index bfc5d7768..37e71f344 100644 --- a/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/notification/RecordingNotificationReceiver.kt +++ b/packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/notification/RecordingNotificationReceiver.kt @@ -24,6 +24,7 @@ class RecordingNotificationReceiver( Log.d(TAG, "Recording stopped via notification") module.invokeHandlerWithEventNameAndEventBody("recordingNotificationPause", mapOf()) } + NOTIFICATION_RECORDING_RESUMED -> { Log.d(TAG, "Recording resumed via notification") module.invokeHandlerWithEventNameAndEventBody("recordingNotificationResume", mapOf()) diff --git a/packages/react-native-audio-api/src/system/notification/RecordingNotificationManager.ios.ts b/packages/react-native-audio-api/src/system/notification/RecordingNotificationManager.ios.ts new file mode 100644 index 000000000..e026975a1 --- /dev/null +++ b/packages/react-native-audio-api/src/system/notification/RecordingNotificationManager.ios.ts @@ -0,0 +1,65 @@ +import { AudioEventEmitter, AudioEventSubscription } from '../../events'; +import type { + NotificationManager, + RecordingNotificationEvent, + RecordingNotificationEventName, + RecordingNotificationInfo, +} from './types'; + +class RecordingNotificationManager + implements + NotificationManager< + RecordingNotificationInfo, + RecordingNotificationEventName + > +{ + private audioEventEmitter: AudioEventEmitter; + + constructor() { + this.audioEventEmitter = new AudioEventEmitter(global.AudioEventEmitter); + console.warn( + 'RecordingNotificationManager is not implemented on iOS. Any calls to it will be no-ops.' + ); + } + + /** + * Show the notification with metadata or update if already visible. + * + * @param info - The info to be displayed. + * @returns Promise that resolves after creating notification. + */ + async show(_info: RecordingNotificationInfo): Promise {} + + /** + * Hide the notification. + * + * @returns Promise that resolves after hiding notification. + */ + async hide(): Promise {} + + /** + * Check if the notification is currently active. + * + * @returns Promise that resolves to whether notification is active. + */ + // eslint-disable-next-line @typescript-eslint/require-await + async isActive(): Promise { + return false; + } + + /** + * Add an event listener for notification actions. + * + * @param eventName - The event name to listen for. + * @param callback - The callback to invoke on event. + * @returns Promise that resolves to whether notification is active. + */ + addEventListener( + eventName: T, + callback: (event: RecordingNotificationEvent[T]) => void + ): AudioEventSubscription { + return this.audioEventEmitter.addAudioEventListener(eventName, callback); + } +} + +export default new RecordingNotificationManager();