Skip to content

Commit 68e08a8

Browse files
committed
fixed mic permission error
1 parent 328a3a5 commit 68e08a8

4 files changed

Lines changed: 17 additions & 38 deletions

File tree

public/echotasks_preview.png

163 KB
Loading

src/app/favicon.ico

-12.3 KB
Binary file not shown.

src/app/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,4 +569,4 @@ export default function Home() {
569569

570570

571571

572-
572+

src/components/voice-recorder.tsx

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type VoiceRecorderProps = {
1515
export function VoiceRecorder({ onRecordingComplete, isProcessing }: VoiceRecorderProps) {
1616
const { settings } = useSettings();
1717
const [isRecording, setIsRecording] = useState(false);
18-
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
18+
const [hasPermission, setHasPermission] = useState(true); // Assume true, will be updated on error
1919
const mediaRecorderRef = useRef<MediaRecorder | null>(null);
2020
const audioChunksRef = useRef<Blob[]>([]);
2121
const silenceTimerRef = useRef<NodeJS.Timeout | null>(null);
@@ -24,30 +24,6 @@ export function VoiceRecorder({ onRecordingComplete, isProcessing }: VoiceRecord
2424
const streamRef = useRef<MediaStream | null>(null);
2525
const spacebarHeldRef = useRef(false);
2626

27-
const checkMicPermission = useCallback(async () => {
28-
try {
29-
// Check permission status without prompting
30-
const permissionStatus = await navigator.permissions.query({ name: 'microphone' as PermissionName });
31-
if (permissionStatus.state === 'granted') {
32-
setHasPermission(true);
33-
} else if (permissionStatus.state === 'denied') {
34-
setHasPermission(false);
35-
} else {
36-
setHasPermission(null); // Prompt needed
37-
}
38-
permissionStatus.onchange = () => {
39-
setHasPermission(permissionStatus.state === 'granted');
40-
};
41-
} catch (error) {
42-
console.error("Permissions API not supported, falling back to getUserMedia check", error);
43-
setHasPermission(null); // Fallback to prompt on action
44-
}
45-
}, []);
46-
47-
useEffect(() => {
48-
checkMicPermission();
49-
}, [checkMicPermission]);
50-
5127
const stopSilenceTimer = () => {
5228
if (silenceTimerRef.current) {
5329
clearTimeout(silenceTimerRef.current);
@@ -67,21 +43,17 @@ export function VoiceRecorder({ onRecordingComplete, isProcessing }: VoiceRecord
6743
}, []);
6844

6945
const stopRecording = useCallback(() => {
70-
if (mediaRecorderRef.current && isRecording) {
46+
if (mediaRecorderRef.current && mediaRecorderRef.current.state === "recording") {
7147
mediaRecorderRef.current.stop();
72-
setIsRecording(false);
7348
}
74-
}, [isRecording]);
49+
// We set isRecording to false in the onstop handler
50+
}, []);
7551

7652
const startRecording = useCallback(async () => {
7753
if (isRecording || isProcessing) return;
78-
79-
if (hasPermission === false) {
80-
alert('Microphone access is denied. Please enable it in your browser settings.');
81-
return;
82-
}
8354

8455
try {
56+
// Directly request microphone access. This is the key change to trigger the prompt.
8557
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
8658
streamRef.current = stream;
8759
setHasPermission(true);
@@ -96,13 +68,20 @@ export function VoiceRecorder({ onRecordingComplete, isProcessing }: VoiceRecord
9668
};
9769

9870
mediaRecorderRef.current.onstop = () => {
71+
setIsRecording(false);
9972
stopSilenceTimer();
10073
if (audioChunksRef.current.length > 0) {
10174
const audioBlob = new Blob(audioChunksRef.current, { type: 'audio/webm' });
10275
onRecordingComplete(audioBlob);
10376
}
10477
stopMediaStream();
10578
};
79+
80+
mediaRecorderRef.current.onerror = (event) => {
81+
console.error('MediaRecorder error:', event);
82+
setIsRecording(false);
83+
stopMediaStream();
84+
}
10685

10786
mediaRecorderRef.current.start();
10887
setIsRecording(true);
@@ -142,9 +121,9 @@ export function VoiceRecorder({ onRecordingComplete, isProcessing }: VoiceRecord
142121
} catch (error) {
143122
console.error('Error accessing microphone:', error);
144123
setHasPermission(false);
145-
alert('Could not access microphone. Please check permissions and try again.');
124+
alert('Could not access microphone. Please enable it in your browser settings and refresh the page.');
146125
}
147-
}, [isRecording, isProcessing, hasPermission, settings.micMode, settings.intelligentStopDuration, onRecordingComplete, stopMediaStream, stopRecording]);
126+
}, [isRecording, isProcessing, settings.micMode, settings.intelligentStopDuration, onRecordingComplete, stopMediaStream, stopRecording]);
148127

149128

150129
useEffect(() => {
@@ -209,7 +188,7 @@ export function VoiceRecorder({ onRecordingComplete, isProcessing }: VoiceRecord
209188
onPointerDown={handlePointerDown}
210189
onPointerUp={handlePointerUp}
211190
onPointerLeave={handlePointerUp} // Stop if user's finger leaves the button
212-
disabled={isProcessing || (hasPermission === null && settings.micMode === 'tap')}
191+
disabled={isProcessing || !hasPermission}
213192
size="lg"
214193
className={cn(
215194
'w-20 h-20 rounded-full transition-all duration-300 ease-in-out touch-none',
@@ -229,4 +208,4 @@ export function VoiceRecorder({ onRecordingComplete, isProcessing }: VoiceRecord
229208
);
230209
}
231210

232-
211+

0 commit comments

Comments
 (0)