import { action, observable, ObservableMap } from "mobx"; import io from "socket.io-client"; // import { hiddenConsole } from "./containers/backgroundUtils"; import { ID } from "../shared/types"; import { isProd } from "../shared/utils/utils"; import { send } from "./serverIpc"; export async function createSocket() { return new Promise((res, rej) => { const socket = io( isProd() ? "https://presentable-backend.herokuapp.com" : "http://localhost:4000", { transports: ["websocket"], } ); socket.on("connect", () => { console.log("SUCCESSFUL SOCKET CONNECTION"); console.log(socket.id); res(socket); }); }); } export enum SocketActions { ENTER_ROOM = "ENTER_ROOM", LEAVE_ROOM = "LEAVE_ROOM", MOUSE_MOVEMENT = "MOUSE_MOVEMENT", CREATE_SLIDE = "CREATE_SLIDE", DELETE_SLIDE = "DELETE_SLIDE", MOUSE_CLICK = "MOUSE_CLICK", } export enum RemoteSocketActions { ENTER_ROOM = "REMOTE_ENTER_ROOM", LEAVE_ROOM = "REMOTE_LEAVE_ROOM", MOUSE_MOVEMENT = "REMOTE_MOUSE_MOVEMENT", CREATE_SLIDE = "REMOTE_CREATE_SLIDE", DELETE_SLIDE = "REMOTE_DELETE_SLIDE", MOUSE_CLICK = "REMOTE_MOUSE_CLICK", } export const UPDATE = "UPDATE"; export const REMOTE_UPDATE = "REMOTE_UPDATE"; export type RemotePayload = { action: RemoteSocketActions; data: any; }; export type MouseMovementData = { x: number; y: number; userId: ID; name: string; }; type EnterRoomData = { userId: ID; }; type LeaveRoomData = { userId: ID; }; export type MouseClickData = { userId: ID; x: number; y: number; timestamp: number; }; export class BackgroundRoomStore { roomId: ID | null; socket: SocketIOClient.Socket; subscribers: ObservableMap; static async createNew() { const socket = await createSocket(); return new BackgroundRoomStore(socket); } constructor(socket: SocketIOClient.Socket) { this.roomId = null; this.subscribers = observable.map({}); this.socket = socket; } handleAction(action: SocketActions, data: any) { switch (action) { case SocketActions.ENTER_ROOM: this.handleEnterRoom(data); break; case SocketActions.LEAVE_ROOM: this.handleLeaveRoom(data); break; case SocketActions.MOUSE_MOVEMENT: this.handleMouseMovement(data); break; case SocketActions.MOUSE_CLICK: this.handleMouseClick(data); break; default: this.handleOtherAction(action, data); } } @action handleEnterRoom(data: EnterRoomData) { this.subscribers.set(data.userId, data.userId); } @action handleLeaveRoom(data: LeaveRoomData) { this.subscribers.delete(data.userId); send("leave-room", { userId: data.userId, }); } @action handleMouseMovement(data: MouseMovementData) { send("mouse-movement", { ...data, timestamp: null, }); } handleOtherAction(action: SocketActions | RemoteSocketActions, data: any) { console.log("UNHANDLED ACTION: " + action); } // TODO: Figure out if this is right. Only doing this for the background thread @action addRoomId(roomId: string) { console.log("ADDING ROOM ID"); console.log(roomId); this.roomId = roomId; console.log( "BackgroundRoomStore:adding roomId and listening for server ws" ); this.socket.on( `${REMOTE_UPDATE}:${this.roomId}`, (payload: RemotePayload) => { this.handleRemoteAction(payload.action, payload.data); } ); } @action closeRoom(roomId: string) { console.log("CLOSING ROOM " + roomId); this.socket.removeListener(`${REMOTE_UPDATE}:${this.roomId}`); this.roomId = null; } handleRemoteAction(action: RemoteSocketActions, data: any) { switch (action) { case RemoteSocketActions.ENTER_ROOM: this.handleEnterRoom(data); break; case RemoteSocketActions.LEAVE_ROOM: this.handleLeaveRoom(data); break; case RemoteSocketActions.MOUSE_MOVEMENT: this.handleMouseMovement(data); break; case RemoteSocketActions.MOUSE_CLICK: this.handleMouseClick(data); break; default: this.handleOtherAction(action, data); } } @action handleMouseClick(data: MouseClickData) { send("mouse-movement", data); } }