Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Recorder context #2405

Merged
merged 2 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/components/DataEntry/DataEntryTable/NewEntry/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
import SenseDialog from "components/DataEntry/DataEntryTable/NewEntry/SenseDialog";
import VernDialog from "components/DataEntry/DataEntryTable/NewEntry/VernDialog";
import Pronunciations from "components/Pronunciations/PronunciationsComponent";
import Recorder from "components/Pronunciations/Recorder";
import { StoreState } from "types";
import theme from "types/theme";
import SpellChecker from "utilities/spellChecker";
Expand All @@ -45,7 +44,6 @@ const gridItemStyle = (spacing: number): CSSProperties => ({
interface NewEntryProps {
analysisLang: WritingSystem;
vernacularLang: WritingSystem;
recorder?: Recorder;
spellChecker?: SpellChecker;
// Parent component handles new entry state:
addNewEntry: () => Promise<void>;
Expand Down Expand Up @@ -74,7 +72,6 @@ export default function NewEntry(props: NewEntryProps): ReactElement {
const {
analysisLang,
vernacularLang,
recorder,
// Parent component handles new entry state:
addNewEntry,
updateWordWithNewGloss,
Expand Down Expand Up @@ -308,7 +305,6 @@ export default function NewEntry(props: NewEntryProps): ReactElement {
wordId={""}
audioInFrontend
pronunciationFiles={newAudioUrls}
recorder={recorder}
deleteAudio={(_, fileName: string) => delNewAudioUrl(fileName)}
uploadAudio={(_, audioFile: File) => addNewAudioUrl(audioFile)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import { defaultWritingSystem } from "types/writingSystem";
// MUI: Unable to set focus to a MenuItem whose component has not been rendered.
jest.mock("@mui/material/MenuItem", () => "div");

jest.mock("goals/ReviewEntries/ReviewEntriesComponent/CellComponents", () => ({
DomainCell: () => <div />,
PartOfSpeechCell: () => <div />,
}));

let testRenderer: renderer.ReactTestRenderer;

const mockState = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import { defaultWritingSystem } from "types/writingSystem";
// MUI: Unable to set focus to a MenuItem whose component has not been rendered.
jest.mock("@mui/material/MenuItem", () => "div");

jest.mock(
"goals/ReviewEntries/ReviewEntriesComponent/CellComponents/GlossCell",
() => "div"
);
jest.mock("goals/ReviewEntries/ReviewEntriesComponent/CellComponents", () => ({
DomainCell: () => <div />,
GlossCell: () => <div />,
PartOfSpeechCell: () => <div />,
}));

let testRenderer: renderer.ReactTestRenderer;

Expand Down
3 changes: 0 additions & 3 deletions src/components/DataEntry/DataEntryTable/RecentEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
VernWithSuggestions,
} from "components/DataEntry/DataEntryTable/EntryCellComponents";
import Pronunciations from "components/Pronunciations/PronunciationsComponent";
import Recorder from "components/Pronunciations/Recorder";
import theme from "types/theme";
import { newGloss } from "types/word";
import SpellChecker from "utilities/spellChecker";
Expand All @@ -27,7 +26,6 @@ export interface RecentEntryProps {
removeEntry: () => void;
addAudioToWord: (wordId: string, audioFile: File) => void;
deleteAudioFromWord: (wordId: string, fileName: string) => void;
recorder: Recorder;
focusNewEntry: () => void;
analysisLang: WritingSystem;
vernacularLang: WritingSystem;
Expand Down Expand Up @@ -144,7 +142,6 @@ export default function RecentEntry(props: RecentEntryProps): ReactElement {
<Pronunciations
wordId={props.entry.id}
pronunciationFiles={props.entry.audio}
recorder={props.recorder}
deleteAudio={(wordId: string, fileName: string) => {
props.deleteAudioFromWord(wordId, fileName);
}}
Expand Down
4 changes: 0 additions & 4 deletions src/components/DataEntry/DataEntryTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import NewEntry from "components/DataEntry/DataEntryTable/NewEntry";
import RecentEntry from "components/DataEntry/DataEntryTable/RecentEntry";
import { filterWordsWithSenses } from "components/DataEntry/utilities";
import { getFileNameForWord } from "components/Pronunciations/AudioRecorder";
import Recorder from "components/Pronunciations/Recorder";
import { StoreState } from "types";
import { Hash } from "types/hash";
import { useAppSelector } from "types/hooks";
Expand Down Expand Up @@ -234,7 +233,6 @@ export default function DataEntryTable(

const levDist = useMemo(() => new LevenshteinDistance(), []);
const newVernInput = useRef<HTMLDivElement>(null);
const recorder = useMemo(() => new Recorder(enqueueSnackbar), []);
const spellChecker = useMemo(() => new SpellChecker(), []);
useEffect(() => {
spellChecker.updateLang(analysisLang.bcp47);
Expand Down Expand Up @@ -878,7 +876,6 @@ export default function DataEntryTable(
deleteAudioFromWord={(wordId: string, fileName: string) =>
deleteAudioFromWord(wordId, fileName)
}
recorder={recorder}
spellChecker={spellChecker}
focusNewEntry={() => focusInput(newVernInput)}
analysisLang={analysisLang}
Expand All @@ -892,7 +889,6 @@ export default function DataEntryTable(

<Grid item xs={12}>
<NewEntry
recorder={recorder}
spellChecker={spellChecker}
analysisLang={analysisLang}
vernacularLang={vernacularLang}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import RecentEntry from "components/DataEntry/DataEntryTable/RecentEntry";
import { EditTextDialog } from "components/Dialogs";
import AudioPlayer from "components/Pronunciations/AudioPlayer";
import AudioRecorder from "components/Pronunciations/AudioRecorder";
import Recorder from "components/Pronunciations/Recorder";
import { defaultState as pronunciationsState } from "components/Pronunciations/Redux/PronunciationsReduxTypes";
import theme from "types/theme";
import { simpleWord } from "types/word";
Expand Down Expand Up @@ -58,7 +57,6 @@ function renderWithWord(word: Word) {
removeEntry={jest.fn()}
addAudioToWord={jest.fn()}
deleteAudioFromWord={jest.fn()}
recorder={new Recorder()}
focusNewEntry={jest.fn()}
analysisLang={newWritingSystem()}
vernacularLang={newWritingSystem()}
Expand Down
6 changes: 3 additions & 3 deletions src/components/Pronunciations/AudioRecorder.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ReactElement } from "react";
import { ReactElement, useContext } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "react-toastify";

import Recorder from "components/Pronunciations/Recorder";
import RecorderContext from "components/Pronunciations/RecorderContext";
import RecorderIcon from "components/Pronunciations/RecorderIcon";

interface RecorderProps {
wordId: string;
recorder?: Recorder;
uploadAudio: (wordId: string, audioFile: File) => void;
}

Expand All @@ -20,8 +20,8 @@ export function getFileNameForWord(wordId: string): string {
}

export default function AudioRecorder(props: RecorderProps): ReactElement {
const recorder = useContext(RecorderContext);
const { t } = useTranslation();
const recorder = props.recorder ?? new Recorder();

function startRecording(): void {
recorder.startRecording();
Expand Down
8 changes: 1 addition & 7 deletions src/components/Pronunciations/PronunciationsComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ import { memo, ReactElement } from "react";
import { getAudioUrl } from "backend";
import AudioPlayer from "components/Pronunciations/AudioPlayer";
import AudioRecorder from "components/Pronunciations/AudioRecorder";
import Recorder from "components/Pronunciations/Recorder";

interface PronunciationProps {
wordId: string;
audioInFrontend?: boolean;
pronunciationFiles: string[];
recorder?: Recorder;
deleteAudio: (wordId: string, fileName: string) => void;
uploadAudio: (wordId: string, audioFile: File) => void;
}
Expand All @@ -32,11 +30,7 @@ export function Pronunciations(props: PronunciationProps): ReactElement {

return (
<>
<AudioRecorder
wordId={props.wordId}
recorder={props.recorder}
uploadAudio={props.uploadAudio}
/>
<AudioRecorder wordId={props.wordId} uploadAudio={props.uploadAudio} />
{audioButtons}
</>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/Pronunciations/Recorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default class Recorder {
static blobType: "audio" = "audio";

constructor(toast?: (text: string) => void) {
this.toast = toast ?? alert;
this.toast = toast ?? ((text: string) => alert(text));
navigator.mediaDevices
.getUserMedia({ audio: true })
.then((audioStream) => this.onMicrophoneAvailable(audioStream))
Expand Down
8 changes: 8 additions & 0 deletions src/components/Pronunciations/RecorderContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { enqueueSnackbar } from "notistack";
import { createContext } from "react";

import Recorder from "components/Pronunciations/Recorder";

const RecorderContext = createContext(new Recorder(enqueueSnackbar));

export default RecorderContext;
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@ const columns: Column<any>[] = [
<PronunciationsCell
wordId={rowData.id}
pronunciationFiles={rowData.pronunciationFiles}
recorder={rowData.recorder}
/>
),
customFilterAndSearch: (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Pronunciations from "components/Pronunciations/PronunciationsComponent";
import Recorder from "components/Pronunciations/Recorder";
import {
deleteAudio,
uploadAudio,
Expand All @@ -9,7 +8,6 @@ import { useAppDispatch } from "types/hooks";
interface PronunciationsCellProps {
wordId: string;
pronunciationFiles: string[];
recorder?: Recorder;
}

/** Used to connect the pronunciation component to the deleteAudio and uploadAudio actions */
Expand All @@ -24,7 +22,6 @@ export default function PronunciationsCell(props: PronunciationsCellProps) {
<Pronunciations
wordId={props.wordId}
pronunciationFiles={props.pronunciationFiles}
recorder={props.recorder}
deleteAudio={dispatchDelete}
uploadAudio={dispatchUpload}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import configureMockStore from "redux-mock-store";

import "tests/reactI18nextMock";

import { DefinitionCell } from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents";
import DefinitionCell from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents/DefinitionCell";
import mockWords from "goals/ReviewEntries/ReviewEntriesComponent/tests/WordsMock";
import { defaultWritingSystem } from "types/writingSystem";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import configureMockStore from "redux-mock-store";

import "tests/reactI18nextMock";

import { DeleteCell } from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents";
import DeleteCell from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents/DeleteCell";
import { defaultState as reviewEntriesState } from "goals/ReviewEntries/ReviewEntriesComponent/Redux/ReviewEntriesReduxTypes";
import mockWords from "goals/ReviewEntries/ReviewEntriesComponent/tests/WordsMock";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import configureMockStore from "redux-mock-store";

import "tests/reactI18nextMock";

import { DomainCell } from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents";
import DomainCell from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents/DomainCell";
import mockWords from "goals/ReviewEntries/ReviewEntriesComponent/tests/WordsMock";

jest.mock("components/TreeView", () => "div");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import renderer from "react-test-renderer";

import "tests/reactI18nextMock";

import { FlagCell } from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents";
import FlagCell from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents/FlagCell";
import mockWords from "goals/ReviewEntries/ReviewEntriesComponent/tests/WordsMock";

const mockWord = mockWords()[1];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import configureMockStore from "redux-mock-store";

import "tests/reactI18nextMock";

import { GlossCell } from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents";
import GlossCell from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents/GlossCell";
import mockWords from "goals/ReviewEntries/ReviewEntriesComponent/tests/WordsMock";
import { defaultWritingSystem } from "types/writingSystem";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import renderer from "react-test-renderer";

import "tests/reactI18nextMock";

import { NoteCell } from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents";
import NoteCell from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents/NoteCell";
import mockWords from "goals/ReviewEntries/ReviewEntriesComponent/tests/WordsMock";

// The multiline TextField causes problems in the mock environment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import renderer from "react-test-renderer";

import "tests/reactI18nextMock";

import { PartOfSpeechCell } from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents";
import PartOfSpeechCell from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents/PartOfSpeechCell";
import mockWords from "goals/ReviewEntries/ReviewEntriesComponent/tests/WordsMock";

const mockWord = mockWords()[1];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import renderer from "react-test-renderer";

import "tests/reactI18nextMock";

import { SenseCell } from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents";
import SenseCell from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents/SenseCell";
import mockWords from "goals/ReviewEntries/ReviewEntriesComponent/tests/WordsMock";

const mockWord = mockWords()[1];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import renderer from "react-test-renderer";

import "tests/reactI18nextMock";

import { VernacularCell } from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents";
import VernacularCell from "goals/ReviewEntries/ReviewEntriesComponent/CellComponents/VernacularCell";
import mockWords from "goals/ReviewEntries/ReviewEntriesComponent/tests/WordsMock";

// The multiline TextField causes problems in the mock environment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ export const reviewEntriesReducer = (
return {
...state,
words: state.words.map((w) =>
w.id === action.oldId
? { ...action.updatedWord, recorder: w.recorder }
: w
w.id === action.oldId ? { ...action.updatedWord } : w
),
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { enqueueSnackbar } from "notistack";
import { ReactElement, useEffect, useMemo, useState } from "react";
import { ReactElement, useEffect, useState } from "react";

import { getFrontierWords } from "backend";
import Recorder from "components/Pronunciations/Recorder";
import ReviewEntriesTable from "goals/ReviewEntries/ReviewEntriesComponent/ReviewEntriesTable";
import { ReviewEntriesWord } from "goals/ReviewEntries/ReviewEntriesComponent/ReviewEntriesTypes";

Expand All @@ -20,17 +18,14 @@ export default function ReviewEntriesComponent(
props: ReviewEntriesProps
): ReactElement {
const [loaded, setLoaded] = useState(false);
const recorder = useMemo(() => new Recorder(enqueueSnackbar), []);
const { updateAllWords, updateFrontierWord } = props;

useEffect(() => {
getFrontierWords().then((frontier) => {
updateAllWords(
frontier.map((w) => new ReviewEntriesWord(w, undefined, recorder))
);
updateAllWords(frontier.map((w) => new ReviewEntriesWord(w)));
setLoaded(true);
});
}, [updateAllWords, recorder]);
}, [updateAllWords]);

return loaded ? (
<ReviewEntriesTable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
Status,
Word,
} from "api/models";
import Recorder from "components/Pronunciations/Recorder";
import { newSense, newWord } from "types/word";
import { cleanDefinitions, cleanGlosses } from "utilities/wordUtilities";

Expand All @@ -30,9 +29,8 @@ export class ReviewEntriesWord {
noteText: string;
flag: Flag;
protected: boolean;
recorder?: Recorder;

constructor(word?: Word, analysisLang?: string, commonRecorder?: Recorder) {
constructor(word?: Word, analysisLang?: string) {
if (!word) {
word = newWord();
}
Expand All @@ -45,7 +43,6 @@ export class ReviewEntriesWord {
this.noteText = word.note.text;
this.flag = word.flag;
this.protected = word.accessibility === Status.Protected;
this.recorder = commonRecorder;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { newSemanticDomain } from "types/semanticDomain";
import { newDefinition, newFlag, newGloss } from "types/word";
import { Bcp47Code } from "types/writingSystem";

jest.mock("components/Pronunciations/PronunciationsComponent", () => "div");
jest.mock("i18next", () => {
const i18n = jest.requireActual("i18next");
return { ...i18n, t: (s: string) => s };
Expand Down
Loading