import { Room, RoomServerMessage, RoomMessage } from "./store/room"; export interface RoomConnectionData { ws_url: string; auth_token: string; } export type MessageHandler = (msg: RoomServerMessage) => void; export default class RoomClient { private ws: WebSocket; public info: Room; public backlog: RoomServerMessage[]; private onMessage?: MessageHandler; private buffer: RoomServerMessage[]; constructor(_ws: WebSocket, _info: Room) { this.info = _info; this.buffer = []; this.backlog = []; this.ws = _ws; this.ws.addEventListener("message", this._received.bind(this)); } private _received(ev: MessageEvent) { let data = JSON.parse(ev.data); if (this.onMessage) { return this.onMessage(data); } // Save messages in a buffer if no handler is set this.buffer.push(data); } public setMessageHandler(handler: MessageHandler) { // Set as handler for all future messages this.onMessage = handler; // If we have messages in our buffer, send them over for (const msg of this.buffer) { handler(msg); } // Empty buffer this.buffer = []; } public static connect(wsdata: RoomConnectionData): Promise { return new Promise((resolve, reject) => { let ws = new WebSocket(wsdata.ws_url); const onMessage = (ev: MessageEvent) => { // Unregister handler ws.removeEventListener("message", onMessage); // Parse message let data = JSON.parse(ev.data) as RoomServerMessage; if ("error" in data) { reject(data.error); } if (data.room) { let client = new RoomClient(ws, data.room); // Check for backlog if (data.backlog) { client.backlog = data.backlog; } resolve(client); } else { reject("missing room info"); } }; ws.addEventListener("message", onMessage); ws.addEventListener("open", ev => { // Send authentication ws.send(JSON.stringify({ token: wsdata.auth_token })); }); }); } }