123 lines
3.2 KiB
JavaScript
123 lines
3.2 KiB
JavaScript
"use strict";
|
|
|
|
/**
|
|
* Client class that implements the InstantChat protocol using WebSockets.
|
|
*
|
|
* Dispatches the following events which can be subscribed/unsubscribed using .on() and .off():
|
|
* - initialized: Connection to server has been established and initialized, ready to send messages.
|
|
* - disconnected: Connection has been closed.
|
|
* - connectionError: Some connection error occurred.
|
|
* - receivedMessage: Chat message has been received. Data: object {from: 'username', text: 'text'}
|
|
*/
|
|
class Client extends EventDispatcher {
|
|
constructor(wsUri, chatID, nickname) {
|
|
super();
|
|
|
|
this.wsUri = wsUri;
|
|
this.chatID = chatID;
|
|
this.nickname = nickname;
|
|
|
|
// Create WebSocket and set internal callbacks
|
|
console.log("Initialize Client...")
|
|
this.webSocket = new WebSocket(wsUri);
|
|
this.webSocket.onopen = this._onSocketOpen.bind(this);
|
|
this.webSocket.onclose = this._onSocketClose.bind(this);
|
|
this.webSocket.onerror = this._onSocketError.bind(this);
|
|
this.webSocket.onmessage = this._onSocketMessage.bind(this);
|
|
}
|
|
|
|
// Internal WebSocket event handlers
|
|
_onSocketOpen(evt) {
|
|
console.log("Connected to " + this.wsUri);
|
|
this.sendInit(this.chatID, this.nickname);
|
|
}
|
|
|
|
_onSocketClose(evt) {
|
|
console.log("Connection closed (code " + evt.code + ").");
|
|
this.dispatch("disconnected");
|
|
}
|
|
|
|
_onSocketError(evt) {
|
|
console.error("Connection error: ", evt);
|
|
this.dispatch("connectionError");
|
|
}
|
|
|
|
_onSocketMessage(evt) {
|
|
console.log("Received: " + evt.data);
|
|
this._parseMessage(evt.data);
|
|
}
|
|
|
|
/**
|
|
* Sends an arbitrary command as JSON.
|
|
*
|
|
* commandObj: The command as an object ('action' specifies type of command).
|
|
*/
|
|
sendCommand(commandObj) {
|
|
const commandJson = JSON.stringify(commandObj);
|
|
console.log("Sending command: " + commandJson);
|
|
this.webSocket.send(commandJson);
|
|
}
|
|
|
|
/**
|
|
* Sends the 'init' command which sets up the session. Also sets the chat ID and nickname.
|
|
*
|
|
* chatID: The ID of the chat instance.
|
|
* nickname: The user's nickname.
|
|
*/
|
|
sendInit(chatID, nickname) {
|
|
this.sendCommand({
|
|
action: "init",
|
|
chat_id: chatID,
|
|
nickname: nickname,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Sends the 'message' command which sends a chat message to the chat.
|
|
*
|
|
* msgText: The text of the chat message.
|
|
*/
|
|
sendChatMessage(msgText) {
|
|
this.sendCommand({
|
|
action: "message",
|
|
text: msgText,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Parses an incoming JSON message and dispatches specific events.
|
|
*
|
|
* msgText: The content of the message as a JSON string.
|
|
*/
|
|
_parseMessage(msgString) {
|
|
try {
|
|
const msg = JSON.parse(msgString);
|
|
|
|
switch (msg.type) {
|
|
// Response to 'init' command (doesn't have much content, I guess)
|
|
case "init":
|
|
console.log("Got init response: ", msg);
|
|
this.dispatch("initialized");
|
|
break;
|
|
|
|
// Incoming chat message
|
|
case "message":
|
|
console.log("Received chat message from '" + msg.from + "', text '" + msg.text + "'");
|
|
this.dispatch("receivedMessage", {
|
|
from: msg.from,
|
|
text: msg.text,
|
|
});
|
|
break;
|
|
|
|
// TODO Topic change, user join/leave, error, ...
|
|
|
|
default:
|
|
console.error("Unknown message type '" + msg.type + "'");
|
|
}
|
|
}
|
|
catch (e) {
|
|
console.error("Error parsing message JSON: " + e.message);
|
|
}
|
|
}
|
|
}
|