import type { AppRouter } from "@thorium/.server/init/router"; import SineWave, { getSinePoint } from "@thorium/ui/SineWave"; import type { inferProcedureInput } from "@thorium/utils/live-query/.server/types"; import { useRef, useState } from "react"; export function WavesDecoder({ waves, updateMessageDecoding, }: { waves: { amplitude: number; frequency: number; phase: number; requiredAmplitude: number; requiredFrequency: number; requiredPhase: number; }[]; updateMessageDecoding: ( decoding: Extract< inferProcedureInput["decoding"], { type: "waves" } >, ) => Promise; }) { const waveWidthPercent = 0.25; const waveAnimationRef = useRef(0); const [selectedWaveIndex] = useState(0); const selectedWave = waves[selectedWaveIndex]; return (
{ const requiredWaves = waves.map( ({ requiredAmplitude, requiredFrequency, requiredPhase }) => ({ amplitude: requiredAmplitude, frequency: requiredFrequency, phase: requiredPhase, }), ); ctx.beginPath(); for ( let i = -10 + waveAnimationRef.current; i < width * window.devicePixelRatio * waveWidthPercent + 10 + waveAnimationRef.current; i += 1 ) { ctx.lineTo(i / 2, getSinePoint(i, requiredWaves) * height + height / 2); } ctx.lineWidth = 1; ctx.strokeStyle = "#ffff00"; ctx.stroke(); waveAnimationRef.current += 10; if (waveAnimationRef.current > width * 2) { waveAnimationRef.current = -width * 2 * waveWidthPercent; } }} />
Frequency:
{ updateMessageDecoding({ type: "waves", waves: waves.map((w, i) => i === selectedWaveIndex ? { ...w, frequency: Number(e.currentTarget.value) } : w, ), }); }} />
Amplitude:
{ updateMessageDecoding({ type: "waves", waves: waves.map((w, i) => i === selectedWaveIndex ? { ...w, amplitude: Number(e.currentTarget.value) } : w, ), }); }} />
Phase:
{ updateMessageDecoding({ type: "waves", waves: waves.map((w, i) => i === selectedWaveIndex ? { ...w, phase: Number(e.currentTarget.value) } : w, ), }); }} />
); }