Updated the writing exam to work based on exercises instead of just a single one

This commit is contained in:
Tiago Ribeiro
2023-04-17 13:03:48 +01:00
parent 5df816c73c
commit 207328dade
9 changed files with 359 additions and 74 deletions

View File

@@ -34,6 +34,7 @@
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-firebase-hooks": "^5.1.1", "react-firebase-hooks": "^5.1.1",
"react-lineto": "^3.3.0", "react-lineto": "^3.3.0",
"react-media-recorder": "^1.6.6",
"react-player": "^2.12.0", "react-player": "^2.12.0",
"react-string-replace": "^1.1.0", "react-string-replace": "^1.1.0",
"react-toastify": "^9.1.2", "react-toastify": "^9.1.2",

View File

@@ -0,0 +1,83 @@
import {errorButtonStyle, infoButtonStyle} from "@/constants/buttonStyles";
import {WritingExercise} from "@/interfaces/exam";
import {mdiArrowLeft, mdiArrowRight} from "@mdi/js";
import Icon from "@mdi/react";
import clsx from "clsx";
import {CommonProps} from ".";
import {Fragment, useEffect, useState} from "react";
import {toast} from "react-toastify";
export default function WriteBlanks({id, prompt, info, wordCounter, onNext, onBack}: WritingExercise & CommonProps) {
const [inputText, setInputText] = useState("");
const [isSubmitEnabled, setIsSubmitEnabled] = useState(false);
useEffect(() => {
const words = inputText.split(" ").filter((x) => x !== "");
if (wordCounter.type === "min") {
setIsSubmitEnabled(wordCounter.limit <= words.length);
} else {
setIsSubmitEnabled(true);
if (wordCounter.limit < words.length) {
toast.warning(`You have reached your word limit of ${wordCounter.limit} words!`, {toastId: "word-limit"});
setInputText(words.slice(0, words.length - 1).join(" "));
}
}
}, [inputText, wordCounter]);
return (
<div className="flex flex-col h-full w-2/3 items-center justify-center gap-8">
<div className="flex flex-col max-w-2xl gap-2">
<span>{info}</span>
<span className="font-bold ml-8">
{prompt.split("\\n").map((line, index) => (
<Fragment key={index}>
<span>{line}</span>
<br />
</Fragment>
))}
</span>
<span>
You should write {wordCounter.type === "min" ? "at least" : "at most"} {wordCounter.limit} words.
</span>
</div>
<textarea
className="w-full h-1/3 cursor-text p-2 input input-bordered bg-white"
onChange={(e) => setInputText(e.target.value)}
value={inputText}
placeholder="Write your text here..."
/>
<div className="self-end flex gap-8">
<button className={clsx("btn btn-wide gap-4 relative text-white", errorButtonStyle)} onClick={onBack}>
<div className="absolute left-4">
<Icon path={mdiArrowLeft} color="white" size={1} />
</div>
Back
</button>
{!isSubmitEnabled && (
<div className="tooltip" data-tip={`You have not yet reached your minimum word count of ${wordCounter.limit} words!`}>
<button
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
disabled={!isSubmitEnabled}
onClick={() => onNext({id, solutions: [inputText], score: {correct: 1, total: 1}})}>
Next
</button>
</div>
)}
{isSubmitEnabled && (
<button
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
disabled={!isSubmitEnabled}
onClick={() => onNext({id, solutions: [inputText], score: {correct: 1, total: 1}})}>
Next
<div className="absolute right-4">
<Icon path={mdiArrowRight} color="white" size={1} />
</div>
</button>
)}
</div>
</div>
);
}

View File

