feat: initial JaniChat messenger — PWA, WebSocket, admin panel
This commit is contained in:
70
frontend/src/api/ws.ts
Normal file
70
frontend/src/api/ws.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
type Handler = (payload: any) => void;
|
||||
|
||||
class WsClient {
|
||||
private ws: WebSocket | null = null;
|
||||
private handlers = new Map<string, Handler[]>();
|
||||
private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
private token: string | null = null;
|
||||
|
||||
connect(token: string) {
|
||||
this.token = token;
|
||||
const wsBase = import.meta.env.VITE_WS_URL || `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}`;
|
||||
this.ws = new WebSocket(`${wsBase}/ws?token=${token}`);
|
||||
|
||||
this.ws.onopen = () => {
|
||||
if (this.reconnectTimer) {
|
||||
clearTimeout(this.reconnectTimer);
|
||||
this.reconnectTimer = null;
|
||||
}
|
||||
this.emit('connected', null);
|
||||
};
|
||||
|
||||
this.ws.onmessage = (event) => {
|
||||
try {
|
||||
const { type, payload } = JSON.parse(event.data);
|
||||
const hs = this.handlers.get(type) || [];
|
||||
hs.forEach(h => h(payload));
|
||||
} catch {}
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
this.emit('disconnected', null);
|
||||
this.reconnectTimer = setTimeout(() => {
|
||||
if (this.token) this.connect(this.token);
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
this.ws.onerror = () => {
|
||||
this.ws?.close();
|
||||
};
|
||||
}
|
||||
|
||||
on(type: string, handler: Handler) {
|
||||
if (!this.handlers.has(type)) this.handlers.set(type, []);
|
||||
this.handlers.get(type)!.push(handler);
|
||||
return () => {
|
||||
const hs = this.handlers.get(type) || [];
|
||||
this.handlers.set(type, hs.filter(h => h !== handler));
|
||||
};
|
||||
}
|
||||
|
||||
private emit(type: string, payload: any) {
|
||||
const hs = this.handlers.get(type) || [];
|
||||
hs.forEach(h => h(payload));
|
||||
}
|
||||
|
||||
send(type: string, payload: any) {
|
||||
if (this.ws?.readyState === WebSocket.OPEN) {
|
||||
this.ws.send(JSON.stringify({ type, payload }));
|
||||
}
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.token = null;
|
||||
if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
|
||||
this.ws?.close();
|
||||
this.ws = null;
|
||||
}
|
||||
}
|
||||
|
||||
export const wsClient = new WsClient();
|
||||
Reference in New Issue
Block a user