refacto: handling of smallest screen size as a whiteboard info

* Also started a bit of config handling cleaning
This commit is contained in:
Florent Chehab 2020-05-10 16:43:11 +02:00
parent 685caffd43
commit 4476ce3284
No known key found for this signature in database
GPG Key ID: 9A0CE018889EA246
7 changed files with 153 additions and 105 deletions

View File

@ -1,4 +1,8 @@
const config = require("./config");
class WhiteboardServerSideInfo { class WhiteboardServerSideInfo {
static defaultScreenResolution = { w: 1000, h: 1000 };
constructor() { constructor() {
/** /**
* @type {number} * @type {number}
@ -6,6 +10,12 @@ class WhiteboardServerSideInfo {
*/ */
this._nbConnectedUsers = 0; this._nbConnectedUsers = 0;
/**
* @type {Map<int, {w: number, h: number}>}
* @private
*/
this._screenResolutionByClients = new Map();
/** /**
* Variable to tell if these info have been sent or not * Variable to tell if these info have been sent or not
* *
@ -29,8 +39,37 @@ class WhiteboardServerSideInfo {
return this._nbConnectedUsers > 0; return this._nbConnectedUsers > 0;
} }
asObject() { /**
return { nbConnectedUsers: this._nbConnectedUsers }; * Store information about the client's screen resolution
*
* @param {number} clientId
* @param {number} w client's width
* @param {number} h client's hight
*/
setScreenResolutionForClient(clientId, { w, h }) {
this._screenResolutionByClients.set(clientId, { w, h });
this._hasNonSentUpdates = true;
}
/**
* Delete the stored information about the client's screen resoltion
* @param clientId
*/
deleteScreenResolutionOfClient(clientId) {
this._screenResolutionByClients.delete(clientId);
this._hasNonSentUpdates = true;
}
/**
* Get the smallest client's screen size on a whiteboard
* @return {{w: number, h: number}}
*/
getSmallestScreenResolution() {
const { _screenResolutionByClients: resolutions } = this;
return {
w: Math.min(...Array.from(resolutions.values()).map((res) => res.w)),
h: Math.min(...Array.from(resolutions.values()).map((res) => res.h)),
};
} }
infoWasSent() { infoWasSent() {
@ -40,6 +79,18 @@ class WhiteboardServerSideInfo {
shouldSendInfo() { shouldSendInfo() {
return this._hasNonSentUpdates; return this._hasNonSentUpdates;
} }
asObject() {
const out = {
nbConnectedUsers: this._nbConnectedUsers,
};
if (!config.disableSmallestScreen) {
out.smallestScreenResolution = this.getSmallestScreenResolution();
}
return out;
}
} }
module.exports = WhiteboardServerSideInfo; module.exports = WhiteboardServerSideInfo;

View File

@ -1,5 +1,45 @@
const { getArgs } = require("./utils");
const config = { const config = {
accessToken: "",
disableSmallestScreen: false,
webdav: false,
whiteboardInfoBroadcastFreq: 1, // once per second whiteboardInfoBroadcastFreq: 1, // once per second
}; };
/**
* Update the config based on the CLI args
* @param {object} startArgs
*/
function updateConfigFromStartArgs(startArgs) {
if (startArgs["accesstoken"]) {
config.accessToken = startArgs["accesstoken"];
}
if (startArgs["disablesmallestscreen"]) {
config.disableSmallestScreen = true;
}
if (startArgs["webdav"]) {
config.webdav = true;
}
}
/**
* Update the config based on the env variables
*/
function updateConfigFromEnv() {
if (process.env.accesstoken) {
config.accessToken = process.env.accesstoken;
}
if (process.env.disablesmallestscreen) {
config.disablesmallestscreen = true;
}
if (process.env.webdav) {
config.webdav = true;
}
}
updateConfigFromEnv();
updateConfigFromStartArgs(getArgs());
module.exports = config; module.exports = config;

View File

@ -1,13 +1,10 @@
const path = require("path"); const path = require("path");
const { getArgs } = require("./utils");
const config = require("./config"); const config = require("./config");
const WhiteboardServerSideInfo = require("./WhiteboardServerSideInfo"); const WhiteboardServerSideInfo = require("./WhiteboardServerSideInfo");
function startBackendServer(port) { function startBackendServer(port) {
var accessToken = ""; //Can be set here or as start parameter (node server.js --accesstoken=MYTOKEN) console.info("Starting backend server with config", config);
var disableSmallestScreen = false; //Can be set to true if you dont want to show (node server.js --disablesmallestscreen=true)
var webdav = false; //Can be set to true if you want to allow webdav save (node server.js --webdav=true)
var fs = require("fs-extra"); var fs = require("fs-extra");
var express = require("express"); var express = require("express");
@ -29,36 +26,8 @@ function startBackendServer(port) {
server.listen(port); server.listen(port);
var io = require("socket.io")(server, { path: "/ws-api" }); var io = require("socket.io")(server, { path: "/ws-api" });
console.log("Webserver & socketserver running on port:" + port); console.log("Webserver & socketserver running on port:" + port);
if (process.env.accesstoken) {
accessToken = process.env.accesstoken;
}
if (process.env.disablesmallestscreen) {
disablesmallestscreen = true;
}
if (process.env.webdav) {
webdav = true;
}
var startArgs = getArgs(); const { accessToken, webdav } = config;
if (startArgs["accesstoken"]) {
accessToken = startArgs["accesstoken"];
}
if (startArgs["disablesmallestscreen"]) {
disableSmallestScreen = true;
}
if (startArgs["webdav"]) {
webdav = true;
}
if (accessToken !== "") {
console.log("AccessToken set to: " + accessToken);
}
if (disableSmallestScreen) {
console.log("Disabled showing smallest screen resolution!");
}
if (webdav) {
console.log("Webdav save is enabled!");
}
app.get("/api/loadwhiteboard", function (req, res) { app.get("/api/loadwhiteboard", function (req, res) {
var wid = req["query"]["wid"]; var wid = req["query"]["wid"];
@ -207,8 +176,6 @@ function startBackendServer(port) {
} }
} }
var smallestScreenResolutions = {};
/** /**
* @type {Map<string, WhiteboardServerSideInfo>} * @type {Map<string, WhiteboardServerSideInfo>}
*/ */
@ -229,20 +196,15 @@ function startBackendServer(port) {
io.on("connection", function (socket) { io.on("connection", function (socket) {
var whiteboardId = null; var whiteboardId = null;
socket.on("disconnect", function () { socket.on("disconnect", function () {
if ( const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
smallestScreenResolutions &&
smallestScreenResolutions[whiteboardId] && if (socket && socket.id) {
socket && whiteboardServerSideInfo.deleteScreenResolutionOfClient(socket.id);
socket.id
) {
delete smallestScreenResolutions[whiteboardId][socket.id];
} }
const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
whiteboardServerSideInfo.decrementNbConnectedUsers(); whiteboardServerSideInfo.decrementNbConnectedUsers();
if (whiteboardServerSideInfo.hasConnectedUser()) { if (whiteboardServerSideInfo.hasConnectedUser()) {
socket.compress(false).broadcast.emit("refreshUserBadges", null); //Removes old user Badges socket.compress(false).broadcast.emit("refreshUserBadges", null); //Removes old user Badges
sendSmallestScreenResolution();
} else { } else {
infoByWhiteboard.delete(whiteboardId); infoByWhiteboard.delete(whiteboardId);
} }
@ -269,14 +231,10 @@ function startBackendServer(port) {
const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId); const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
whiteboardServerSideInfo.incrementNbConnectedUsers(); whiteboardServerSideInfo.incrementNbConnectedUsers();
whiteboardServerSideInfo.setScreenResolutionForClient(
smallestScreenResolutions[whiteboardId] = smallestScreenResolutions[whiteboardId] socket.id,
? smallestScreenResolutions[whiteboardId] content["windowWidthHeight"] || WhiteboardServerSideInfo.defaultScreenResolution
: {}; );
smallestScreenResolutions[whiteboardId][socket.id] = content[
"windowWidthHeight"
] || { w: 10000, h: 10000 };
sendSmallestScreenResolution();
} else { } else {
socket.emit("wrongAccessToken", true); socket.emit("wrongAccessToken", true);
} }
@ -284,38 +242,14 @@ function startBackendServer(port) {
socket.on("updateScreenResolution", function (content) { socket.on("updateScreenResolution", function (content) {
content = escapeAllContentStrings(content); content = escapeAllContentStrings(content);
if ( if (accessToken === "" || accessToken == content["at"]) {
smallestScreenResolutions[whiteboardId] && const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
(accessToken === "" || accessToken == content["at"]) whiteboardServerSideInfo.setScreenResolutionForClient(
) { socket.id,
smallestScreenResolutions[whiteboardId][socket.id] = content[ content["windowWidthHeight"] || WhiteboardServerSideInfo.defaultScreenResolution
"windowWidthHeight" );
] || { w: 10000, h: 10000 };
sendSmallestScreenResolution();
} }
}); });
function sendSmallestScreenResolution() {
if (disableSmallestScreen) {
return;
}
var smallestWidth = 10000;
var smallestHeight = 10000;
for (var i in smallestScreenResolutions[whiteboardId]) {
smallestWidth =
smallestWidth > smallestScreenResolutions[whiteboardId][i]["w"]
? smallestScreenResolutions[whiteboardId][i]["w"]
: smallestWidth;
smallestHeight =
smallestHeight > smallestScreenResolutions[whiteboardId][i]["h"]
? smallestScreenResolutions[whiteboardId][i]["h"]
: smallestHeight;
}
io.to(whiteboardId).emit("updateSmallestScreenResolution", {
w: smallestWidth,
h: smallestHeight,
});
}
}); });
//Prevent cross site scripting (xss) //Prevent cross site scripting (xss)

View File

@ -254,6 +254,7 @@
<div id="whiteboardInfoContainer"> <div id="whiteboardInfoContainer">
<p><b>Whiteboard information:</b></p> <p><b>Whiteboard information:</b></p>
<p># connected users: <i id="connectedUsersCount">0</i></p> <p># connected users: <i id="connectedUsersCount">0</i></p>
<p>Smallest screen resolution: <i id="smallestScreenResolution">Unknown.</i></p>
<p># msg. sent to server: <i id="messageSentCount">0</i></p> <p># msg. sent to server: <i id="messageSentCount">0</i></p>
<p># msg. received from server: <i id="messageReceivedCount">0</i></p> <p># msg. received from server: <i id="messageReceivedCount">0</i></p>
</div> </div>

View File

@ -51,6 +51,7 @@ function main() {
signaling_socket.on("whiteboardInfoUpdate", (info) => { signaling_socket.on("whiteboardInfoUpdate", (info) => {
InfoService.updateInfoFromServer(info); InfoService.updateInfoFromServer(info);
whiteboard.updateSmallestScreenResolution();
}); });
signaling_socket.on("drawToWhiteboard", function (content) { signaling_socket.on("drawToWhiteboard", function (content) {
@ -69,10 +70,6 @@ function main() {
} }
}); });
signaling_socket.on("updateSmallestScreenResolution", function (widthHeight) {
whiteboard.updateSmallestScreenResolution(widthHeight["w"], widthHeight["h"]);
});
signaling_socket.emit("joinWhiteboard", { signaling_socket.emit("joinWhiteboard", {
wid: whiteboardId, wid: whiteboardId,
at: accessToken, at: accessToken,

View File

@ -20,6 +20,13 @@ class InfoService {
*/ */
_nbConnectedUsers = 0; _nbConnectedUsers = 0;
/**
*
* @type {{w: number, h: number}}
* @private
*/
_smallestScreenResolution = undefined;
/** /**
* @type {number} * @type {number}
* @private * @private
@ -41,9 +48,20 @@ class InfoService {
/** /**
* @param {number} nbConnectedUsers * @param {number} nbConnectedUsers
* @param {{w: number, h: number}} smallestScreenResolution
*/ */
updateInfoFromServer({ nbConnectedUsers }) { updateInfoFromServer({ nbConnectedUsers, smallestScreenResolution = undefined }) {
this._nbConnectedUsers = nbConnectedUsers; this._nbConnectedUsers = nbConnectedUsers;
if (smallestScreenResolution) {
this._smallestScreenResolution = smallestScreenResolution;
}
}
/**
* @returns {(undefined|{w: number, h: number})}
*/
get smallestScreenResolution() {
return this._smallestScreenResolution;
} }
incrementNbMessagesReceived() { incrementNbMessagesReceived() {
@ -58,6 +76,8 @@ class InfoService {
$("#messageReceivedCount")[0].innerText = String(this._nbMessagesReceived); $("#messageReceivedCount")[0].innerText = String(this._nbMessagesReceived);
$("#messageSentCount")[0].innerText = String(this._nbMessagesSent); $("#messageSentCount")[0].innerText = String(this._nbMessagesSent);
$("#connectedUsersCount")[0].innerText = String(this._nbConnectedUsers); $("#connectedUsersCount")[0].innerText = String(this._nbConnectedUsers);
const { _smallestScreenResolution: ssr } = this;
$("#smallestScreenResolution")[0].innerText = ssr ? `(${ssr.w}, ${ssr.h})` : "Unknown";
} }
displayInfo() { displayInfo() {

View File

@ -6,6 +6,7 @@ import {
POINTER_EVENT_THRESHOLD_MIN_TIME_DELTA, POINTER_EVENT_THRESHOLD_MIN_TIME_DELTA,
} from "./const"; } from "./const";
import ReadOnlyService from "./services/ReadOnlyService"; import ReadOnlyService from "./services/ReadOnlyService";
import InfoService from "./services/InfoService";
const RAD_TO_DEG = 180.0 / Math.PI; const RAD_TO_DEG = 180.0 / Math.PI;
const DEG_TO_RAD = Math.PI / 180.0; const DEG_TO_RAD = Math.PI / 180.0;
@ -363,7 +364,7 @@ const whiteboard = {
```<div class="dragMe" style="position:absolute; left: ${left}px; top: ${top}px; width: ${width}px; border: 2px dotted gray; overflow: hidden; height: ${height}px;" cursor:move;"> ```<div class="dragMe" style="position:absolute; left: ${left}px; top: ${top}px; width: ${width}px; border: 2px dotted gray; overflow: hidden; height: ${height}px;" cursor:move;">
<canvas style="cursor:move; position:absolute; top:0px; left:0px;" width="${width}" height="${height}"/> <canvas style="cursor:move; position:absolute; top:0px; left:0px;" width="${width}" height="${height}"/>
<div style="position:absolute; right:5px; top:3px;"> <div style="position:absolute; right:5px; top:3px;">
<button draw="1" style="margin: 0px 0px; background: #03a9f4; padding: 5px; margin-top: 3px; color: white;" class="addToCanvasBtn btn btn-default">Drop</button> <button draw="1" style="margin: 0px 0px; background: #03a9f4; padding: 5px; margin-top: 3px; color: white;" class="addToCanvasBtn btn btn-default">Drop</button>
<button style="margin: 0px 0px; background: #03a9f4; padding: 5px; margin-top: 3px; color: white;" class="xCanvasBtn btn btn-default">x</button> <button style="margin: 0px 0px; background: #03a9f4; padding: 5px; margin-top: 3px; color: white;" class="xCanvasBtn btn btn-default">x</button>
</div> </div>
</div>``` </div>```
@ -1061,21 +1062,25 @@ const whiteboard = {
_this.setTextboxFontColor(_this.latestActiveTextBoxId, color); _this.setTextboxFontColor(_this.latestActiveTextBoxId, color);
} }
}, },
updateSmallestScreenResolution(width, height) { updateSmallestScreenResolution() {
this.backgroundGrid.empty(); const { smallestScreenResolution } = InfoService;
if (width < $(window).width() || height < $(window).height()) { if (smallestScreenResolution) {
this.backgroundGrid.append( const { w: width, h: height } = smallestScreenResolution;
'<div style="position:absolute; left:0px; top:0px; border-right:3px dotted black; border-bottom:3px dotted black; width:' + this.backgroundGrid.empty();
width + if (width < $(window).width() || height < $(window).height()) {
"px; height:" + this.backgroundGrid.append(
height + '<div style="position:absolute; left:0px; top:0px; border-right:3px dotted black; border-bottom:3px dotted black; width:' +
'px;"></div>' width +
); "px; height:" +
this.backgroundGrid.append( height +
'<div style="position:absolute; left:' + 'px;"></div>'
(width + 5) + );
'px; top:0px;">smallest screen participating</div>' this.backgroundGrid.append(
); '<div style="position:absolute; left:' +
(width + 5) +
'px; top:0px;">smallest screen participating</div>'
);
}
} }
}, },
handleEventsAndData: function (content, isNewData, doneCallback) { handleEventsAndData: function (content, isNewData, doneCallback) {