functionality for handling male and female recordings of words

This commit is contained in:
adueck 2024-09-10 19:07:16 -04:00
parent a91ae1b1f3
commit d2a1d03640
5 changed files with 69 additions and 21 deletions

View File

@ -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>
) {
const gendersRecorded = getRecordedGenders(entry);
function handlePlayStorageAudio(gender: T.Gender) {
return (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
e.stopPropagation();
playStorageAudio(entry.ts, entry.p, () => null);
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 && (
{!nonClickable &&
gendersRecorded.map((gender) => (
<i
onClick={handlePlayStorageAudio}
onClick={handlePlayStorageAudio(gender)}
className="clickable ml-2 fas fa-volume-down px-1"
title="play audio"
/>
)}
))}
</div>
<div>
<ExtraEntryInfo entry={entry} textOptions={textOptions} />

View File

@ -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"

View File

@ -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();

View File

@ -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"]
: [];
}

View File

@ -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",