import { createSignal, onCleanup, createEffect } from "solid-js"; import { STATES, formatMsToTime } from "~/entrypoints/content/utils"; import micOn from "~/assets/mic-on.svg"; import { createDraggable } from "@neodrag/solid"; interface IRControls { pause: () => void; resume: () => void; stop: () => Promise; changeState: (newState: keyof typeof STATES) => void; getMicStatus: () => Promise; getClockStart: () => number; mute: () => void; unmute: () => void; getInitState: () => string; onRestart: () => void; getAudioPerm: () => number; } function RecordingControls({ pause, resume, stop, changeState, getMicStatus, getClockStart, mute, unmute, getInitState, onRestart, getAudioPerm, }: IRControls) { const { draggable } = createDraggable(); const initState = getInitState(); const [isLoading, setIsLoading] = createSignal(false); const [mic, setMic] = createSignal(false); const [recording, setRecording] = createSignal(initState === "recording"); const [time, setTime] = createSignal(0); const [timeStr, setTimeStr] = createSignal(formatMsToTime(0)); const onMsg = (e: any) => { if (e.data.type === "content:trigger-stop") { void onEnd(); } }; createEffect(() => { window.addEventListener("message", onMsg); const startDelta = getClockStart(); setTime(startDelta); setTimeStr(formatMsToTime(startDelta)); getMicStatus().then((status) => { setMic(status); }); }); const createTimer = () => { return setInterval(() => { const timeDelta = time() + 1000; if (timeDelta > 3 * 60 * 1000) { void onEnd(); return; } else { setTime((time) => { const newTime = time + 1000; const newTimeStr = formatMsToTime(newTime); setTimeStr(newTimeStr); return newTime; }); } }, 1000); }; let timer: ReturnType | null = initState === "recording" ? createTimer() : null; onCleanup(() => { if (timer) { clearInterval(timer); } window.removeEventListener("message", onMsg); }); const onPause = () => { if (timer) { clearInterval(timer); } timer = null; pause(); setRecording(false); }; const onRestartEv = () => { onPause(); onRestart(); }; const onResume = () => { timer = createTimer(); resume(); setRecording(true); }; const onEnd = async () => { setIsLoading(true); if (timer) { clearInterval(timer); } try { await stop(); } catch (e) { console.error(e); } setTimeout(() => { changeState(STATES.saving); }, 25); }; const toggleMic = async () => { if (mic()) { mute(); } else { unmute(); } const status = await getMicStatus(); setMic(status); }; let handleRef: HTMLDivElement; setTimeout(() => { handleRef.classList.remove("popupanimated"); }, 250); const audioPerm = getAudioPerm(); return (
(handleRef = el)} > {!isLoading() ? (
{recording() ? ( ) : ( )}
{timeStr()}
) : (
Loading video...
)}
); } export default RecordingControls;