import {useContext, useEffect, useMemo, useState} from "react"; import RuntimeContext from "../../contexts/RuntimeContext"; import {WorkoutStatus} from "../../models/Workouts"; import {faPause, faPlay} from "@fortawesome/free-solid-svg-icons"; import {useKey, usePlusMinus} from "../../hooks/keyboard"; import {Boi} from "../../primitives/boi/Boi"; import {TitleLine} from "../../primitives/misc/Misc"; import Blob, {BlobText} from "../../primitives/blob/Blob"; import {Icon} from "../../primitives/Shared"; import {useLastState} from "./hooks"; import {IconDefinition} from "@fortawesome/fontawesome-svg-core"; import MessageBoi from "./MessageBoi"; interface Option { icon?: IconDefinition text?: string warning?: boolean onClick(): void } const skipMessages = ["Ikke hopp over", "Hopp over straks", "Hopp over nĂ¥"]; export function ControlsBoi() { const {workout, disconnect, start, stop, setLevel, skip} = useContext(RuntimeContext); const lastState = useLastState(); const [mode, setMode] = useState<"default" | "level" | "skip">("default"); const [nextSkip, setNextSkip] = useState(-1); const [lastTime, setLastTime] = useState(0); const options: Option[] = useMemo(() => { if (!workout) return []; const isStopped = workout.status === WorkoutStatus.Connected || workout.status === WorkoutStatus.Stopped; const btnList: Option[] = []; if (isStopped) { btnList.push({icon: faPlay, onClick: start}) } if (workout.status === WorkoutStatus.Started) { btnList.push({icon: faPause, onClick: stop}); if (workout.program) { const text = nextSkip > 0 ? `Hopper om ${nextSkip - lastTime} sek.` : "Hopp over steg"; btnList.push({text, warning: nextSkip >= 0, onClick: () => setMode("skip")}) } else { btnList.push({text: "Motstand", onClick: () => setMode("level")}); } } if (isStopped) { btnList.push({text: "Avslutt", onClick: disconnect}); } return btnList; }, [workout, start, stop, disconnect, skip, nextSkip, lastTime]); let length = options.length; if (mode === "level") length = 32; if (mode === "skip") length = 3; const [sel, setSel] = usePlusMinus(length); useKey("Enter", () => { if (mode !== "default") { if (mode === "level") { setLevel(sel + 1); } else { if (sel === 1) { setNextSkip(lastTime + 60 - (lastTime % 60)); } else if (sel === 2) { setNextSkip(0); } else { setNextSkip(-1); } } setSel(0); setMode("default"); } else { if (options[sel]) { options[sel].onClick(); } } setSel(0); }, [options, lastTime, sel]); useKey("Escape", () => { if (!workout) return; const isStopped = workout.status === WorkoutStatus.Connected || workout.status === WorkoutStatus.Stopped; if (isStopped) { disconnect(); } }, [workout, disconnect]); useEffect(() => { if (lastState?.level && mode === "level") { setSel(lastState.level - 1); } }, [mode]); useEffect(() => { if (lastState?.time) { setLastTime(lastState.time!); } }, [lastState]); useEffect(() => { if (nextSkip !== -1 && (nextSkip === 0 || nextSkip <= lastTime)) { setNextSkip(-1); skip(); } }, [lastTime, nextSkip]); if (mode === "level") { return ; } if (mode === "skip") { return ; } return ( {options.map((o, i) => ( {o.icon && } {o.text} ))} ); }