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.
169 lines
4.2 KiB
169 lines
4.2 KiB
import React, {createContext, useEffect, useState} from "react";
|
|
import {
|
|
connectWorkout,
|
|
createNewWorkout,
|
|
fetchActiveWorkouts, fetchBikes, fetchPrograms,
|
|
openWebsocket, pauseWorkout,
|
|
startWorkout,
|
|
stopWorkout
|
|
} from "../hooks/net";
|
|
import useMilestones from "../hooks/milestones";
|
|
|
|
export const StatusContext = createContext({
|
|
bike: null,
|
|
program: null,
|
|
bikes: null,
|
|
programs: null,
|
|
workout: null,
|
|
workoutStatus: null,
|
|
setBike: null,
|
|
setProgram: null,
|
|
state: null,
|
|
milestones: [],
|
|
create: () => null,
|
|
resume: () => null,
|
|
start: () => null,
|
|
pause: () => null,
|
|
stop: () => null,
|
|
});
|
|
|
|
export const StatusContextProvider = ({children}) => {
|
|
const [bike, setBike] = useState(null);
|
|
const [program, setProgram] = useState(null);
|
|
const [bikes, setBikes] = useState(null);
|
|
const [programs, setPrograms] = useState(null);
|
|
const [workout, setWorkout] = useState(null);
|
|
const [workoutStatus, setWorkoutStatus] = useState(null);
|
|
const [state, setState] = useState("offline");
|
|
const {milestones, prevDiff, prevLongDiff, msDispatch} = useMilestones();
|
|
const [socket, setSocket] = useState(null);
|
|
const [hidden, setHidden] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (programs === null) {
|
|
fetchPrograms().then(newPrograms => setPrograms(newPrograms));
|
|
}
|
|
}, [programs]);
|
|
|
|
useEffect(() => {
|
|
if (bikes === null) {
|
|
fetchBikes().then(newBikes => {
|
|
setBikes(newBikes);
|
|
|
|
if (newBikes.length === 1) {
|
|
setBike(newBikes[0]);
|
|
}
|
|
});
|
|
}
|
|
}, [bikes]);
|
|
|
|
useEffect(() => {
|
|
if (bike === null && program === null && workout === null) {
|
|
resume();
|
|
}
|
|
}, [bike, program, workout]);
|
|
|
|
useEffect(() => {
|
|
if (bikes === null || programs === null) {
|
|
setState("loading");
|
|
} else if (workout !== null) {
|
|
setState(workout.state || "unknown");
|
|
} else if (bike === null) {
|
|
setState("bike");
|
|
} else if (program === null) {
|
|
setState("program");
|
|
}
|
|
}, [bike, program, workout, bikes, programs]);
|
|
|
|
useEffect(() => {
|
|
if (socket === null) {
|
|
return;
|
|
}
|
|
|
|
if (workout === null) {
|
|
socket.close();
|
|
setSocket(null);
|
|
return;
|
|
}
|
|
|
|
socket.onmessage = ({data}) => {
|
|
const body = JSON.parse(data);
|
|
|
|
if (typeof body.workout !== "undefined") {
|
|
setWorkout({...body.workout, ...workout});
|
|
}
|
|
|
|
if (typeof body.workoutStatusBackfill !== "undefined") {
|
|
body.workoutStatusBackfill.forEach(wsbf => {
|
|
setWorkoutStatus(wsbf);
|
|
msDispatch({type: "measure", payload: {...wsbf, program}});
|
|
});
|
|
}
|
|
|
|
if (typeof body.workoutStatus !== "undefined") {
|
|
setWorkoutStatus(body.workoutStatus);
|
|
msDispatch({type: "measure", payload: {...body.workoutStatus, program}});
|
|
}
|
|
};
|
|
|
|
return () => {
|
|
socket.onmessage = null;
|
|
}
|
|
}, [socket, workout, program, msDispatch]);
|
|
|
|
async function create(myProgram = null) {
|
|
setWorkoutStatus(null);
|
|
|
|
let newWorkout = await createNewWorkout(bike, myProgram || program);
|
|
|
|
setWorkout(newWorkout);
|
|
setWorkout(await connectWorkout(newWorkout));
|
|
|
|
setSocket(openWebsocket(newWorkout));
|
|
}
|
|
|
|
async function resume() {
|
|
const activeWorkouts = await fetchActiveWorkouts();
|
|
const activeAndConnected = activeWorkouts.filter(w => w.state !== "disconnected");
|
|
const count = activeAndConnected.length;
|
|
const last = count > 0 ? activeAndConnected[count - 1] : null;
|
|
|
|
if (last !== null) {
|
|
setProgram(last.program);
|
|
setWorkout(last);
|
|
setBike(last.bike);
|
|
|
|
setSocket(openWebsocket(last));
|
|
}
|
|
}
|
|
|
|
async function start() {
|
|
setWorkout(await startWorkout(workout));
|
|
}
|
|
|
|
async function pause() {
|
|
setWorkout(await pauseWorkout(workout));
|
|
}
|
|
|
|
async function stop() {
|
|
await stopWorkout(workout);
|
|
|
|
setBike(null);
|
|
setProgram(null);
|
|
setWorkout(null);
|
|
msDispatch({type: "clear"});
|
|
}
|
|
|
|
return (
|
|
<StatusContext.Provider value={{
|
|
bike, program, workout, workoutStatus, state, milestones,
|
|
setBike, setProgram,
|
|
create, resume, start, pause, stop,
|
|
programs, bikes,
|
|
prevDiff, prevLongDiff,
|
|
hidden, setHidden,
|
|
}}>
|
|
{children}
|
|
</StatusContext.Provider>
|
|
)
|
|
};
|