Skip to content

Commit 983768f

Browse files
committed
refactor: share audio playback hook
1 parent 3513880 commit 983768f

File tree

3 files changed

+76
-45
lines changed

3 files changed

+76
-45
lines changed

nepalingo-web/src/components/Card.tsx

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import React, { useState } from "react";
1+
import React from "react";
22
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
33
import { faVolumeHigh } from "@fortawesome/free-solid-svg-icons";
44
import { useLanguage } from "@/hooks/Langauge";
5+
import useAudioPlayer from "@/hooks/useAudioPlayer";
56

67
interface CardProps {
78
Word: string;
@@ -22,25 +23,12 @@ const Card: React.FC<CardProps> = ({
2223
PronounciationUrl,
2324
viewType,
2425
}) => {
25-
const [audio, setAudio] = useState<HTMLAudioElement | null>(null);
2626
const { selectedLanguage } = useLanguage();
27+
const { togglePlayback } = useAudioPlayer(PronounciationUrl);
2728

28-
const handlePronunciation = (event: React.MouseEvent) => {
29+
const handlePronunciation = (event: React.MouseEvent<HTMLButtonElement>) => {
2930
event.stopPropagation();
30-
if (PronounciationUrl) {
31-
if (audio) {
32-
if (!audio.paused) {
33-
audio.pause();
34-
audio.currentTime = 0;
35-
} else {
36-
audio.play();
37-
}
38-
} else {
39-
const newAudio = new Audio(PronounciationUrl);
40-
setAudio(newAudio);
41-
newAudio.play();
42-
}
43-
}
31+
togglePlayback();
4432
};
4533

4634
return (

nepalingo-web/src/components/SearchResponseCard.tsx

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,16 @@
11
import { Meaning } from "@/hooks/useDictionary";
2-
import React, { useEffect, useState } from "react";
2+
import React from "react";
33
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
44
import { faVolumeHigh } from "@fortawesome/free-solid-svg-icons";
5+
import useAudioPlayer from "@/hooks/useAudioPlayer";
56

67
const SearchResponseCard = ({ meaning }: { meaning: Meaning }) => {
7-
const [audio, setAudio] = useState<HTMLAudioElement | null>(null);
8-
9-
useEffect(() => {
10-
return () => {
11-
if (audio) {
12-
audio.pause();
13-
audio.currentTime = 0;
14-
}
15-
};
16-
}, [audio]);
8+
const { togglePlayback } = useAudioPlayer(meaning.audio?.uri);
179

1810
const handlePronunciation = (event: React.MouseEvent<HTMLButtonElement>) => {
1911
event.stopPropagation();
2012

21-
if (!meaning.audio?.uri) {
22-
return;
23-
}
24-
25-
if (audio) {
26-
if (!audio.paused) {
27-
audio.pause();
28-
audio.currentTime = 0;
29-
} else {
30-
audio.currentTime = 0;
31-
void audio.play();
32-
}
33-
} else {
34-
const newAudio = new Audio(meaning.audio.uri);
35-
setAudio(newAudio);
36-
void newAudio.play();
37-
}
13+
togglePlayback();
3814
};
3915

4016
return (
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { useCallback, useEffect, useRef } from "react";
2+
3+
const resetAudio = (audio: HTMLAudioElement | null) => {
4+
if (!audio) {
5+
return;
6+
}
7+
8+
audio.pause();
9+
audio.currentTime = 0;
10+
};
11+
12+
const useAudioPlayer = (audioUrl?: string) => {
13+
const audioRef = useRef<HTMLAudioElement | null>(null);
14+
const lastUrlRef = useRef<string | undefined>(audioUrl);
15+
16+
useEffect(() => {
17+
return () => {
18+
resetAudio(audioRef.current);
19+
audioRef.current = null;
20+
};
21+
}, []);
22+
23+
useEffect(() => {
24+
if (!audioUrl) {
25+
resetAudio(audioRef.current);
26+
audioRef.current = null;
27+
} else if (lastUrlRef.current && lastUrlRef.current !== audioUrl) {
28+
resetAudio(audioRef.current);
29+
audioRef.current = null;
30+
}
31+
32+
lastUrlRef.current = audioUrl;
33+
}, [audioUrl]);
34+
35+
const togglePlayback = useCallback(() => {
36+
if (!audioUrl) {
37+
return;
38+
}
39+
40+
const existingAudio = audioRef.current;
41+
42+
if (existingAudio) {
43+
if (!existingAudio.paused) {
44+
resetAudio(existingAudio);
45+
} else {
46+
existingAudio.currentTime = 0;
47+
const playPromise = existingAudio.play();
48+
if (playPromise) {
49+
void playPromise.catch(() => undefined);
50+
}
51+
}
52+
53+
return;
54+
}
55+
56+
const newAudio = new Audio(audioUrl);
57+
audioRef.current = newAudio;
58+
const playPromise = newAudio.play();
59+
if (playPromise) {
60+
void playPromise.catch(() => undefined);
61+
}
62+
}, [audioUrl]);
63+
64+
return { togglePlayback };
65+
};
66+
67+
export default useAudioPlayer;

0 commit comments

Comments
 (0)