@@ -1,8 +1,17 @@
import {Exercise, FillBlanksExercise, MatchSentencesExercise, MultipleChoiceExercise, UserSolution, WriteBlanksExercise} from "@/interfaces/exam"; import {
Exercise,
FillBlanksExercise,
MatchSentencesExercise,
MultipleChoiceExercise,
UserSolution,
WriteBlanksExercise,
WritingExercise,
} from "@/interfaces/exam";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import FillBlanks from "./FillBlanks"; import FillBlanks from "./FillBlanks";
import MultipleChoice from "./MultipleChoice"; import MultipleChoice from "./MultipleChoice";
import WriteBlanks from "./WriteBlanks"; import WriteBlanks from "./WriteBlanks";
import Writing from "./Writing";
const MatchSentences = dynamic(() => import("@/components/Exercises/MatchSentences"), {ssr: false}); const MatchSentences = dynamic(() => import("@/components/Exercises/MatchSentences"), {ssr: false});
@@ -21,5 +30,7 @@ export const renderExercise = (exercise: Exercise, onNext: (userSolutions: UserS
return <MultipleChoice {...(exercise as MultipleChoiceExercise)} onNext={onNext} onBack={onBack} />; return <MultipleChoice {...(exercise as MultipleChoiceExercise)} onNext={onNext} onBack={onBack} />;
case "writeBlanks": case "writeBlanks":
return <WriteBlanks {...(exercise as WriteBlanksExercise)} onNext={onNext} onBack={onBack} />; return <WriteBlanks {...(exercise as WriteBlanksExercise)} onNext={onNext} onBack={onBack} />;
case "writing":
return <Writing {...(exercise as WritingExercise)} onNext={onNext} onBack={onBack} />;
} }
}; };

View File

@@ -39,9 +39,9 @@ export default function Listening({exam, showSolutions = false, onFinish}: Props
} }
if (solution) { if (solution) {
onFinish([...userSolutions.filter((x) => x.id !== solution.id), solution].map((x) => ({...x, module: "listening"}))); onFinish([...userSolutions.filter((x) => x.id !== solution.id), solution].map((x) => ({...x, module: "listening", exam: exam.id})));
} else { } else {
onFinish(userSolutions.map((x) => ({...x, module: "listening"}))); onFinish(userSolutions.map((x) => ({...x, module: "listening", exam: exam.id})));
} }
}; };

View File

@@ -99,9 +99,9 @@ export default function Reading({exam, showSolutions = false, onFinish}: Props)
} }
if (solution) { if (solution) {
onFinish([...userSolutions.filter((x) => x.id !== solution.id), solution].map((x) => ({...x, module: "reading"}))); onFinish([...userSolutions.filter((x) => x.id !== solution.id), solution].map((x) => ({...x, module: "reading", exam: exam.id})));
} else { } else {
onFinish(userSolutions.map((x) => ({...x, module: "reading"}))); onFinish(userSolutions.map((x) => ({...x, module: "reading", exam: exam.id})));
} }
}; };

View File

