mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
97 lines
2.7 KiB
React
97 lines
2.7 KiB
React
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
import { useSocket } from './SocketContext.jsx';
|
|
|
|
const SessionContext = createContext({
|
|
connected: false,
|
|
session: null,
|
|
logs: [],
|
|
login: async () => {},
|
|
setRole: async () => {},
|
|
requestControl: async () => {},
|
|
releaseControl: async () => {},
|
|
subscribeAll: async () => {},
|
|
});
|
|
|
|
function useAckEmitter(socket) {
|
|
return useCallback(
|
|
(event, payload = {}) =>
|
|
new Promise((resolve, reject) => {
|
|
socket.emit(event, payload, (resp = {}) => {
|
|
if (resp.error) {
|
|
reject(new Error(resp.error));
|
|
} else {
|
|
resolve(resp);
|
|
}
|
|
});
|
|
}),
|
|
[socket],
|
|
);
|
|
}
|
|
|
|
export function SessionProvider({ children }) {
|
|
const socket = useSocket();
|
|
const emitWithAck = useAckEmitter(socket);
|
|
const [session, setSession] = useState(null);
|
|
const [logs, setLogs] = useState([]);
|
|
const [connected, setConnected] = useState(socket.connected);
|
|
|
|
useEffect(() => {
|
|
const onConnect = () => setConnected(true);
|
|
const onDisconnect = () => setConnected(false);
|
|
socket.on('connect', onConnect);
|
|
socket.on('disconnect', onDisconnect);
|
|
return () => {
|
|
socket.off('connect', onConnect);
|
|
socket.off('disconnect', onDisconnect);
|
|
};
|
|
}, [socket]);
|
|
|
|
useEffect(() => {
|
|
function handleSession(payload) {
|
|
setSession(payload);
|
|
}
|
|
function handleLogInit(entries = []) {
|
|
setLogs(entries);
|
|
}
|
|
function handleLogEntry(entry) {
|
|
setLogs((prev) => [...prev.slice(-199), entry]);
|
|
}
|
|
socket.on('session:sync', handleSession);
|
|
socket.on('log:init', handleLogInit);
|
|
socket.on('log:entry', handleLogEntry);
|
|
return () => {
|
|
socket.off('session:sync', handleSession);
|
|
socket.off('log:init', handleLogInit);
|
|
socket.off('log:entry', handleLogEntry);
|
|
};
|
|
}, [socket]);
|
|
|
|
const actions = useMemo(
|
|
() => ({
|
|
login: (username, password) => emitWithAck('auth:login', { username, password }),
|
|
setRole: (role) => emitWithAck('session:setRole', { role }),
|
|
requestControl: (roverId, options = {}) =>
|
|
emitWithAck('session:requestControl', { roverId, ...options }),
|
|
releaseControl: (roverId) => emitWithAck('session:releaseControl', { roverId }),
|
|
subscribeAll: () => emitWithAck('session:subscribeAll'),
|
|
}),
|
|
[emitWithAck],
|
|
);
|
|
|
|
const value = useMemo(
|
|
() => ({
|
|
connected,
|
|
session,
|
|
logs,
|
|
...actions,
|
|
}),
|
|
[actions, connected, logs, session],
|
|
);
|
|
|
|
return <SessionContext.Provider value={value}>{children}</SessionContext.Provider>;
|
|
}
|
|
|
|
export function useSession() {
|
|
return useContext(SessionContext);
|
|
}
|