Kopie van https://gitlab.com/studieverenigingvia/ict/centurion met een paar aanpassingen
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
2.8 KiB
131 lines
2.8 KiB
import { Socket } from "socket.io";
|
|
|
|
import Room, { SerializedRoom } from "./Room";
|
|
import { getTimelineNames } from "./timeline";
|
|
|
|
export interface Config {
|
|
availableTimelines: string[];
|
|
}
|
|
|
|
export default class User {
|
|
socket: Socket;
|
|
id: string;
|
|
|
|
room: Room | null = null;
|
|
readyToParticipate = false;
|
|
|
|
constructor(socket: Socket) {
|
|
this.socket = socket;
|
|
this.id = socket.id;
|
|
}
|
|
|
|
serialize() {
|
|
return {
|
|
id: this.id,
|
|
readyToParticipate: this.readyToParticipate,
|
|
};
|
|
}
|
|
|
|
async setRoom(room: Room | null) {
|
|
if (this.room === room) return;
|
|
|
|
if (this.room !== null) {
|
|
await this.socket.leave(this.room.id.toString());
|
|
this.readyToParticipate = false;
|
|
}
|
|
|
|
this.room = room;
|
|
|
|
if (this.room !== null) {
|
|
await this.socket.join(this.room.id.toString());
|
|
}
|
|
|
|
this.sync();
|
|
}
|
|
|
|
getConfig() {
|
|
return {
|
|
availableTimelines: getTimelineNames(),
|
|
};
|
|
}
|
|
|
|
sentConfig: Config | null = null;
|
|
sentRoom: SerializedRoom | null = null;
|
|
sentTimelineName: string | null = null;
|
|
|
|
sync() {
|
|
// Config
|
|
const config = this.getConfig();
|
|
if (!this.syncEquals(this.sentConfig, config)) {
|
|
this.sentConfig = Object.assign({}, config);
|
|
this.emit("config", {
|
|
config: this.sentConfig,
|
|
});
|
|
}
|
|
|
|
// Room
|
|
if (!this.syncEquals(this.sentRoom, this.room?.serialize(this))) {
|
|
this.sentRoom = this.room
|
|
? (JSON.parse(
|
|
JSON.stringify(this.room.serialize(this))
|
|
) as SerializedRoom)
|
|
: null;
|
|
|
|
this.emit("room", {
|
|
room: this.sentRoom,
|
|
});
|
|
}
|
|
|
|
// Timeline
|
|
if (!this.syncEquals(this.sentTimelineName, this.room?.timelineName)) {
|
|
this.sentTimelineName = this.room?.timelineName || null;
|
|
this.emit("timeline", {
|
|
timeline:
|
|
this.sentTimelineName == null ? null : this.room?.serializeTimeline(),
|
|
});
|
|
}
|
|
}
|
|
|
|
emit(eventName: string, obj: unknown) {
|
|
this.socket.emit(eventName, obj);
|
|
}
|
|
|
|
syncEquals(obj1: unknown, obj2: unknown): boolean {
|
|
if (typeof obj1 !== typeof obj2) {
|
|
return false;
|
|
}
|
|
|
|
if (typeof obj1 !== "object") {
|
|
// Both are not 'object'
|
|
return Object.is(obj1, obj2);
|
|
}
|
|
|
|
if (obj1 === null && obj2 === null) {
|
|
return true;
|
|
}
|
|
|
|
if (obj1 === null || obj2 === null) {
|
|
return false;
|
|
}
|
|
|
|
if (typeof obj2 !== "object") {
|
|
// This can not happen ;)
|
|
throw new TypeError("Obj2 is not object while obj1 is.");
|
|
}
|
|
|
|
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
|
|
return false;
|
|
}
|
|
|
|
return Object.keys(obj1).every((key: string) => {
|
|
if (!(key in obj1) || !(key in obj2)) {
|
|
return false;
|
|
}
|
|
|
|
return this.syncEquals(
|
|
obj1[key as keyof object],
|
|
obj2[key as keyof object]
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|