diff --git a/website/src/components/Entry.tsx b/website/src/components/Entry.tsx index 85980ce..73ee29c 100644 --- a/website/src/components/Entry.tsx +++ b/website/src/components/Entry.tsx @@ -47,6 +47,7 @@ function Entry({ )} diff --git a/website/src/components/EntryAudioDisplay.tsx b/website/src/components/EntryAudioDisplay.tsx index 9ae0d20..2a7fa86 100644 --- a/website/src/components/EntryAudioDisplay.tsx +++ b/website/src/components/EntryAudioDisplay.tsx @@ -12,6 +12,7 @@ export function EntryAudioDisplay({ opts: T.TextOptions; user: LingdocsUser | undefined; }) { + const audioPath = getAudioPath(entry.ts); if (!entry.a) { return null; } @@ -24,23 +25,54 @@ export function EntryAudioDisplay({ action: `play ${entry.p} - ${entry.ts}`, }); } + + function handleDownload() { + const documentName = `${entry.p}-${entry.ts}.mp3`; + + fetch(audioPath) + .then((res) => { + return res.blob(); + }) + .then((blob) => { + const href = window.URL.createObjectURL(blob); + const a = document.createElement("a"); + a.download = documentName; + a.href = href; + a.click(); + a.href = ""; + }) + .catch((err) => console.error(err)); + } return (
- Listen to {{ p: entry.p, f: entry.f }} +
+ Listen to{" "} + {{ p: entry.p, f: entry.f }} +
-
); } diff --git a/website/src/components/SearchBar.tsx b/website/src/components/SearchBar.tsx index 4b75713..3883b30 100644 --- a/website/src/components/SearchBar.tsx +++ b/website/src/components/SearchBar.tsx @@ -9,17 +9,18 @@ import Mousetrap from "mousetrap"; import { useEffect, useRef } from "react"; import { State } from "../types/dictionary-types"; -import { - OptionsAction, - Language, - SearchType, -} from "../types/dictionary-types"; +import { OptionsAction, Language, SearchType } from "../types/dictionary-types"; -const SearchBar = ({ state, optionsDispatch, handleSearchValueChange, onBottom }: { - state: State - optionsDispatch: (action: OptionsAction) => void, - handleSearchValueChange: (searchValue: string) => void, - onBottom?: boolean, +const SearchBar = ({ + state, + optionsDispatch, + handleSearchValueChange, + onBottom, +}: { + state: State; + optionsDispatch: (action: OptionsAction) => void; + handleSearchValueChange: (searchValue: string) => void; + onBottom?: boolean; }) => { const inputRef = useRef(null); useEffect(() => { @@ -34,8 +35,8 @@ const SearchBar = ({ state, optionsDispatch, handleSearchValueChange, onBottom } return () => { window.removeEventListener("focus", onFocus); Mousetrap.unbind(["shift+space"]); - } - // eslint-disable-next-line + }; + // eslint-disable-next-line }, []); function onFocus() { if (["/", "/search"].includes(window.location.pathname)) { @@ -50,43 +51,56 @@ const SearchBar = ({ state, optionsDispatch, handleSearchValueChange, onBottom } onClick={() => optionsDispatch({ type: "toggleLanguage" })} data-testid="languageToggle" > -
+
Ps En
); - } + }; const SearchTypeToggle = ({ searchType }: { searchType: SearchType }) => { - const icon = (searchType === "alphabetical") ? "book" : "bolt"; + const icon = searchType === "alphabetical" ? "book" : "bolt"; return ( - + ); }; - const placeholder = (state.options.searchType === "alphabetical" && state.options.language === "Pashto") - ? "Browse alphabetically" - : `Search ${state.options.language === "Pashto" ? "Pashto" : "English"}`; + const placeholder = + state.options.searchType === "alphabetical" && + state.options.language === "Pashto" + ? "Browse alphabetically" + : `Search ${state.options.language === "Pashto" ? "Pashto" : "English"}`; return ( -