@@ -1,5 +1,9 @@
import {renderExercise} from "@/components/Exercises";
import {renderSolution} from "@/components/Solutions";
import {infoButtonStyle} from "@/constants/buttonStyles"; import {infoButtonStyle} from "@/constants/buttonStyles";
import {UserSolution, WritingExam} from "@/interfaces/exam"; import {UserSolution, WritingExam} from "@/interfaces/exam";
import {mdiArrowRight} from "@mdi/js";
import Icon from "@mdi/react";
import clsx from "clsx"; import clsx from "clsx";
import {Fragment, useEffect, useState} from "react"; import {Fragment, useEffect, useState} from "react";
import {toast} from "react-toastify"; import {toast} from "react-toastify";
@@ -11,9 +15,9 @@ interface Props {
} }
export default function Writing({exam, showSolutions = false, onFinish}: Props) { export default function Writing({exam, showSolutions = false, onFinish}: Props) {
const [inputText, setInputText] = useState(""); const [exerciseIndex, setExerciseIndex] = useState(0);
const [isSubmitEnabled, setIsSubmitEnabled] = useState(false);
const [timer, setTimer] = useState<number>(); const [timer, setTimer] = useState<number>();
const [userSolutions, setUserSolutions] = useState<UserSolution[]>([]);
useEffect(() => { useEffect(() => {
setTimer(exam.minTimer * 60); setTimer(exam.minTimer * 60);
@@ -24,22 +28,29 @@ export default function Writing({exam, showSolutions = false, onFinish}: Props)
}; };
}, [exam.minTimer]); }, [exam.minTimer]);
useEffect(() => { const nextExercise = (solution?: UserSolution) => {
const words = inputText.split(" ").filter((x) => x !== ""); if (solution) {
const {wordCounter} = exam.text; setUserSolutions((prev) => [...prev.filter((x) => x.id !== solution.id), solution]);
if (wordCounter.type === "min") {
setIsSubmitEnabled(wordCounter.limit <= words.length);
} else {
setIsSubmitEnabled(true);
if (wordCounter.limit < words.length) {
toast.warning(`You have reached your word limit of ${wordCounter.limit} words!`, {toastId: "word-limit"});
setInputText(words.slice(0, words.length - 1).join(" "));
}
} }
}, [inputText, exam]);
if (exerciseIndex + 1 < exam.exercises.length) {
setExerciseIndex((prev) => prev + 1);
return;
}
if (solution) {
onFinish([...userSolutions.filter((x) => x.id !== solution.id), solution].map((x) => ({...x, module: "writing", exam: exam.id})));
} else {
onFinish(userSolutions.map((x) => ({...x, module: "writing", exam: exam.id})));
}
};
const previousExercise = () => {
setExerciseIndex((prev) => prev - 1);
};
return ( return (
<div className="h-full w-full flex flex-col items-center justify-center gap-8 relative"> <div className="w-full h-full relative flex flex-col gap-8 items-center justify-center p-8 px-16 overflow-hidden">
{timer && ( {timer && (
<div className="absolute w-24 top-8 text-center right-8 font-semibold text-lg border-ielts-writing border-2 p-2 rounded-xl bg-ielts-writing-transparent text-white"> <div className="absolute w-24 top-8 text-center right-8 font-semibold text-lg border-ielts-writing border-2 p-2 rounded-xl bg-ielts-writing-transparent text-white">
{Math.floor(timer / 60) < 10 ? "0" : ""} {Math.floor(timer / 60) < 10 ? "0" : ""}
@@ -47,46 +58,22 @@ export default function Writing({exam, showSolutions = false, onFinish}: Props)
{timer % 60} {timer % 60}
</div> </div>
)} )}
<div className="flex flex-col max-w-2xl gap-2"> {exerciseIndex > -1 &&
<span>{exam.text.info}</span> exerciseIndex < exam.exercises.length &&
<span className="font-bold ml-8"> !showSolutions &&
{exam.text.prompt.split("\\n").map((line, index) => ( renderExercise(exam.exercises[exerciseIndex], nextExercise, previousExercise)}
<Fragment key={index}> {exerciseIndex > -1 &&
<span>{line}</span> exerciseIndex < exam.exercises.length &&
<br /> showSolutions &&
</Fragment> renderSolution(exam.exercises[exerciseIndex], nextExercise, previousExercise)}
))} {exerciseIndex === -1 && (
</span> <button className={clsx("btn btn-wide gap-4 relative text-white self-end", infoButtonStyle)} onClick={() => nextExercise()}>
<span> Next
You should write {exam.text.wordCounter.type === "min" ? "at least" : "at most"} {exam.text.wordCounter.limit} words. <div className="absolute right-4">
</span> <Icon path={mdiArrowRight} color="white" size={1} />
</div>
<textarea
className="w-1/2 h-1/3 cursor-text p-2 input input-bordered bg-white"
onChange={(e) => setInputText(e.target.value)}
value={inputText}
placeholder="Write your text here..."
/>
<div className="w-1/2 flex justify-end">
{!isSubmitEnabled && (
<div className="tooltip" data-tip={`You have not yet reached your minimum word count of ${exam.text.wordCounter.limit} words!`}>
<button
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
disabled={!isSubmitEnabled}
onClick={() => onFinish([{id: exam.id, solutions: [inputText.trim()], score: {correct: 0, total: 1}}])}>
Next
</button>
</div> </div>
)} </button>
{isSubmitEnabled && ( )}
<button
className={clsx("btn btn-wide gap-4 relative text-white", infoButtonStyle)}
disabled={!isSubmitEnabled}
onClick={() => onFinish([{id: exam.id, solutions: [inputText.trim()], score: {correct: 0, total: 1}}])}>
Next
</button>
)}
</div>
</div> </div>
); );
} }

