import React, { useEffect, useMemo, useRef } from "react"; import { ActivityIndicator, Alert, Linking, NativeModules, PermissionsAndroid, Platform, TouchableOpacity, View, } from "react-native"; import { useTheme } from "../../../theme"; import { Icon } from "../../icons/Icon"; import { AnimatingMic } from "./AnimatingMic"; import { Timer } from "./Timer"; import { CometChatAudioPreview } from "./CometChatAudioPreview/CometChatAudioPreview"; import { CometChatTheme } from "../../../theme/type"; import { deepMerge } from "../../helper/helperFunctions"; import { useCometChatTranslation } from "../../resources/CometChatLocalizeNew"; export interface CometChatMediaRecorderInterface { onClose?: Function; onPlay?: Function; onPause?: Function; onStop?: Function; onSend?: Function; onStart?: Function; style?: CometChatTheme["mediaRecorderStyle"]; } type RecordingState = "initial" | "recording" | "paused" | "stopped" | "loading"; export const CometChatMediaRecorder = (props: CometChatMediaRecorderInterface) => { const { onClose, onPause, onPlay, onSend, onStop, onStart, style } = props; const [time, setTime] = React.useState(0); const [recordedFile, setRecordedFile] = React.useState(""); const [recordingState, setRecordedState] = React.useState("initial"); const recordingTimeRef = useRef({ recordingStartedAt: 0, recordingTotalDuration: 0, }); const theme = useTheme(); const {t}=useCometChatTranslation() const mergedStyle = useMemo(() => { return deepMerge(theme.mediaRecorderStyle, style ?? {}); }, [theme, style]); const _audioBubbleStyle = theme.messageListStyles.outgoingMessageBubbleStyles?.audioBubbleStyles; useEffect(() => { setRecordedState("loading"); // Set loading state before recording starts recordingInitiator(); // Automatically start recording }, []); useEffect(() => { return () => { if (Platform.OS === "android") { PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO).then((res) => { if (!res) return; deleteFile(); }); } else { deleteFile(); } }; }, []); function deleteFile() { NativeModules.FileManager.deleteFile((success: any) => console.log("Filepath delete", success)); NativeModules.FileManager.releaseMediaResources((result: any) => {}); setRecordedFile(""); // Stop playing audio here } function permissionAlert() { Alert.alert('', t("MICROPHONE_PERMISSION"), [ { style: "cancel", text: t("CANCEL"), }, { style: "default", text: t("SETTINGS"), onPress: () => { Linking.openSettings(); }, }, ]); } const recordingInitiator = async (): Promise => { let microphonePermission = Platform.select({ ios: true, android: await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO), })!; if (microphonePermission) { NativeModules.FileManager.startRecording((filepath: any) => { recordingTimeRef.current.recordingStartedAt = Date.now(); recordingTimeRef.current.recordingTotalDuration = 0; setRecordedState("recording"); if (Platform.OS === "ios") { try { let resObj = JSON.parse(filepath); if (resObj?.granted === false) { permissionAlert(); onClose && onClose(); } } catch (error) { permissionAlert(); onClose && onClose(); } } }); } else { permissionAlert(); onClose && onClose(); } }; const _onStop = () => { NativeModules.FileManager.releaseMediaResources((result: any) => { setRecordedState("stopped"); recordingTimeRef.current.recordingTotalDuration += Date.now() - recordingTimeRef.current.recordingStartedAt; if (Platform.OS === "ios") { recordingTimeRef.current.recordingTotalDuration = JSON.parse(result).duration * 1000; } setRecordedFile(JSON.parse(result)?.file); onStop && onStop(JSON.parse(result)?.file); }); }; const startRecording = () => { // TODO: Set time to 0 setRecordedState("loading"); setRecordedFile(""); NativeModules.FileManager.deleteFile((success: any) => { NativeModules.FileManager.startRecording((result: any) => { setRecordedState("recording"); }); }); onStart && onStart(); }; // const _onPause = () => { // NativeModules.FileManager.pausePlaying((filepath) => { // console.log("Filepath onRecorderAudioPaused", filepath); // onPause && onPause(); // setRecordedPlaying(false); // // clearTimeout(stopRecordingIntervalId); // console.log("timeout cleared", stopRecordingIntervalId); // }); // }; // const _onClose = () => { // _onPause(); // setRecordedFile(""); // setRecordedPlaying(false); // NativeModules.FileManager.releaseMediaResources((filepath) => { // console.log("Filepath onClose", filepath); // }); // onClose && onClose(); // }; const _onDelete = () => { // Stop playing setRecordedFile(""); setRecordedState("initial"); NativeModules.FileManager.releaseMediaResources((filepath: any) => { //console.log("Filepath onClose", filepath); }); onClose && onClose(); }; const _onSend = () => { NativeModules.FileManager.releaseMediaResources((result: any) => { //console.log("Filepath _stopRecorderAudio", result); }); onSend && onSend(recordedFile); onClose && onClose(); }; const pressableIconStyle = useMemo(() => { return { padding: 8, backgroundColor: theme.color.background1, shadowColor: "#000", shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.23, shadowRadius: 2.62, elevation: 4, }; }, [theme]); return ( {recordingState !== "stopped" && ( )} {(recordingState === "recording" || recordingState === "paused") && ( )} {recordingState === "stopped" && ( )} {["paused", "stopped", "recording"].includes(recordingState) && ( )} { if (recordingState === "initial") { setRecordedState("loading"); recordingInitiator(); } else if (recordingState === "recording") { NativeModules.FileManager.pauseRecording().then((result: any) => { setRecordedState("paused"); recordingTimeRef.current.recordingTotalDuration += Date.now() - recordingTimeRef.current.recordingStartedAt; }); // _onStop(); } else if (recordingState === "paused") { NativeModules.FileManager.resumeRecording().then((result: any) => { setRecordedState("recording"); }); } else if (recordingState === "stopped") { _onSend(); } }} > {recordingState === "loading" ? ( ) : ( )} {(recordingState === "recording" || recordingState === "paused") && ( { setRecordedState("loading"); _onStop(); }} > )} {recordingState === "stopped" && ( { startRecording(); }} > )} ); };