-
Notifications
You must be signed in to change notification settings - Fork 138
/
Copy pathuseVoiceRecorder.tsx
111 lines (104 loc) · 3.16 KB
/
useVoiceRecorder.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { useCallback, useEffect, useRef, useState } from 'react';
import { VoiceRecorderEventHandler, useVoiceRecorderContext } from '.';
import { noop } from '../../utils/utils';
import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
// export interface UseVoiceRecorderProps extends VoiceRecorderEventHandler {
// /**
// * onRecordingStarted
// * onRecordingEnded
// */
// }
/* eslint-disable no-redeclare */
export const VoiceRecorderStatus = {
PREPARING: 'PREPARING',
READY_TO_RECORD: 'READY_TO_RECORD',
RECORDING: 'RECORDING',
COMPLETED: 'COMPLETED',
} as const;
export type VoiceRecorderStatus = typeof VoiceRecorderStatus[keyof typeof VoiceRecorderStatus];
export interface UseVoiceRecorderContext {
start: () => void;
stop: () => void;
cancel: () => void;
recordingLimit: number;
recordingTime: number;
recordedFile: File | null;
recordingStatus: VoiceRecorderStatus;
}
export const useVoiceRecorder = ({
onRecordingStarted = noop,
onRecordingEnded = noop,
}: VoiceRecorderEventHandler): UseVoiceRecorderContext => {
const { state } = useSendbird();
const { config } = state;
const { voiceRecord } = config;
const maxRecordingTime = voiceRecord.maxRecordingTime;
const voiceRecorder = useVoiceRecorderContext();
const { isRecordable } = voiceRecorder;
const [recordedFile, setRecordedFile] = useState<File | null>(null);
const [recordingStatus, setRecordingStatus] = useState<VoiceRecorderStatus>(VoiceRecorderStatus.PREPARING);
useEffect(() => {
if (isRecordable && recordingStatus === VoiceRecorderStatus.PREPARING) {
setRecordingStatus(VoiceRecorderStatus.READY_TO_RECORD);
}
}, [isRecordable]);
const start = useCallback(() => {
voiceRecorder?.start({
onRecordingStarted: () => {
setRecordingStatus(VoiceRecorderStatus.RECORDING);
onRecordingStarted();
startTimer();
},
onRecordingEnded: (audioFile) => {
setRecordingStatus(VoiceRecorderStatus.COMPLETED);
onRecordingEnded(audioFile);
setRecordedFile(audioFile);
stopTimer();
},
});
}, [onRecordingStarted, onRecordingEnded]);
const stop = useCallback(() => {
voiceRecorder?.stop();
stopTimer();
}, [voiceRecorder]);
const cancel = useCallback(() => {
stop();
setRecordedFile(null);
}, [voiceRecorder]);
// Timer
const [recordingTime, setRecordingTime] = useState<number>(0);
const timer = useRef<ReturnType<typeof setInterval> | null>(null);
function startTimer() {
stopTimer();
setRecordingTime(0);
timer.current = setInterval(() => {
setRecordingTime(prevTime => {
const newTime = prevTime + 100;
if (newTime > maxRecordingTime) {
stopTimer();
}
return newTime;
});
}, 100);
}
function stopTimer() {
if (timer.current) {
clearInterval(timer.current);
timer.current = null;
}
}
useEffect(() => {
if (recordingTime > maxRecordingTime) {
stop();
}
}, [recordingTime, maxRecordingTime, stop]);
return ({
start,
stop,
cancel,
recordingStatus,
recordingTime,
recordedFile,
recordingLimit: maxRecordingTime,
});
};