View File

@@ -27,6 +27,7 @@ export interface ListeningExam {
export interface UserSolution { export interface UserSolution {
solutions: any[]; solutions: any[];
module?: Module; module?: Module;
exam?: string;
score: { score: {
correct: number; correct: number;
total: number; total: number;
@@ -37,13 +38,8 @@ export interface UserSolution {
export interface WritingExam { export interface WritingExam {
module: "writing"; module: "writing";
id: string; id: string;
text: {
info: string; //* The information about the task, like the amount of time they should spend on it
prompt: string; //* The context given to the user containing what they should write about
wordCounter: WordCounter; //* The minimum or maximum amount of words that should be written
};
minTimer: number;
exercises: Exercise[]; exercises: Exercise[];
minTimer: number;
} }
interface WordCounter { interface WordCounter {
@@ -51,7 +47,15 @@ interface WordCounter {
limit: number; limit: number;
} }
export type Exercise = FillBlanksExercise | MatchSentencesExercise | MultipleChoiceExercise | WriteBlanksExercise; export type Exercise = FillBlanksExercise | MatchSentencesExercise | MultipleChoiceExercise | WriteBlanksExercise | WritingExercise;
export interface WritingExercise {
id: string;
type: "writing";
info: string; //* The information about the task, like the amount of time they should spend on it
prompt: string; //* The context given to the user containing what they should write about
wordCounter: WordCounter; //* The minimum or maximum amount of words that should be written
}
export interface FillBlanksExercise { export interface FillBlanksExercise {
prompt: string; // *EXAMPLE: "Complete the summary below. Click a blank to select the corresponding word for it." prompt: string; // *EXAMPLE: "Complete the summary below. Click a blank to select the corresponding word for it."

9
src/utils/string.ts Normal file
View File

@@ -0,0 +1,9 @@
function convertCamelCaseToReadable(camelCaseString: string): string {
// Split the string using regex to match the capital letters
const wordsArray = camelCaseString.split(/(?=[A-Z])/);
// Capitalize the first letter of each word and join the words with a space
const readableString = wordsArray.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
return readableString;
}

206
yarn.lock
View File

@@ -2,6 +2,13 @@
# yarn lockfile v1 # yarn lockfile v1
"@babel/runtime@^7.18.9", "@babel/runtime@^7.20.6", "@babel/runtime@^7.21.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
version "7.21.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
dependencies:
regenerator-runtime "^0.13.11"
"@babel/runtime@^7.20.7": "@babel/runtime@^7.20.7":
version "7.20.13" version "7.20.13"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.13.tgz#7055ab8a7cff2b8f6058bf6ae45ff84ad2aded4b" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.13.tgz#7055ab8a7cff2b8f6058bf6ae45ff84ad2aded4b"
@@ -9,13 +16,6 @@
dependencies: dependencies:
regenerator-runtime "^0.13.11" regenerator-runtime "^0.13.11"
"@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
version "7.21.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
dependencies:
regenerator-runtime "^0.13.11"
"@emotion/is-prop-valid@^0.8.2": "@emotion/is-prop-valid@^0.8.2":
version "0.8.8" version "0.8.8"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
@@ -1117,6 +1117,14 @@ asynckit@^0.4.0:
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
automation-events@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/automation-events/-/automation-events-5.0.2.tgz#c792ce2b1e43481019153f37dcb0d18c68642425"
integrity sha512-8mfgjeI22tlKeaGY8y0bDt93IIUJhQKR/ISTsnhhFkpAzCirPdQ/Rmfp3xakCTmIihLgDuIWcWygHWozYKVGyQ==
dependencies:
"@babel/runtime" "^7.21.0"
tslib "^2.5.0"
autoprefixer@^10.4.13: autoprefixer@^10.4.13:
version "10.4.13" version "10.4.13"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8"
@@ -1185,6 +1193,16 @@ braces@^3.0.2, braces@~3.0.2:
dependencies: dependencies:
fill-range "^7.0.1" fill-range "^7.0.1"
broker-factory@^3.0.75:
version "3.0.75"
resolved "https://registry.yarnpkg.com/broker-factory/-/broker-factory-3.0.75.tgz#0170602bcfe8965368b08231c75dc8c093572eed"
integrity sha512-VMC2GBMaoKXdVPC0yH/Z1NbDieYRuKlGPT6PbrrReDwvHSZH2Cl5dJVO3tPTkA9Q+xXOmnRYgcjNktZD/Oz21w==
dependencies:
"@babel/runtime" "^7.21.0"
fast-unique-numbers "^7.0.2"
tslib "^2.5.0"
worker-factory "^6.0.76"
browserslist@^4.21.4: browserslist@^4.21.4:
version "4.21.5" version "4.21.5"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
@@ -1310,6 +1328,16 @@ combined-stream@^1.0.8:
dependencies: dependencies:
delayed-stream "~1.0.0" delayed-stream "~1.0.0"
compilerr@^10.0.2:
version "10.0.2"
resolved "https://registry.yarnpkg.com/compilerr/-/compilerr-10.0.2.tgz#d6ecff912304634ebef232f0d660a724187b5f03"
integrity sha512-CFwUXxJ9OuWsSvnLSbefxi+GLsZ0YnuJh40ry5QdmZ1FWK59OG+QB8XSj6t7Kq+/c5DSS7en+cML6GlzHKH58A==
dependencies:
"@babel/runtime" "^7.21.0"
dashify "^2.0.0"
indefinite-article "0.0.2"
tslib "^2.5.0"
concat-map@0.0.1: concat-map@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -1362,6 +1390,11 @@ damerau-levenshtein@^1.0.8:
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
dashify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/dashify/-/dashify-2.0.0.tgz#fff270ca2868ca427fee571de35691d6e437a648"
integrity sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==
debug@^3.2.7: debug@^3.2.7:
version "3.2.7" version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
@@ -1808,6 +1841,48 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
extendable-media-recorder-wav-encoder-broker@^7.0.77:
version "7.0.77"
resolved "https://registry.yarnpkg.com/extendable-media-recorder-wav-encoder-broker/-/extendable-media-recorder-wav-encoder-broker-7.0.77.tgz#a71af2362a5d861d4a52212b0fca57b8082ac59a"
integrity sha512-HNUcsUMtKw8hUx1pHM/78+joa3L7FpCh+R3jX9RRuSrHMUw/ldq29wi/evBs4lMoasyMZLHD3yI1Phz0hYH7pg==
dependencies:
"@babel/runtime" "^7.21.0"
broker-factory "^3.0.75"
extendable-media-recorder-wav-encoder-worker "^8.0.76"
tslib "^2.5.0"
extendable-media-recorder-wav-encoder-worker@^8.0.76:
version "8.0.76"
resolved "https://registry.yarnpkg.com/extendable-media-recorder-wav-encoder-worker/-/extendable-media-recorder-wav-encoder-worker-8.0.76.tgz#645a997eb0dea0c7841930dc4ec5641c41648548"
integrity sha512-m/pafu/XodKM05r3wkdY6D+gvprD6VCe1rLKnmF/Ooj4VGQ3DglsOhxWmEXRHVtzFWHIxIpjq6Z14VYaj1sXUg==
dependencies:
"@babel/runtime" "^7.21.0"
tslib "^2.5.0"
worker-factory "^6.0.76"
extendable-media-recorder-wav-encoder@^7.0.68:
version "7.0.85"
resolved "https://registry.yarnpkg.com/extendable-media-recorder-wav-encoder/-/extendable-media-recorder-wav-encoder-7.0.85.tgz#2c0cd70a4ad88e5ac34fd2eb379560290da87cb1"
integrity sha512-M96Y6twJ/OBordRltfyf8Kl2P2C0e176ogVTpGYquHApEyRnGpnm6LMmNqiRkQC8me0WOOhKLVvKCGmEF3lmvQ==
dependencies:
"@babel/runtime" "^7.21.0"
extendable-media-recorder-wav-encoder-broker "^7.0.77"
extendable-media-recorder-wav-encoder-worker "^8.0.76"
tslib "^2.5.0"
extendable-media-recorder@^6.6.5:
version "6.6.10"
resolved "https://registry.yarnpkg.com/extendable-media-recorder/-/extendable-media-recorder-6.6.10.tgz#44f3ac8f15441e8499ea9f311761dbbbc1561161"
integrity sha512-gnSmLqDFq40ZdbGfuarnMLNqYPLCPpPr0p21V+g67wG4Pv2oCc/ga8sfsZrEM5GywEi7FcpyRm3z99JWZ/0aPw==
dependencies:
"@babel/runtime" "^7.18.9"
media-encoder-host "^8.0.76"
multi-buffer-data-view "^3.0.20"
recorder-audio-worklet "^5.1.26"
standardized-audio-context "^25.3.29"
subscribable-things "^2.1.6"
tslib "^2.4.0"
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3" version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
@@ -1834,6 +1909,14 @@ fast-levenshtein@^2.0.6:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fast-unique-numbers@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/fast-unique-numbers/-/fast-unique-numbers-7.0.2.tgz#d66d7118204461be6cb8d0802a91a3f7e40c6130"
integrity sha512-xnqpsnu889bHbq5cbDMwCJ2BPf6kjFPMu+RHfqKvisRxeEbTOVxY5aW/ZNsZ/r8OlwatxmjdFEVQog2xAhLkvg==
dependencies:
"@babel/runtime" "^7.21.0"
tslib "^2.5.0"
fastparse@^1.1.2: fastparse@^1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
@@ -2195,6 +2278,11 @@ imurmurhash@^0.1.4:
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
indefinite-article@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/indefinite-article/-/indefinite-article-0.0.2.tgz#4bc855257066cfab61ea68beba75d100d6e2506b"
integrity sha512-Au/2XzRkvxq2J6w5uvSSbBKPZ5kzINx5F2wb0SF8xpRL8BP9Lav81TnRbfPp6p+SYjYxwaaLn4EUwI3/MmYKSw==
inflight@^1.0.4: inflight@^1.0.4:
version "1.0.6" version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@@ -2549,6 +2637,37 @@ lru-cache@^6.0.0:
dependencies: dependencies:
yallist "^4.0.0" yallist "^4.0.0"
media-encoder-host-broker@^7.0.78:
version "7.0.78"
resolved "https://registry.yarnpkg.com/media-encoder-host-broker/-/media-encoder-host-broker-7.0.78.tgz#057844981fac6592e4b14169fd7478e3b710b117"
integrity sha512-5IZEZwN4qyCymkP6FCELS6rRCE2xhNFiE3FWr+8R3ySRn1iwPWd/U/YFB4PdvjqFw3MtQ9rHFErfc/YjUf8j9g==
dependencies:
"@babel/runtime" "^7.21.0"
broker-factory "^3.0.75"
fast-unique-numbers "^7.0.2"
media-encoder-host-worker "^9.1.0"
tslib "^2.5.0"
media-encoder-host-worker@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/media-encoder-host-worker/-/media-encoder-host-worker-9.1.0.tgz#2af9f1e57d0569e8691cec768a0829c3cf200349"
integrity sha512-dVvb65RH/5Yt5PBxBVGw+BcCFkq8A15/fw3HxEKugtaFJocTcwQsS1IeDUuf1i831Fk/FuCipnXFz8VsGRCZyg==
dependencies:
"@babel/runtime" "^7.21.0"
extendable-media-recorder-wav-encoder-broker "^7.0.77"
tslib "^2.5.0"
worker-factory "^6.0.76"
media-encoder-host@^8.0.76:
version "8.0.88"
resolved "https://registry.yarnpkg.com/media-encoder-host/-/media-encoder-host-8.0.88.tgz#53a44630f737c8fd5b46dd7d9f3bfcde51fced09"
integrity sha512-15pWY8GFLsm3w01JuSQdEIkCh1+KUKqNQg5F6s5SXhAwbj0DuTceFbyuqWFMq+XzV8zZrPt8LtYAAj5ld5IEOw==
dependencies:
"@babel/runtime" "^7.21.0"
media-encoder-host-broker "^7.0.78"
media-encoder-host-worker "^9.1.0"
tslib "^2.5.0"
memoize-one@^5.1.1: memoize-one@^5.1.1:
version "5.2.1" version "5.2.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
@@ -2601,6 +2720,14 @@ ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
multi-buffer-data-view@^3.0.20:
version "3.0.24"
resolved "https://registry.yarnpkg.com/multi-buffer-data-view/-/multi-buffer-data-view-3.0.24.tgz#5c9be6445812f6ececc901e6e0eb57ef02312aea"
integrity sha512-jm7Ycplx37ExXyQmqhwl7zfQmAj81y5LLzVx0XyWea4omP9W/xJhLEHs/5b+WojGyYSRt8BHiXZVcYzu68Ma0Q==
dependencies:
"@babel/runtime" "^7.20.6"
tslib "^2.4.1"
nanoid@^3.3.4: nanoid@^3.3.4:
version "3.3.4" version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
@@ -3023,6 +3150,14 @@ react-lineto@^3.3.0:
prop-types "15.7.2" prop-types "15.7.2"
react "17.0.2" react "17.0.2"
react-media-recorder@^1.6.6:
version "1.6.6"
resolved "https://registry.yarnpkg.com/react-media-recorder/-/react-media-recorder-1.6.6.tgz#4067c54e3f11c56f33a7df9daa1650a7aa4305f1"
integrity sha512-VdC4bUINMWJyqOAHw1DaZ8HZhdCyVBK85zJ4cHMo9tsrekui3wq5ZxNtBmNe6nbAFQBTNj/pRnLEsiVrCW+TNQ==
dependencies:
extendable-media-recorder "^6.6.5"
extendable-media-recorder-wav-encoder "^7.0.68"
react-player@^2.12.0: react-player@^2.12.0:
version "2.12.0" version "2.12.0"
resolved "https://registry.yarnpkg.com/react-player/-/react-player-2.12.0.tgz#2fc05dbfec234c829292fbca563b544064bd14f0" resolved "https://registry.yarnpkg.com/react-player/-/react-player-2.12.0.tgz#2fc05dbfec234c829292fbca563b544064bd14f0"
@@ -3085,6 +3220,28 @@ readdirp@~3.6.0:
dependencies: dependencies:
picomatch "^2.2.1" picomatch "^2.2.1"
recorder-audio-worklet-processor@^4.2.21:
version "4.2.21"
resolved "https://registry.yarnpkg.com/recorder-audio-worklet-processor/-/recorder-audio-worklet-processor-4.2.21.tgz#24129ffda37084543b9f639ab1367dd2618b4881"
integrity sha512-oiiS2sp6eMxkvjt13yetSYUJvnAxBZk60mIxz0Vf/2lDWa/4svCyMLHIDzYKbHahkISd0UYyqLS9dI7xDlUOCA==
dependencies:
"@babel/runtime" "^7.21.0"
tslib "^2.5.0"
recorder-audio-worklet@^5.1.26:
version "5.1.39"
resolved "https://registry.yarnpkg.com/recorder-audio-worklet/-/recorder-audio-worklet-5.1.39.tgz#7bbffd2d4e7028e0954c68350e50177e05acaa7f"
integrity sha512-w/RazoBwZnkFnEPRsJYNThOHznLQC98/IzWRrutpJQVvCcL0nbLsVSLDaRrnrqVpRUI11VgiXRh30HaHiSdVhQ==
dependencies:
"@babel/runtime" "^7.21.0"
broker-factory "^3.0.75"
fast-unique-numbers "^7.0.2"
recorder-audio-worklet-processor "^4.2.21"
standardized-audio-context "^25.3.41"
subscribable-things "^2.1.14"
tslib "^2.5.0"
worker-factory "^6.0.76"
regenerator-runtime@^0.13.11: regenerator-runtime@^0.13.11:
version "0.13.11" version "0.13.11"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
@@ -3151,6 +3308,11 @@ run-parallel@^1.1.9:
dependencies: dependencies:
queue-microtask "^1.2.2" queue-microtask "^1.2.2"
rxjs-interop@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/rxjs-interop/-/rxjs-interop-2.0.0.tgz#dca61a93789a8304f653d2e159e377cefa348ec7"
integrity sha512-ASEq9atUw7lualXB+knvgtvwkCEvGWV2gDD/8qnASzBkzEARZck9JAyxmY8OS6Nc1pCPEgDTKNcx+YqqYfzArw==
safe-buffer@>=5.1.0: safe-buffer@>=5.1.0:
version "5.2.1" version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
@@ -3227,6 +3389,15 @@ source-map-js@^1.0.2:
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
standardized-audio-context@^25.3.29, standardized-audio-context@^25.3.41:
version "25.3.41"
resolved "https://registry.yarnpkg.com/standardized-audio-context/-/standardized-audio-context-25.3.41.tgz#42689e0653698bba13705e220b78fe1f9cf458da"
integrity sha512-NCKY1kLCGN37dnCCIG4NX1LHWRgONvIU6u6GS3nzhMM9CV/M+GR48uIeojjeJBSICfWXfQ+t2N1MTdsgJz3wlA==
dependencies:
"@babel/runtime" "^7.21.0"
automation-events "^5.0.2"
tslib "^2.5.0"
stop-iteration-iterator@^1.0.0: stop-iteration-iterator@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4"
@@ -3299,6 +3470,15 @@ styled-jsx@5.1.1:
dependencies: dependencies:
client-only "0.0.1" client-only "0.0.1"
subscribable-things@^2.1.14, subscribable-things@^2.1.6:
version "2.1.14"
resolved "https://registry.yarnpkg.com/subscribable-things/-/subscribable-things-2.1.14.tgz#b281471f4d934d41452561ef44e671361efaf70c"
integrity sha512-+0e6wGpFVa7snrwzY/xwiiQhlpBglvPAhsYK9EhFAcboP5z0eN1W3CQoROYyeY3psiCbwcleb9vaXasKAcvISw==
dependencies:
"@babel/runtime" "^7.21.0"
rxjs-interop "^2.0.0"
tslib "^2.5.0"
supports-color@^7.1.0: supports-color@^7.1.0:
version "7.2.0" version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
@@ -3400,7 +3580,7 @@ tslib@^1.8.1:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0: tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.5.0:
version "2.5.0" version "2.5.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
@@ -3556,6 +3736,16 @@ word-wrap@^1.2.3:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
worker-factory@^6.0.76:
version "6.0.76"
resolved "https://registry.yarnpkg.com/worker-factory/-/worker-factory-6.0.76.tgz#78f86a300b959b1b5ebe010f042aae22e72346e4"
integrity sha512-W1iBNPmE9p0asU4aFmYJYCnMxhkvk4qlKc660GlHxWgmflY64NxxTbmKqipu4K5p9LiKKPjqXfcQme6153BZEQ==
dependencies:
"@babel/runtime" "^7.21.0"
compilerr "^10.0.2"
fast-unique-numbers "^7.0.2"
tslib "^2.5.0"
wrap-ansi@^7.0.0: wrap-ansi@^7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"