2020-03-29 16:04:50 +00:00
|
|
|
/**
|
|
|
|
* Main client websocket
|
|
|
|
*
|
|
|
|
* @author Pierre HUBERT
|
|
|
|
*/
|
2020-03-31 09:38:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
class WsMessage {
|
|
|
|
constructor(info) {
|
|
|
|
this.title = info.title
|
|
|
|
this.id = info.id
|
|
|
|
this.data = info.data
|
|
|
|
}
|
|
|
|
|
|
|
|
get hasId() {
|
|
|
|
return this.id.length > 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-31 14:25:05 +00:00
|
|
|
let requests = {};
|
|
|
|
let reqCounter = 0;
|
|
|
|
|
2020-03-29 16:04:50 +00:00
|
|
|
class UserWebSocket {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Connect to server
|
|
|
|
*/
|
|
|
|
static async Connect() {
|
|
|
|
|
2020-03-29 16:32:05 +00:00
|
|
|
try {
|
|
|
|
await this.Disconnect();
|
|
|
|
|
|
|
|
console.log("Connect to websocket");
|
|
|
|
|
|
|
|
// Generate an access token
|
|
|
|
const token = (await api("ws/token", null, true)).token;
|
|
|
|
|
|
|
|
// Determine websocket URL
|
2020-03-29 16:40:51 +00:00
|
|
|
const url = ComunicWeb.__config.apiURL.replace("http", "ws") + "ws?token=" + token
|
2020-03-29 16:32:05 +00:00
|
|
|
|
|
|
|
// Connect to websocket
|
|
|
|
this.ws = new WebSocket(url);
|
|
|
|
|
|
|
|
// Wait for connection
|
|
|
|
this.ws.addEventListener("open", () => console.log("Connected to websocket!"))
|
|
|
|
this.ws.addEventListener("error", (e) => this.Error(e))
|
2020-03-30 11:48:40 +00:00
|
|
|
this.ws.addEventListener("close", (e) => this.Closed(e));
|
2020-03-29 16:32:05 +00:00
|
|
|
|
2020-03-30 12:52:43 +00:00
|
|
|
// Handle incoming messages
|
|
|
|
this.ws.addEventListener("message", (e) => {
|
2020-03-31 09:38:09 +00:00
|
|
|
this.ProcessMessage(new WsMessage(JSON.parse(e.data)));
|
2020-03-30 12:52:43 +00:00
|
|
|
})
|
|
|
|
|
2020-03-29 16:32:05 +00:00
|
|
|
} catch(e) {
|
|
|
|
this.Error(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-01 08:23:45 +00:00
|
|
|
/**
|
|
|
|
* Wait for the socket to be connected (if not already)
|
|
|
|
*/
|
|
|
|
static WaitForConnected() {
|
|
|
|
return new Promise((res, err) => {
|
|
|
|
|
|
|
|
// Check if we are already connected
|
|
|
|
if(this.ws.readyState == WebSocket.OPEN) {
|
|
|
|
res();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.ws.addEventListener("open", () => res());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-04-01 08:51:07 +00:00
|
|
|
/**
|
|
|
|
* Get current connection status with the server
|
|
|
|
*/
|
|
|
|
static get IsConnected() {
|
|
|
|
return this.hasOwnProperty("ws")
|
|
|
|
&& this.ws.readyState == WebSocket.OPEN;
|
|
|
|
}
|
|
|
|
|
2020-03-29 16:32:05 +00:00
|
|
|
/**
|
|
|
|
* Handles websocket errors
|
|
|
|
*/
|
|
|
|
static async Error(e) {
|
|
|
|
console.error(e)
|
|
|
|
notify("Could not connect to websocket ! Try to refresh the page...", "danger");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When we get disconnected from the websocket
|
|
|
|
*/
|
2020-03-30 11:48:40 +00:00
|
|
|
static async Closed(e) {
|
|
|
|
console.error("WS closed", e)
|
2020-04-01 08:23:45 +00:00
|
|
|
|
2020-04-01 12:14:08 +00:00
|
|
|
// Notify the application
|
|
|
|
SendEvent("wsClosed");
|
|
|
|
|
2020-04-01 08:23:45 +00:00
|
|
|
// Reset requests queue
|
|
|
|
requests = {};
|
2020-03-30 11:48:40 +00:00
|
|
|
|
2020-03-30 12:24:45 +00:00
|
|
|
// Check if the server was gracefully stopped
|
|
|
|
if(!this.hasOwnProperty("ws"))
|
|
|
|
return;
|
|
|
|
|
2020-03-31 08:40:04 +00:00
|
|
|
const num_seconds = ComunicWeb.__config.productionMode ? 5 : 0.8;
|
2020-03-30 11:48:40 +00:00
|
|
|
|
|
|
|
notify("Disconnected from the server, page will be reloaded in "+num_seconds+" seconds !", "danger");
|
|
|
|
|
2020-03-30 12:24:45 +00:00
|
|
|
setTimeout(() => {
|
2020-03-31 08:44:54 +00:00
|
|
|
ComunicWeb.common.system.reset();
|
2020-03-30 12:24:45 +00:00
|
|
|
}, num_seconds*1000);
|
2020-03-29 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Disconnect from server
|
|
|
|
*/
|
|
|
|
static async Disconnect() {
|
2020-03-29 16:32:05 +00:00
|
|
|
console.log("Disconnect from websocket");
|
2020-03-29 16:04:50 +00:00
|
|
|
|
2020-03-29 16:32:05 +00:00
|
|
|
// Disconnect, if reuired
|
|
|
|
if(this.hasOwnProperty("ws")) {
|
|
|
|
if(this.ws.readyState == WebSocket.OPEN)
|
|
|
|
this.ws.close()
|
|
|
|
delete this.ws
|
|
|
|
}
|
2020-03-29 16:04:50 +00:00
|
|
|
}
|
2020-03-30 12:52:43 +00:00
|
|
|
|
2020-03-31 14:25:05 +00:00
|
|
|
/**
|
|
|
|
* Send a request to the server through the socket
|
|
|
|
*
|
|
|
|
* @param {String} title The title of the request
|
|
|
|
* @param {any} data Information associated to the request
|
|
|
|
*/
|
|
|
|
static SendRequest(title, data) {
|
|
|
|
// Send request
|
|
|
|
return new Promise((res, err) => {
|
2020-04-01 16:45:29 +00:00
|
|
|
if(!this.hasOwnProperty("ws") || this.ws.readyState != WebSocket.OPEN)
|
2020-03-31 14:25:05 +00:00
|
|
|
throw new Error("WebSocket is not open!");
|
|
|
|
|
|
|
|
// Determine unique request ID
|
|
|
|
const req_id = "r-"+reqCounter++;
|
|
|
|
|
|
|
|
// Send the message
|
2020-04-01 12:30:04 +00:00
|
|
|
console.info("WS request", req_id, title, data);
|
2020-03-31 14:25:05 +00:00
|
|
|
this.ws.send(JSON.stringify(new WsMessage({
|
|
|
|
id: req_id,
|
|
|
|
title: title,
|
|
|
|
data: data
|
|
|
|
})))
|
|
|
|
|
|
|
|
// Add promise information to the queue
|
|
|
|
requests[req_id] = {
|
|
|
|
res: res,
|
|
|
|
err: err
|
|
|
|
};
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-03-30 12:52:43 +00:00
|
|
|
/**
|
|
|
|
* Process an incoming message
|
|
|
|
*
|
2020-03-31 09:38:09 +00:00
|
|
|
* @param {WsMessage} msg The incoming message
|
2020-03-30 12:52:43 +00:00
|
|
|
*/
|
|
|
|
static async ProcessMessage(msg) {
|
2020-03-31 09:38:09 +00:00
|
|
|
|
2020-04-01 12:30:04 +00:00
|
|
|
console.info("WS remote message", msg);
|
|
|
|
|
2020-03-31 09:38:09 +00:00
|
|
|
// Check if the message is not associated if any request
|
|
|
|
if(!msg.hasId)
|
|
|
|
this.ProcessDetachedMessage(msg)
|
|
|
|
|
|
|
|
else
|
2020-03-31 14:25:05 +00:00
|
|
|
this.ProcessResponse(msg);
|
2020-03-31 09:38:09 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process detached message
|
|
|
|
* @param {WsMessage} msg Incoming message
|
|
|
|
*/
|
|
|
|
static async ProcessDetachedMessage(msg) {
|
|
|
|
|
|
|
|
switch(msg.title) {
|
|
|
|
|
|
|
|
case "number_notifs":
|
|
|
|
SendEvent("newNumberNotifs", msg.data)
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "number_unread_conversations":
|
|
|
|
SendEvent("newNumberUnreadConvs", msg.data)
|
|
|
|
break;
|
2020-04-01 12:19:56 +00:00
|
|
|
|
|
|
|
case "new_conv_message":
|
|
|
|
SendEvent("newConvMessage", msg.data);
|
|
|
|
break;
|
2020-03-31 09:38:09 +00:00
|
|
|
|
2020-04-01 09:28:13 +00:00
|
|
|
default:
|
|
|
|
console.error("WS Unspported kind of message!", msg);
|
|
|
|
break;
|
2020-03-31 09:38:09 +00:00
|
|
|
}
|
|
|
|
|
2020-03-30 12:52:43 +00:00
|
|
|
}
|
2020-03-31 14:25:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Process response message
|
|
|
|
*
|
|
|
|
* @param {WsMessage} msg The message
|
|
|
|
*/
|
|
|
|
static ProcessResponse(msg) {
|
|
|
|
|
|
|
|
// Check for attached request
|
|
|
|
if(!requests.hasOwnProperty(msg.id)) {
|
|
|
|
console.error("WS error: received unattended message! ", msg)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const queue = requests[msg.id];
|
|
|
|
delete requests[msg.id];
|
|
|
|
|
|
|
|
// Check for error
|
|
|
|
if(msg.title !== "success") {
|
|
|
|
console.error("WS error", msg.data);
|
|
|
|
queue.err(msg)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// It is a success
|
|
|
|
queue.res(msg.data);
|
|
|
|
}
|
2020-04-01 08:51:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Register some events
|
|
|
|
document.addEventListener("incognitoStatusChanged", (e) => {
|
|
|
|
if(UserWebSocket.IsConnected)
|
|
|
|
ws("$main/set_incognito", {enable: e.detail.enabled})
|
|
|
|
})
|