functionality for handling male and female recordings of words
This commit is contained in:
parent
a91ae1b1f3
commit
d2a1d03640
|
@ -9,6 +9,7 @@ import ExtraEntryInfo from "../components/ExtraEntryInfo";
|
|||
import classNames from "classnames";
|
||||
import { Types as T, InlinePs } from "@lingdocs/ps-react";
|
||||
import playStorageAudio from "./PlayStorageAudio";
|
||||
import { getRecordedGenders } from "../lib/recorded-genders";
|
||||
|
||||
function Entry({
|
||||
entry,
|
||||
|
@ -22,11 +23,12 @@ function Entry({
|
|||
isolateEntry?: (ts: number) => void;
|
||||
admin: boolean;
|
||||
}) {
|
||||
function handlePlayStorageAudio(
|
||||
e: React.MouseEvent<HTMLElement, MouseEvent>
|
||||
) {
|
||||
e.stopPropagation();
|
||||
playStorageAudio(entry.ts, entry.p, () => null);
|
||||
const gendersRecorded = getRecordedGenders(entry);
|
||||
function handlePlayStorageAudio(gender: T.Gender) {
|
||||
return (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
||||
e.stopPropagation();
|
||||
playStorageAudio(entry.ts, gender, entry.p, () => null);
|
||||
};
|
||||
}
|
||||
return (
|
||||
<div
|
||||
|
@ -43,13 +45,14 @@ function Entry({
|
|||
{` `}
|
||||
{/* Can't figure out why but the <em> here can't be empty */}
|
||||
<em>{entry.c || "\u00A0"}</em>
|
||||
{entry.a && !nonClickable && (
|
||||
<i
|
||||
onClick={handlePlayStorageAudio}
|
||||
className="clickable ml-2 fas fa-volume-down px-1"
|
||||
title="play audio"
|
||||
/>
|
||||
)}
|
||||
{!nonClickable &&
|
||||
gendersRecorded.map((gender) => (
|
||||
<i
|
||||
onClick={handlePlayStorageAudio(gender)}
|
||||
className="clickable ml-2 fas fa-volume-down px-1"
|
||||
title="play audio"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
<ExtraEntryInfo entry={entry} textOptions={textOptions} />
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Types as T, InlinePs } from "@lingdocs/ps-react";
|
||||
import { getAudioPath } from "./PlayStorageAudio";
|
||||
import ReactGA from "react-ga4";
|
||||
import { getRecordedGenders } from "../lib/recorded-genders";
|
||||
|
||||
export function EntryAudioDisplay({
|
||||
entry,
|
||||
|
@ -9,23 +10,46 @@ export function EntryAudioDisplay({
|
|||
entry: T.DictionaryEntry;
|
||||
opts: T.TextOptions;
|
||||
}) {
|
||||
const audioPath = getAudioPath(entry.ts);
|
||||
if (!entry.a) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className="mb-4">
|
||||
{getRecordedGenders(entry).map((gender) => (
|
||||
<EntryRecording entry={entry} opts={opts} gender={gender} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function EntryRecording({
|
||||
entry,
|
||||
opts,
|
||||
gender,
|
||||
}: {
|
||||
entry: T.DictionaryEntry;
|
||||
opts: T.TextOptions;
|
||||
gender: T.Gender;
|
||||
}) {
|
||||
const audioPath = getAudioPath(entry.ts, gender);
|
||||
if (!entry.a) {
|
||||
return null;
|
||||
}
|
||||
function handlePlay() {
|
||||
ReactGA.event({
|
||||
category: "sounds",
|
||||
action: `play ${entry.p} - ${entry.ts}`,
|
||||
action: `play ${entry.p} - ${entry.ts} ${gender}`,
|
||||
});
|
||||
}
|
||||
|
||||
function handleDownload() {
|
||||
ReactGA.event({
|
||||
category: "sounds",
|
||||
action: `download ${entry.p} - ${entry.ts}`,
|
||||
action: `download ${entry.p} - ${entry.ts} ${gender}`,
|
||||
});
|
||||
const documentName = `${entry.p}-${entry.ts}.mp3`;
|
||||
const documentName = `${entry.p}-${entry.ts}-${
|
||||
gender === "masc" ? "m" : "f"
|
||||
}.mp3`;
|
||||
|
||||
fetch(audioPath)
|
||||
.then((res) => {
|
||||
|
@ -45,10 +69,15 @@ export function EntryAudioDisplay({
|
|||
<figure>
|
||||
<figcaption className="mb-2 pl-2">
|
||||
<div style={{ display: "none" }}>
|
||||
Listen to <InlinePs opts={opts} ps={{ p: entry.p, f: entry.f }} />
|
||||
Listen to <InlinePs opts={opts} ps={{ p: entry.p, f: entry.f }} />:
|
||||
{` `}
|
||||
{gender === "masc" ? "Male" : "Female"} recording
|
||||
</div>
|
||||
</figcaption>
|
||||
<div className="d-flex align-items-center">
|
||||
<div className="mr-2" style={{ width: "1rem" }}>
|
||||
{gender === "masc" ? "M" : "F"}
|
||||
</div>
|
||||
<audio
|
||||
controls
|
||||
controlsList="nofullscreen"
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import ReactGA from "react-ga4";
|
||||
import { Types as T } from "@lingdocs/ps-react";
|
||||
|
||||
export function getAudioPath(ts: number): string {
|
||||
return `https://storage.lingdocs.com/audio/${ts}.mp3`;
|
||||
export function getAudioPath(ts: number, gender: T.Gender): string {
|
||||
return `https://storage.lingdocs.com/audio/${ts}${
|
||||
gender === "fem" ? "f" : ""
|
||||
}.mp3`;
|
||||
}
|
||||
|
||||
export default function playStorageAudio(
|
||||
ts: number,
|
||||
gender: T.Gender,
|
||||
p: string,
|
||||
callback: () => void
|
||||
) {
|
||||
|
@ -14,7 +18,7 @@ export default function playStorageAudio(
|
|||
category: "sounds",
|
||||
action: `quick play ${p} - ${ts}`,
|
||||
});
|
||||
let audio = new Audio(getAudioPath(ts));
|
||||
let audio = new Audio(getAudioPath(ts, gender));
|
||||
audio.addEventListener("ended", () => {
|
||||
callback();
|
||||
audio.remove();
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { Types as T } from "@lingdocs/ps-react";
|
||||
|
||||
export function getRecordedGenders(entry: T.DictionaryEntry): T.Gender[] {
|
||||
return entry.a === 1
|
||||
? ["masc"]
|
||||
: entry.a === 2
|
||||
? ["fem"]
|
||||
: entry.a === 3
|
||||
? ["masc", "fem"]
|
||||
: [];
|
||||
}
|
|
@ -58,7 +58,8 @@ registerRoute(
|
|||
registerRoute(
|
||||
// Add in any other file extensions or routing criteria as needed.
|
||||
({ url }) =>
|
||||
url.origin === self.location.origin && ([".png", ".woff2", "woff"].some(ending => url.pathname.endsWith(ending)))
|
||||
url.origin === self.location.origin &&
|
||||
[".png", ".woff2", "woff"].some((ending) => url.pathname.endsWith(ending)),
|
||||
// Customize this strategy as needed, e.g., by changing to CacheFirst.
|
||||
new StaleWhileRevalidate({
|
||||
cacheName: "images",
|
||||
|
|
Loading…
Reference in New Issue