mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-04 23:18:01 +00:00
a41fe8806b
* chore: upgrade monorepo deps * chore: configure lint-staged * refactor: lenient use of any
140 lines
3.6 KiB
TypeScript
140 lines
3.6 KiB
TypeScript
import { Log, RuntimeStore } from 'ontime-types';
|
|
|
|
import { isProduction, RUNTIME, websocketUrl } from '../api/apiConstants';
|
|
import { ontimeQueryClient } from '../queryClient';
|
|
import { socketClientName } from '../stores/connectionName';
|
|
import { addLog } from '../stores/logger';
|
|
import { runtime } from '../stores/runtime';
|
|
|
|
export let websocket: WebSocket | null = null;
|
|
let reconnectTimeout: NodeJS.Timeout | null = null;
|
|
const reconnectInterval = 1000;
|
|
export let shouldReconnect = true;
|
|
export let hasConnected = false;
|
|
export let reconnectAttempts = 0;
|
|
export const connectSocket = (preferredClientName?: string) => {
|
|
websocket = new WebSocket(websocketUrl);
|
|
|
|
websocket.onopen = () => {
|
|
clearTimeout(reconnectTimeout as NodeJS.Timeout);
|
|
hasConnected = true;
|
|
reconnectAttempts = 0;
|
|
|
|
if (preferredClientName) {
|
|
socketSendJson('set-client-name', preferredClientName);
|
|
}
|
|
};
|
|
|
|
websocket.onclose = () => {
|
|
console.warn('WebSocket disconnected');
|
|
if (shouldReconnect) {
|
|
reconnectTimeout = setTimeout(() => {
|
|
console.warn('WebSocket: attempting reconnect');
|
|
if (websocket && websocket.readyState === WebSocket.CLOSED) {
|
|
reconnectAttempts += 1;
|
|
connectSocket();
|
|
}
|
|
}, reconnectInterval);
|
|
}
|
|
};
|
|
|
|
websocket.onerror = (error) => {
|
|
console.error('WebSocket error:', error);
|
|
};
|
|
|
|
websocket.onmessage = (event) => {
|
|
try {
|
|
const data = JSON.parse(event.data);
|
|
|
|
const { type, payload } = data;
|
|
|
|
if (!type) {
|
|
return;
|
|
}
|
|
|
|
// TODO: implement partial store updates
|
|
switch (type) {
|
|
case 'client-name': {
|
|
socketClientName.getState().setName(payload);
|
|
break;
|
|
}
|
|
case 'ontime-log': {
|
|
addLog(payload as Log);
|
|
break;
|
|
}
|
|
case 'ontime': {
|
|
runtime.setState(payload as RuntimeStore);
|
|
if (!isProduction) {
|
|
ontimeQueryClient.setQueryData(RUNTIME, data.payload);
|
|
}
|
|
break;
|
|
}
|
|
case 'ontime-playback': {
|
|
const state = runtime.getState();
|
|
state.playback = payload;
|
|
runtime.setState(state);
|
|
break;
|
|
}
|
|
case 'ontime-timer': {
|
|
const state = runtime.getState();
|
|
state.timer = payload;
|
|
runtime.setState(state);
|
|
break;
|
|
}
|
|
case 'ontime-loaded': {
|
|
const state = runtime.getState();
|
|
state.loaded = payload;
|
|
runtime.setState(state);
|
|
break;
|
|
}
|
|
case 'ontime-timerMessage': {
|
|
const state = runtime.getState();
|
|
state.timerMessage = payload;
|
|
runtime.setState(state);
|
|
break;
|
|
}
|
|
case 'ontime-publicMessage': {
|
|
const state = runtime.getState();
|
|
state.publicMessage = payload;
|
|
runtime.setState(state);
|
|
break;
|
|
}
|
|
case 'ontime-lowerMessage': {
|
|
const state = runtime.getState();
|
|
state.lowerMessage = payload;
|
|
runtime.setState(state);
|
|
break;
|
|
}
|
|
case 'ontime-onAir': {
|
|
const state = runtime.getState();
|
|
state.onAir = payload;
|
|
runtime.setState(state);
|
|
break;
|
|
}
|
|
}
|
|
} catch (_) {
|
|
// ignore unhandled
|
|
}
|
|
};
|
|
};
|
|
|
|
export const disconnectSocket = () => {
|
|
shouldReconnect = false;
|
|
websocket?.close();
|
|
};
|
|
|
|
export const socketSend = (message: any) => {
|
|
if (websocket && websocket.readyState === WebSocket.OPEN) {
|
|
websocket.send(message);
|
|
}
|
|
};
|
|
|
|
export const socketSendJson = (type: string, payload?: unknown) => {
|
|
socketSend(
|
|
JSON.stringify({
|
|
type,
|
|
payload,
|
|
}),
|
|
);
|
|
};
|