Untitled

 avatar
unknown
javascript
a month ago
3.1 kB
3
Indexable
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
import notifee from '@notifee/react-native';

export type IOSInterruptionType = 
  | 'phone_call'
  | 'facetime'
  | 'siri'
  | 'system_alert'
  | 'unknown';

export type IOSInterruptionEvent = {
  type: 'began' | 'ended';
  reason: IOSInterruptionType;
  options?: {
    shouldResume?: boolean;
  };
};

class IOSAudioSessionManager {
  private listeners: Set<(event: IOSInterruptionEvent) => void> = new Set();
  private audioSessionEmitter?: NativeEventEmitter;

  constructor() {
    if (Platform.OS === 'ios') {
      const { RNAudioRecorderPlayer } = NativeModules;
      this.audioSessionEmitter = new NativeEventEmitter(RNAudioRecorderPlayer);
      this.setupInterruptionListener();
    }
  }

  private setupInterruptionListener(): void {
    if (!this.audioSessionEmitter) return;

    this.audioSessionEmitter.addListener(
      'audioSessionInterruption',
      this.handleAudioInterruption
    );
  }

  private handleAudioInterruption = (event: any) => {
    const interruptionType = this.getInterruptionType(event);
    
    this.notifyListeners({
      type: event.type === 'began' ? 'began' : 'ended',
      reason: interruptionType,
      options: {
        shouldResume: event.type === 'ended' && event.options?.shouldResume
      }
    });

    this.updateNotification(event.type, interruptionType);
  };

  private getInterruptionType(event: any): IOSInterruptionType {
    switch (event.reason) {
      case 'AVAudioSessionInterruptionTypePhoneCall':
        return 'phone_call';
      case 'AVAudioSessionInterruptionTypeFaceTime':
        return 'facetime';
      case 'AVAudioSessionInterruptionTypeSiri':
        return 'siri';
      case 'AVAudioSessionInterruptionTypeSystemAlert':
        return 'system_alert';
      default:
        return 'unknown';
    }
  }

  private async updateNotification(
    state: 'began' | 'ended',
    type: IOSInterruptionType
  ) {
    const messages = {
      phone_call: 'Phone Call',
      facetime: 'FaceTime Call',
      siri: 'Siri',
      system_alert: 'System Alert',
      unknown: 'System Interruption'
    };

    await notifee.displayNotification({
      id: 'recording-notification',
      title: state === 'began' ? 'Recording Paused' : 'Recording Resumed',
      body: state === 'began' 
        ? `Recording paused due to ${messages[type]}`
        : 'Recording has resumed',
      ios: {
        categoryId: 'recording',
        interruptionLevel: 'active'
      }
    });
  }

  public addListener(listener: (event: IOSInterruptionEvent) => void): () => void {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }

  private notifyListeners(event: IOSInterruptionEvent): void {
    this.listeners.forEach(listener => listener(event));
  }

  public cleanup(): void {
    if (this.audioSessionEmitter) {
      this.audioSessionEmitter.removeAllListeners('audioSessionInterruption');
    }
    this.listeners.clear();
  }
}

export const iOSAudioManager = new IOSAudioSessionManager();
Leave a Comment