link-stack/apps/metamigo-frontend/components/voice/voicelines/MicInput.tsx

150 lines
4 KiB
TypeScript
Raw Normal View History

2023-02-13 12:41:30 +00:00
import { useInput } from "react-admin";
import React, { useState } from "react";
import dynamic from "next/dynamic";
import MicIcon from "@material-ui/icons/Mic";
import StopIcon from "@material-ui/icons/Stop";
import Button from "@material-ui/core/Button";
import { makeStyles, useTheme } from "@material-ui/core/styles";
import AudioPlayer from "material-ui-audio-player";
import { useStopwatch } from "react-timer-hook";
import style from "./MicInput.module.css";
//import type { ReactMicProps } from "react-mic";
2023-02-13 12:41:30 +00:00
2023-03-14 17:40:24 +00:00
const ReactMic = dynamic<any>(
2023-02-13 12:41:30 +00:00
// eslint-disable-next-line promise/prefer-await-to-then
2023-03-14 17:40:24 +00:00
() => {
throw new Error(
"MIC INPUT FEATURE IS DISABLED"
); /*return import("react-mic").then((mod) => mod.ReactMic);*/
},
2023-02-13 12:41:30 +00:00
{ ssr: false }
);
2023-03-14 17:40:24 +00:00
const blobToDataUri = (blob: Blob) => {
2023-02-13 12:41:30 +00:00
const reader = new FileReader();
reader.readAsDataURL(blob);
return new Promise((resolve) => {
reader.onloadend = () => {
resolve(reader.result);
};
});
};
2023-03-14 17:40:24 +00:00
const dataUriToObj = (dataUri: string) => {
2023-02-13 12:41:30 +00:00
const [prefix, base64] = dataUri.split(",");
const mime = prefix.slice(5, prefix.indexOf(";"));
2023-03-14 17:40:24 +00:00
const result: any = {};
2023-02-13 12:41:30 +00:00
result[mime] = base64;
return result;
};
2023-03-14 17:40:24 +00:00
const blobToResult = async (blob: Blob) => {
const result = dataUriToObj((await blobToDataUri(blob)) as string);
2023-02-13 12:41:30 +00:00
return result;
};
2023-03-14 17:40:24 +00:00
const resultToDataUri = (result: Record<string, any>): string => {
2023-02-13 12:41:30 +00:00
if (!result || !result["audio/webm"]) return "";
const base64 = result["audio/webm"];
const r = `data:audio/webm;base64,${base64}`;
return r;
};
2023-03-14 17:40:24 +00:00
const MicInput = (props: any) => {
2023-02-13 12:41:30 +00:00
const { seconds, minutes, hours, start, reset, pause } = useStopwatch();
const theme = useTheme();
const {
2023-03-14 17:40:24 +00:00
field: { value, onChange },
2023-02-13 12:41:30 +00:00
} = useInput(props);
let [record, setRecorder] = useState({ record: false });
const decodedValue = resultToDataUri(value);
const startRecording = () => {
setRecorder({ record: true });
reset();
start();
};
const stopRecording = () => {
setRecorder({ record: false });
pause();
};
2023-03-14 17:40:24 +00:00
async function onData(recordedBlob: any) {}
2023-02-13 12:41:30 +00:00
2023-03-14 17:40:24 +00:00
async function onStop(recordedBlob: any) {
2023-02-13 12:41:30 +00:00
const result = await blobToResult(recordedBlob.blob);
onChange(result);
}
const isRecording = record.record;
const canPlay = !isRecording && decodedValue;
2023-03-14 17:40:24 +00:00
const duration = `${hours.toString().padStart(2, "0")}:${minutes
2023-02-13 12:41:30 +00:00
.toString()
.padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
const useStyles = makeStyles((theme) => {
return {
volumeIcon: {
display: "none",
},
mainSlider: {
display: "none",
},
};
});
return (
<div className="MuiFormControl-marginDense RaFormInput-input-40">
<div className={style.content}>
<div className={style.voiceWaveWrapper}>
<ReactMic
record={record.record}
className={isRecording ? style.visible : style.hidden}
onStop={onStop}
onData={onData}
strokeColor={theme.palette.primary.main}
backgroundColor="white"
mimeType="audio/webm"
visualSetting="frequencyBars"
/>
</div>
<div>{isRecording ? <p>Recording... {duration}</p> : ""}</div>
<div className={style.buttonWrapper}>
{isRecording ? (
<Button variant="contained" color="primary" onClick={stopRecording}>
<StopIcon />
Stop
</Button>
) : (
<Button
variant="contained"
color="primary"
onClick={startRecording}
style={{ marginRight: "20px" }}
>
<MicIcon />
Record
</Button>
)}
</div>
<div className={style.playerWrapper}>
{canPlay && (
<AudioPlayer
elevation={0}
src={decodedValue}
variation="secondary"
volume={false}
useStyles={useStyles}
/>
)}
</div>
</div>
</div>
);
};
export default MicInput;