Loading packages/client/src/components/Settings/AudioSettings.tsx +92 −4 Original line number Diff line number Diff line import { useCallback, useEffect, useState } from "react"; import { useRef } from "react"; import { Slider } from "@heroui/react"; import { CanvasLib } from "@sc07-canvas/lib/canvas"; import { useCallback, useEffect, useRef, useState } from "react"; import useSound from "use-sound"; import { useAppContext } from "@/contexts/AppContext"; import { useAudio } from "@/contexts/AudioContext"; import { CanvasCore } from "@/lib/canvas"; import network from "../../lib/network"; import African1 from "../../sounds/African1.mp3"; Loading @@ -20,8 +23,11 @@ const _ = (v: boolean) => (v ? "enable" : "disable"); export const AudioSettings = () => { const { state, dispatch } = useAudio(); const { config } = useAppContext<true>(); const coffee2Ref = useRef<(() => void) | null>(null); const delayedAvailableSoundRef = useRef<number | undefined>(undefined); const earlyAvailableSoundPlayedRef = useRef(false); const [Coffee1Sound] = useSound(Coffee1, { volume: 0.5 }); Loading @@ -44,6 +50,7 @@ export const AudioSettings = () => { const [WoodBlock3Sound] = useSound(WoodBlock3, { volume: 0.1 }); const [pixelsAvailable, setPixelsAvailable] = useState(0); const [pixelAvailableOffset, setPixelAvailableOffset] = useState(0); const WoodSounds = [WoodBlock1Sound, WoodBlock2Sound, WoodBlock3Sound]; Loading @@ -51,15 +58,41 @@ export const AudioSettings = () => { coffee2Ref.current = Coffee2Sound; }, [Coffee2Sound]); useEffect(() => { return () => { if (delayedAvailableSoundRef.current !== undefined) { window.clearTimeout(delayedAvailableSoundRef.current); delayedAvailableSoundRef.current = undefined; } }; }, [pixelAvailableOffset, state.pixelAvailable]); const handleAvailable = useCallback( (available: number, isUndo: boolean) => { if (available > pixelsAvailable && state.pixelAvailable && !isUndo) { if (pixelAvailableOffset < 0) { if (!earlyAvailableSoundPlayedRef.current) Coffee2Sound(); earlyAvailableSoundPlayedRef.current = false; } else if (pixelAvailableOffset === 0) { Coffee2Sound(); } else { delayedAvailableSoundRef.current = window.setTimeout(() => { Coffee2Sound(); delayedAvailableSoundRef.current = undefined; }, pixelAvailableOffset * 1000); } } else if (available < pixelsAvailable) { earlyAvailableSoundPlayedRef.current = false; } setPixelsAvailable(available); }, [pixelsAvailable, state.pixelAvailable], [ Coffee2Sound, pixelAvailableOffset, pixelsAvailable, state.pixelAvailable, ], ); useEffect(() => { Loading @@ -70,6 +103,44 @@ export const AudioSettings = () => { }; }, [handleAvailable]); useEffect(() => { earlyAvailableSoundPlayedRef.current = false; if ( !state.pixelAvailable || pixelAvailableOffset >= 0 || pixelsAvailable >= config.canvas.pixel.maxStack ) { return; } const canvas = CanvasCore.get(false); if (!canvas?.lastPlace) return; const cooldown = CanvasLib.getPixelCooldown(pixelsAvailable + 1, config); const availableAt = canvas.lastPlace + cooldown * 1000 * (pixelsAvailable + 1); const soundAt = availableAt + pixelAvailableOffset * 1000; const delay = soundAt - Date.now(); if (delay <= 0) return; const timeout = window.setTimeout(() => { earlyAvailableSoundPlayedRef.current = true; Coffee2Sound(); }, delay); return () => { window.clearTimeout(timeout); }; }, [ Coffee2Sound, config, pixelAvailableOffset, pixelsAvailable, state.pixelAvailable, ]); const handlePlace = useCallback(() => { if (!state.place) return; Loading Loading @@ -166,6 +237,23 @@ export const AudioSettings = () => { > Pixel Available </Switch> {state.pixelAvailable && ( <Slider className="px-2" label="Chime Offset" step={1} minValue={-5} maxValue={15} value={-pixelAvailableOffset} onChange={(value) => setPixelAvailableOffset(-(value as number)) } getValue={(value) => { const offset = -(value as number); return `${offset > 0 ? "+" : ""}${offset}s`; }} /> )} <Switch silent isSelected={state.place} Loading Loading
packages/client/src/components/Settings/AudioSettings.tsx +92 −4 Original line number Diff line number Diff line import { useCallback, useEffect, useState } from "react"; import { useRef } from "react"; import { Slider } from "@heroui/react"; import { CanvasLib } from "@sc07-canvas/lib/canvas"; import { useCallback, useEffect, useRef, useState } from "react"; import useSound from "use-sound"; import { useAppContext } from "@/contexts/AppContext"; import { useAudio } from "@/contexts/AudioContext"; import { CanvasCore } from "@/lib/canvas"; import network from "../../lib/network"; import African1 from "../../sounds/African1.mp3"; Loading @@ -20,8 +23,11 @@ const _ = (v: boolean) => (v ? "enable" : "disable"); export const AudioSettings = () => { const { state, dispatch } = useAudio(); const { config } = useAppContext<true>(); const coffee2Ref = useRef<(() => void) | null>(null); const delayedAvailableSoundRef = useRef<number | undefined>(undefined); const earlyAvailableSoundPlayedRef = useRef(false); const [Coffee1Sound] = useSound(Coffee1, { volume: 0.5 }); Loading @@ -44,6 +50,7 @@ export const AudioSettings = () => { const [WoodBlock3Sound] = useSound(WoodBlock3, { volume: 0.1 }); const [pixelsAvailable, setPixelsAvailable] = useState(0); const [pixelAvailableOffset, setPixelAvailableOffset] = useState(0); const WoodSounds = [WoodBlock1Sound, WoodBlock2Sound, WoodBlock3Sound]; Loading @@ -51,15 +58,41 @@ export const AudioSettings = () => { coffee2Ref.current = Coffee2Sound; }, [Coffee2Sound]); useEffect(() => { return () => { if (delayedAvailableSoundRef.current !== undefined) { window.clearTimeout(delayedAvailableSoundRef.current); delayedAvailableSoundRef.current = undefined; } }; }, [pixelAvailableOffset, state.pixelAvailable]); const handleAvailable = useCallback( (available: number, isUndo: boolean) => { if (available > pixelsAvailable && state.pixelAvailable && !isUndo) { if (pixelAvailableOffset < 0) { if (!earlyAvailableSoundPlayedRef.current) Coffee2Sound(); earlyAvailableSoundPlayedRef.current = false; } else if (pixelAvailableOffset === 0) { Coffee2Sound(); } else { delayedAvailableSoundRef.current = window.setTimeout(() => { Coffee2Sound(); delayedAvailableSoundRef.current = undefined; }, pixelAvailableOffset * 1000); } } else if (available < pixelsAvailable) { earlyAvailableSoundPlayedRef.current = false; } setPixelsAvailable(available); }, [pixelsAvailable, state.pixelAvailable], [ Coffee2Sound, pixelAvailableOffset, pixelsAvailable, state.pixelAvailable, ], ); useEffect(() => { Loading @@ -70,6 +103,44 @@ export const AudioSettings = () => { }; }, [handleAvailable]); useEffect(() => { earlyAvailableSoundPlayedRef.current = false; if ( !state.pixelAvailable || pixelAvailableOffset >= 0 || pixelsAvailable >= config.canvas.pixel.maxStack ) { return; } const canvas = CanvasCore.get(false); if (!canvas?.lastPlace) return; const cooldown = CanvasLib.getPixelCooldown(pixelsAvailable + 1, config); const availableAt = canvas.lastPlace + cooldown * 1000 * (pixelsAvailable + 1); const soundAt = availableAt + pixelAvailableOffset * 1000; const delay = soundAt - Date.now(); if (delay <= 0) return; const timeout = window.setTimeout(() => { earlyAvailableSoundPlayedRef.current = true; Coffee2Sound(); }, delay); return () => { window.clearTimeout(timeout); }; }, [ Coffee2Sound, config, pixelAvailableOffset, pixelsAvailable, state.pixelAvailable, ]); const handlePlace = useCallback(() => { if (!state.place) return; Loading Loading @@ -166,6 +237,23 @@ export const AudioSettings = () => { > Pixel Available </Switch> {state.pixelAvailable && ( <Slider className="px-2" label="Chime Offset" step={1} minValue={-5} maxValue={15} value={-pixelAvailableOffset} onChange={(value) => setPixelAvailableOffset(-(value as number)) } getValue={(value) => { const offset = -(value as number); return `${offset > 0 ? "+" : ""}${offset}s`; }} /> )} <Switch silent isSelected={state.place} Loading