You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

106 lines
2.7 KiB

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
onClick(): void
}
export function ControlsBoi() {
const {workout, disconnect, start, stop, setLevel} = useContext(RuntimeContext);
const lastState = useLastState();
const [mode, setMode] = useState<"default" | "level">("default");
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) {
btnList.push({
text: "Motstand", onClick: () => {
setMode("level");
}
});
}
}
if (isStopped) {
btnList.push({text: "Avslutt", onClick: disconnect});
}
return btnList;
}, [workout]);
const [sel, setSel] = usePlusMinus(mode === "level" ? 32 : options.length);
useKey("Enter", () => {
if (mode === "level") {
setLevel(sel + 1);
setSel(0);
setMode("default");
} else {
if (options[sel]) {
options[sel].onClick();
}
}
setSel(0);
}, [options, 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]);
if (mode === "level") {
return (
<MessageBoi text={`${sel + 1} +/-`}/>
);
}
return (
<Boi vertical="top" horizontal="right" style={{fontSize: "2vmax"}}>
{options.map((o, i) => (
<Blob key={i} color={sel === i ? "indigo" : "gray"} onClick={o.onClick}>
<BlobText>
{o.icon && <Icon value={o.icon}/>} {o.text}
</BlobText>
</Blob>
))}
</Boi>
);
}