+
+
Whiteboard information:
+
# connected users: 0
+
Smallest screen resolution: Unknown.
# msg. sent to server: 0
# msg. received from server: 0
diff --git a/src/js/classes/Point.js b/src/js/classes/Point.js
index 55f0717..4c8fd81 100644
--- a/src/js/classes/Point.js
+++ b/src/js/classes/Point.js
@@ -1,34 +1,41 @@
import { computeDist } from "../utils";
class Point {
+ /**
+ * @type {number}
+ */
+ #x;
+ get x() {
+ return this.#x;
+ }
+
+ /**
+ * @type {number}
+ */
+ #y;
+ get y() {
+ return this.#y;
+ }
+
+ /**
+ * @type {Point}
+ */
+ static #lastKnownPos = new Point(0, 0);
+ static get lastKnownPos() {
+ return Point.#lastKnownPos;
+ }
+
/**
* @param {number} x
* @param {number} y
*/
constructor(x, y) {
- /**
- * @type {number}
- * @private
- */
- this._x = x;
-
- /**
- * @type {number}
- * @private
- */
- this._y = y;
- }
-
- get x() {
- return this._x;
- }
-
- get y() {
- return this._y;
+ this.#x = x;
+ this.#y = y;
}
get isZeroZero() {
- return this._x === 0 && this._y === 0;
+ return this.#x === 0 && this.#y === 0;
}
/**
@@ -50,20 +57,14 @@ class Point {
y = touch.clientY - $("#mouseOverlay").offset().top;
} else {
// if it's a touchend event
- return Point._lastKnownPos;
+ return Point.#lastKnownPos;
}
}
- Point._lastKnownPos = new Point(x - epsilon, y - epsilon);
- return Point._lastKnownPos;
+ Point.#lastKnownPos = new Point(x - epsilon, y - epsilon);
+ return Point.#lastKnownPos;
}
- /**
- * @type {Point}
- * @private
- */
- static _lastKnownPos = new Point(0, 0);
-
/**
* Compute euclidean distance between points
*
diff --git a/src/js/const.js b/src/js/const.js
deleted file mode 100644
index 9645fb8..0000000
--- a/src/js/const.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export const POINTER_EVENT_THRESHOLD_MIN_DIST_DELTA = 1; // 1px
-export const POINTER_EVENT_THRESHOLD_MIN_TIME_DELTA = 10; // 1ms
diff --git a/src/js/icons.js b/src/js/icons.js
index c6bbf98..6c39955 100644
--- a/src/js/icons.js
+++ b/src/js/icons.js
@@ -18,6 +18,7 @@ import {
faExpandArrowsAlt,
faLock,
faLockOpen,
+ faInfoCircle,
} from "@fortawesome/free-solid-svg-icons";
import {
faSquare,
@@ -50,7 +51,8 @@ library.add(
faFileAlt,
faPlusSquare,
faLock,
- faLockOpen
+ faLockOpen,
+ faInfoCircle
);
dom.i2svg();
diff --git a/src/js/main.js b/src/js/main.js
index 221ecfd..c76b3d7 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -7,57 +7,64 @@ import { dom } from "@fortawesome/fontawesome-svg-core";
import pdfjsLib from "pdfjs-dist/webpack";
import shortcutFunctions from "./shortcutFunctions";
import ReadOnlyService from "./services/ReadOnlyService";
+import InfoService from "./services/InfoService";
+import { getQueryVariable, getSubDir } from "./utils";
+import ConfigService from "./services/ConfigService";
+
+let whiteboardId = getQueryVariable("whiteboardid");
+const randomid = getQueryVariable("randomid");
+if (randomid && !whiteboardId) {
+ //set random whiteboard on empty whiteboardid
+ whiteboardId = Array(2)
+ .fill(null)
+ .map(() => Math.random().toString(36).substr(2))
+ .join("");
+ const urlParams = new URLSearchParams(window.location.search);
+ urlParams.set("whiteboardid", whiteboardId);
+ window.location.search = urlParams;
+}
+
+whiteboardId = whiteboardId || "myNewWhiteboard";
+whiteboardId = unescape(encodeURIComponent(whiteboardId)).replace(/[^a-zA-Z0-9 ]/g, "");
+const myUsername = getQueryVariable("username") || "unknown" + (Math.random() + "").substring(2, 6);
+const accessToken = getQueryVariable("accesstoken") || "";
+
+// Custom Html Title
+const title = getQueryVariable("title");
+if (!title === false) {
+ document.title = decodeURIComponent(title);
+}
+
+const subdir = getSubDir();
+let signaling_socket;
function main() {
- var whiteboardId = getQueryVariable("whiteboardid");
- var randomid = getQueryVariable("randomid");
- if (randomid && !whiteboardId) {
- //set random whiteboard on empty whiteboardid
- whiteboardId = Array(2)
- .fill(null)
- .map(() => Math.random().toString(36).substr(2))
- .join("");
- const urlParams = new URLSearchParams(window.location.search);
- urlParams.set("whiteboardid", whiteboardId);
- window.location.search = urlParams;
- }
-
- whiteboardId = whiteboardId || "myNewWhiteboard";
- whiteboardId = unescape(encodeURIComponent(whiteboardId)).replace(/[^a-zA-Z0-9 ]/g, "");
- var myUsername = getQueryVariable("username");
- var accessToken = getQueryVariable("accesstoken");
- myUsername = myUsername || "unknown" + (Math.random() + "").substring(2, 6);
- accessToken = accessToken || "";
- var accessDenied = false;
-
- // Custom Html Title
- var title = getQueryVariable("title");
- if (!title === false) {
- document.title = decodeURIComponent(title);
- }
-
- var url = document.URL.substr(0, document.URL.lastIndexOf("/"));
- var signaling_socket = null;
- var urlSplit = url.split("/");
- var subdir = "";
- for (var i = 3; i < urlSplit.length; i++) {
- subdir = subdir + "/" + urlSplit[i];
- }
signaling_socket = io("", { path: subdir + "/ws-api" }); // Connect even if we are in a subdir behind a reverse proxy
signaling_socket.on("connect", function () {
console.log("Websocket connected!");
- let messageReceivedCount = 0;
+ signaling_socket.on("whiteboardConfig", (serverResponse) => {
+ ConfigService.initFromServer(serverResponse);
+ // Inti whiteboard only when we have the config from the server
+ initWhiteboard();
+ });
+
+ signaling_socket.on("whiteboardInfoUpdate", (info) => {
+ InfoService.updateInfoFromServer(info);
+ whiteboard.updateSmallestScreenResolution();
+ });
+
signaling_socket.on("drawToWhiteboard", function (content) {
whiteboard.handleEventsAndData(content, true);
- $("#messageReceivedCount")[0].innerText = String(messageReceivedCount++);
+ InfoService.incrementNbMessagesReceived();
});
signaling_socket.on("refreshUserBadges", function () {
whiteboard.refreshUserBadges();
});
+ let accessDenied = false;
signaling_socket.on("wrongAccessToken", function () {
if (!accessDenied) {
accessDenied = true;
@@ -65,17 +72,15 @@ function main() {
}
});
- signaling_socket.on("updateSmallestScreenResolution", function (widthHeight) {
- whiteboard.updateSmallestScreenResolution(widthHeight["w"], widthHeight["h"]);
- });
-
signaling_socket.emit("joinWhiteboard", {
wid: whiteboardId,
at: accessToken,
windowWidthHeight: { w: $(window).width(), h: $(window).height() },
});
});
+}
+function initWhiteboard() {
$(document).ready(function () {
// by default set in readOnly mode
ReadOnlyService.activateReadOnlyMode();
@@ -84,7 +89,6 @@ function main() {
$("#uploadWebDavBtn").show();
}
- let messageSentCount = 0;
whiteboard.loadWhiteboard("#whiteboardContainer", {
//Load the whiteboard
whiteboardId: whiteboardId,
@@ -97,7 +101,7 @@ function main() {
// }
content["at"] = accessToken;
signaling_socket.emit("drawToWhiteboard", content);
- $("#messageSentCount")[0].innerText = String(messageSentCount++);
+ InfoService.incrementNbMessagesSent();
},
});
@@ -382,6 +386,10 @@ function main() {
showBasicAlert("Copied Whiteboard-URL to clipboard.", { hideAfter: 2 });
});
+ $("#displayWhiteboardInfoBtn").click(() => {
+ InfoService.toggleDisplayInfo();
+ });
+
var btnsMini = false;
$("#minMaxBtn").click(function () {
if (!btnsMini) {
@@ -596,9 +604,15 @@ function main() {
whiteboard.refreshCursorAppearance();
if (process.env.NODE_ENV === "production") {
- ReadOnlyService.activateReadOnlyMode();
+ if (ConfigService.readOnlyOnWhiteboardLoad) ReadOnlyService.activateReadOnlyMode();
+ else ReadOnlyService.deactivateReadOnlyMode();
+
+ if (ConfigService.displayInfoOnWhiteboardLoad) InfoService.displayInfo();
+ else InfoService.hideInfo();
} else {
+ // in dev
ReadOnlyService.deactivateReadOnlyMode();
+ InfoService.displayInfo();
}
});
@@ -789,19 +803,6 @@ function main() {
}, 1000 * options.hideAfter);
}
}
-
- // get 'GET' parameter by variable name
- function getQueryVariable(variable) {
- var query = window.location.search.substring(1);
- var vars = query.split("&");
- for (var i = 0; i < vars.length; i++) {
- var pair = vars[i].split("=");
- if (pair[0] == variable) {
- return pair[1];
- }
- }
- return false;
- }
}
export default main;
diff --git a/src/js/services/ConfigService.js b/src/js/services/ConfigService.js
new file mode 100644
index 0000000..c00b70e
--- /dev/null
+++ b/src/js/services/ConfigService.js
@@ -0,0 +1,84 @@
+import { getThrottling } from "./ConfigService.utils";
+
+/**
+ * Class to hold the configuration sent by the backend
+ */
+class ConfigService {
+ /**
+ * @type {object}
+ */
+ #configFromServer = {};
+ get configFromServer() {
+ return this.#configFromServer;
+ }
+
+ /**
+ * @type {{displayInfo: boolean, setReadOnly: boolean}}
+ * @readonly
+ */
+ #onWhiteboardLoad = { setReadOnly: false, displayInfo: false };
+ get readOnlyOnWhiteboardLoad() {
+ return this.#onWhiteboardLoad.setReadOnly;
+ }
+ get displayInfoOnWhiteboardLoad() {
+ return this.#onWhiteboardLoad.displayInfo;
+ }
+
+ /**
+ * @type {boolean}
+ */
+ #showSmallestScreenIndicator = true;
+ get showSmallestScreenIndicator() {
+ return this.#showSmallestScreenIndicator;
+ }
+
+ /**
+ * @type {{minDistDelta: number, minTimeDelta: number}}
+ */
+ #pointerEventsThrottling = { minDistDelta: 0, minTimeDelta: 0 };
+ get pointerEventsThrottling() {
+ return this.#pointerEventsThrottling;
+ }
+
+ /**
+ * @type {number}
+ */
+ #refreshInfoInterval = 1000;
+ get refreshInfoInterval() {
+ return this.#refreshInfoInterval;
+ }
+
+ /**
+ * Init the service from the config sent by the server
+ *
+ * @param {object} configFromServer
+ */
+ initFromServer(configFromServer) {
+ this.#configFromServer = configFromServer;
+
+ const { common } = configFromServer;
+ const { onWhiteboardLoad, showSmallestScreenIndicator, performance } = common;
+
+ this.#onWhiteboardLoad = onWhiteboardLoad;
+ this.#showSmallestScreenIndicator = showSmallestScreenIndicator;
+ this.#refreshInfoInterval = 1000 / performance.refreshInfoFreq;
+
+ console.log("Whiteboard config from server:", configFromServer, "parsed:", this);
+ }
+
+ /**
+ * Refresh config that depends on the number of user connected to whiteboard
+ *
+ * @param {number} userCount
+ */
+ refreshUserCountDependant(userCount) {
+ const { configFromServer } = this;
+ const { common } = configFromServer;
+ const { performance } = common;
+ const { pointerEventsThrottling } = performance;
+
+ this.#pointerEventsThrottling = getThrottling(pointerEventsThrottling, userCount);
+ }
+}
+
+export default new ConfigService();
diff --git a/src/js/services/ConfigService.utils.js b/src/js/services/ConfigService.utils.js
new file mode 100644
index 0000000..1733880
--- /dev/null
+++ b/src/js/services/ConfigService.utils.js
@@ -0,0 +1,21 @@
+/**
+ * Helper to extract the correct throttling values based on the config and the number of user
+ *
+ * @param {Array.<{fromUserCount: number, minDistDelta: number, maxFreq: number}>} pointerEventsThrottling
+ * @param {number} userCount
+ * @return {{minDistDelta: number, minTimeDelta: number}}
+ */
+export function getThrottling(pointerEventsThrottling, userCount) {
+ let tmpOut = pointerEventsThrottling[0];
+ let lastDistToUserCount = userCount - tmpOut.fromUserCount;
+ if (lastDistToUserCount < 0) lastDistToUserCount = Number.MAX_VALUE;
+ for (const el of pointerEventsThrottling) {
+ const distToUserCount = userCount - el.fromUserCount;
+ if (el.fromUserCount <= userCount && distToUserCount <= lastDistToUserCount) {
+ tmpOut = el;
+ lastDistToUserCount = distToUserCount;
+ }
+ }
+
+ return { minDistDelta: tmpOut.minDistDelta, minTimeDelta: 1000 * (1 / tmpOut.maxFreq) };
+}
diff --git a/src/js/services/ConfigService.utils.test.js b/src/js/services/ConfigService.utils.test.js
new file mode 100644
index 0000000..acb96ca
--- /dev/null
+++ b/src/js/services/ConfigService.utils.test.js
@@ -0,0 +1,29 @@
+import { getThrottling } from "./ConfigService.utils";
+
+test("Simple throttling config", () => {
+ const throttling = [{ fromUserCount: 0, minDistDelta: 1, maxFreq: 1 }];
+
+ const target0 = { minDistDelta: 1, minTimeDelta: 1000 };
+ expect(getThrottling(throttling, 0)).toEqual(target0);
+
+ const target100 = { minDistDelta: 1, minTimeDelta: 1000 };
+ expect(getThrottling(throttling, 100)).toEqual(target100);
+});
+
+test("Complex throttling config", () => {
+ // mix ordering
+ const throttling = [
+ { fromUserCount: 100, minDistDelta: 100, maxFreq: 1 },
+ { fromUserCount: 0, minDistDelta: 1, maxFreq: 1 },
+ { fromUserCount: 50, minDistDelta: 50, maxFreq: 1 },
+ ];
+
+ const target0 = { minDistDelta: 1, minTimeDelta: 1000 };
+ expect(getThrottling(throttling, 0)).toEqual(target0);
+
+ const target50 = { minDistDelta: 50, minTimeDelta: 1000 };
+ expect(getThrottling(throttling, 50)).toEqual(target50);
+
+ const target100 = { minDistDelta: 100, minTimeDelta: 1000 };
+ expect(getThrottling(throttling, 100)).toEqual(target100);
+});
diff --git a/src/js/services/InfoService.js b/src/js/services/InfoService.js
new file mode 100644
index 0000000..162d6eb
--- /dev/null
+++ b/src/js/services/InfoService.js
@@ -0,0 +1,137 @@
+import ConfigService from "./ConfigService";
+
+/**
+ * Class the handle the information about the whiteboard
+ */
+class InfoService {
+ /**
+ * @type {boolean}
+ */
+ #infoAreDisplayed = false;
+ get infoAreDisplayed() {
+ return this.#infoAreDisplayed;
+ }
+
+ /**
+ * Holds the number of user connected to the server
+ *
+ * @type {number}
+ */
+ #nbConnectedUsers = -1;
+ get nbConnectedUsers() {
+ return this.#nbConnectedUsers;
+ }
+
+ /**
+ * @type {{w: number, h: number}}
+ */
+ #smallestScreenResolution = undefined;
+ get smallestScreenResolution() {
+ return this.#smallestScreenResolution;
+ }
+
+ /**
+ * @type {number}
+ */
+ #nbMessagesSent = 0;
+ get nbMessagesSent() {
+ return this.#nbMessagesSent;
+ }
+
+ /**
+ * @type {number}
+ */
+ #nbMessagesReceived = 0;
+ get nbMessagesReceived() {
+ return this.#nbMessagesReceived;
+ }
+
+ /**
+ * Holds the interval Id
+ * @type {number}
+ */
+ #refreshInfoIntervalId = undefined;
+ get refreshInfoIntervalId() {
+ return this.#refreshInfoIntervalId;
+ }
+
+ /**
+ * @param {number} nbConnectedUsers
+ * @param {{w: number, h: number}} smallestScreenResolution
+ */
+ updateInfoFromServer({ nbConnectedUsers, smallestScreenResolution = undefined }) {
+ if (this.#nbConnectedUsers !== nbConnectedUsers) {
+ // Refresh config service parameters on nb connected user change
+ ConfigService.refreshUserCountDependant(nbConnectedUsers);
+ }
+ this.#nbConnectedUsers = nbConnectedUsers;
+ if (smallestScreenResolution) {
+ this.#smallestScreenResolution = smallestScreenResolution;
+ }
+ }
+
+ incrementNbMessagesReceived() {
+ this.#nbMessagesReceived++;
+ }
+
+ incrementNbMessagesSent() {
+ this.#nbMessagesSent++;
+ }
+
+ refreshDisplayedInfo() {
+ const {
+ nbMessagesReceived,
+ nbMessagesSent,
+ nbConnectedUsers,
+ smallestScreenResolution: ssr,
+ } = this;
+ $("#messageReceivedCount")[0].innerText = String(nbMessagesReceived);
+ $("#messageSentCount")[0].innerText = String(nbMessagesSent);
+ $("#connectedUsersCount")[0].innerText = String(nbConnectedUsers);
+ $("#smallestScreenResolution")[0].innerText = ssr ? `(${ssr.w}, ${ssr.h})` : "Unknown";
+ }
+
+ /**
+ * Show the info div
+ */
+ displayInfo() {
+ $("#whiteboardInfoContainer").toggleClass("displayNone", false);
+ $("#displayWhiteboardInfoBtn").toggleClass("active", true);
+ this.#infoAreDisplayed = true;
+
+ this.refreshDisplayedInfo();
+ this.#refreshInfoIntervalId = setInterval(() => {
+ // refresh only on a specific interval to reduce
+ // refreshing cost
+ this.refreshDisplayedInfo();
+ }, ConfigService.refreshInfoInterval);
+ }
+
+ /**
+ * Hide the info div
+ */
+ hideInfo() {
+ $("#whiteboardInfoContainer").toggleClass("displayNone", true);
+ $("#displayWhiteboardInfoBtn").toggleClass("active", false);
+ this.#infoAreDisplayed = false;
+ const { refreshInfoIntervalId } = this;
+ if (refreshInfoIntervalId) {
+ clearInterval(refreshInfoIntervalId);
+ this.#refreshInfoIntervalId = undefined;
+ }
+ }
+
+ /**
+ * Switch between hiding and showing the info div
+ */
+ toggleDisplayInfo() {
+ const { infoAreDisplayed } = this;
+ if (infoAreDisplayed) {
+ this.hideInfo();
+ } else {
+ this.displayInfo();
+ }
+ }
+}
+
+export default new InfoService();
diff --git a/src/js/services/ReadOnlyService.js b/src/js/services/ReadOnlyService.js
index dd1568f..449c4c4 100644
--- a/src/js/services/ReadOnlyService.js
+++ b/src/js/services/ReadOnlyService.js
@@ -4,23 +4,27 @@
class ReadOnlyService {
/**
* @type {boolean}
- * @private
*/
- _readOnlyActive = true;
+ #readOnlyActive = true;
+ get readOnlyActive() {
+ return this.#readOnlyActive;
+ }
/**
* @type {object}
- * @private
*/
- _previousToolHtmlElem = null;
+ #previousToolHtmlElem = null;
+ get previousToolHtmlElem() {
+ return this.#previousToolHtmlElem;
+ }
/**
* Activate read-only mode
*/
activateReadOnlyMode() {
- this._readOnlyActive = true;
+ this.#readOnlyActive = true;
- this._previousToolHtmlElem = $(".whiteboard-tool.active");
+ this.#previousToolHtmlElem = $(".whiteboard-tool.active");
// switch to mouse tool to prevent the use of the
// other tools
@@ -36,7 +40,7 @@ class ReadOnlyService {
* Deactivate read-only mode
*/
deactivateReadOnlyMode() {
- this._readOnlyActive = false;
+ this.#readOnlyActive = false;
$(".whiteboard-tool").prop("disabled", false);
$(".whiteboard-edit-group > button").prop("disabled", false);
@@ -45,15 +49,8 @@ class ReadOnlyService {
$("#whiteboardLockBtn").hide();
// restore previously selected tool
- if (this._previousToolHtmlElem) this._previousToolHtmlElem.click();
- }
-
- /**
- * Get the read-only status
- * @returns {boolean}
- */
- get readOnlyActive() {
- return this._readOnlyActive;
+ const { previousToolHtmlElem } = this;
+ if (previousToolHtmlElem) previousToolHtmlElem.click();
}
}
diff --git a/src/js/services/ThrottlingService.js b/src/js/services/ThrottlingService.js
new file mode 100644
index 0000000..73c69b8
--- /dev/null
+++ b/src/js/services/ThrottlingService.js
@@ -0,0 +1,48 @@
+import Point from "../classes/Point";
+import { getCurrentTimeMs } from "../utils";
+import ConfigService from "./ConfigService";
+
+/**
+ * Class to handle all the throttling logic
+ */
+class ThrottlingService {
+ /**
+ * @type {number}
+ */
+ #lastSuccessTime = 0;
+ get lastSuccessTime() {
+ return this.#lastSuccessTime;
+ }
+
+ /**
+ * @type {Point}
+ */
+ #lastPointPosition = new Point(0, 0);
+ get lastPointPosition() {
+ return this.#lastPointPosition;
+ }
+
+ /**
+ * Helper to throttle events based on the configuration.
+ * Only if checks are ok, the onSuccess callback will be called.
+ *
+ * @param {Point} newPosition New point position to base the throttling on
+ * @param {function()} onSuccess Callback called when the throttling is successful
+ */
+ throttle(newPosition, onSuccess) {
+ const newTime = getCurrentTimeMs();
+ const { lastPointPosition, lastSuccessTime } = this;
+ if (newTime - lastSuccessTime > ConfigService.pointerEventsThrottling.minTimeDelta) {
+ if (
+ lastPointPosition.distTo(newPosition) >
+ ConfigService.pointerEventsThrottling.minDistDelta
+ ) {
+ onSuccess();
+ this.#lastPointPosition = newPosition;
+ this.#lastSuccessTime = newTime;
+ }
+ }
+ }
+}
+
+export default new ThrottlingService();
diff --git a/src/js/utils.js b/src/js/utils.js
index d5329d3..1e02d15 100644
--- a/src/js/utils.js
+++ b/src/js/utils.js
@@ -14,3 +14,31 @@ export function computeDist(p1, p2) {
export function getCurrentTimeMs() {
return new Date().getTime();
}
+
+/**
+ * get 'GET' parameter by variable name
+ * @param variable
+ * @return {boolean|*}
+ */
+export function getQueryVariable(variable) {
+ const query = window.location.search.substring(1);
+ const vars = query.split("&");
+ for (let i = 0; i < vars.length; i++) {
+ const pair = vars[i].split("=");
+ if (pair[0] === variable) {
+ return pair[1];
+ }
+ }
+ return false;
+}
+
+export function getSubDir() {
+ const url = document.URL.substr(0, document.URL.lastIndexOf("/"));
+ const urlSplit = url.split("/");
+ let subdir = "";
+ for (let i = 3; i < urlSplit.length; i++) {
+ subdir = subdir + "/" + urlSplit[i];
+ }
+
+ return subdir;
+}
diff --git a/src/js/whiteboard.js b/src/js/whiteboard.js
index e9a9673..89923f6 100644
--- a/src/js/whiteboard.js
+++ b/src/js/whiteboard.js
@@ -1,11 +1,9 @@
import { dom } from "@fortawesome/fontawesome-svg-core";
-import { getCurrentTimeMs } from "./utils";
import Point from "./classes/Point";
-import {
- POINTER_EVENT_THRESHOLD_MIN_DIST_DELTA,
- POINTER_EVENT_THRESHOLD_MIN_TIME_DELTA,
-} from "./const";
import ReadOnlyService from "./services/ReadOnlyService";
+import InfoService from "./services/InfoService";
+import ThrottlingService from "./services/ThrottlingService";
+import ConfigService from "./services/ConfigService";
const RAD_TO_DEG = 180.0 / Math.PI;
const DEG_TO_RAD = Math.PI / 180.0;
@@ -211,25 +209,15 @@ const whiteboard = {
const currentPos = Point.fromEvent(e);
- const pointerSentTime = getCurrentTimeMs();
- if (
- pointerSentTime - _this.lastPointerSentTime >
- POINTER_EVENT_THRESHOLD_MIN_TIME_DELTA
- ) {
- if (
- _this.lastPointerPosition.distTo(currentPos) >
- POINTER_EVENT_THRESHOLD_MIN_DIST_DELTA
- ) {
- _this.lastPointerSentTime = pointerSentTime;
- _this.lastPointerPosition = currentPos;
- _this.sendFunction({
- t: "cursor",
- event: "move",
- d: [currentPos.x, currentPos.y],
- username: _this.settings.username,
- });
- }
- }
+ ThrottlingService.throttle(currentPos, () => {
+ _this.lastPointerPosition = currentPos;
+ _this.sendFunction({
+ t: "cursor",
+ event: "move",
+ d: [currentPos.x, currentPos.y],
+ username: _this.settings.username,
+ });
+ });
});
_this.mouseOverlay.on("mousemove touchmove", function (e) {
@@ -363,7 +351,7 @@ const whiteboard = {
```
```
@@ -543,23 +531,15 @@ const whiteboard = {
_this.prevPos = currentPos;
});
- const pointerSentTime = getCurrentTimeMs();
- if (pointerSentTime - _this.lastPointerSentTime > POINTER_EVENT_THRESHOLD_MIN_TIME_DELTA) {
- const newPointerPosition = currentPos;
- if (
- _this.lastPointerPosition.distTo(newPointerPosition) >
- POINTER_EVENT_THRESHOLD_MIN_DIST_DELTA
- ) {
- _this.lastPointerSentTime = pointerSentTime;
- _this.lastPointerPosition = newPointerPosition;
- _this.sendFunction({
- t: "cursor",
- event: "move",
- d: [newPointerPosition.x, newPointerPosition.y],
- username: _this.settings.username,
- });
- }
- }
+ ThrottlingService.throttle(currentPos, () => {
+ _this.lastPointerPosition = currentPos;
+ _this.sendFunction({
+ t: "cursor",
+ event: "move",
+ d: [currentPos.x, currentPos.y],
+ username: _this.settings.username,
+ });
+ });
},
triggerMouseOver: function () {
var _this = this;
@@ -876,28 +856,17 @@ const whiteboard = {
currX += textBox.width() - 4;
}
- const pointerSentTime = getCurrentTimeMs();
const newPointerPosition = new Point(currX, currY);
- // At least 100 ms between messages to reduce server load
- if (
- pointerSentTime - _this.lastPointerSentTime >
- POINTER_EVENT_THRESHOLD_MIN_TIME_DELTA
- ) {
- // Minimal distance between messages to reduce server load
- if (
- _this.lastPointerPosition.distTo(newPointerPosition) >
- POINTER_EVENT_THRESHOLD_MIN_DIST_DELTA
- ) {
- _this.lastPointerSentTime = pointerSentTime;
- _this.lastPointerPosition = newPointerPosition;
- _this.sendFunction({
- t: "cursor",
- event: "move",
- d: [newPointerPosition.x, newPointerPosition.y],
- username: _this.settings.username,
- });
- }
- }
+
+ ThrottlingService.throttle(newPointerPosition, () => {
+ _this.lastPointerPosition = newPointerPosition;
+ _this.sendFunction({
+ t: "cursor",
+ event: "move",
+ d: [newPointerPosition.x, newPointerPosition.y],
+ username: _this.settings.username,
+ });
+ });
});
this.textContainer.append(textBox);
textBox.draggable({
@@ -1061,21 +1030,26 @@ const whiteboard = {
_this.setTextboxFontColor(_this.latestActiveTextBoxId, color);
}
},
- updateSmallestScreenResolution(width, height) {
- this.backgroundGrid.empty();
- if (width < $(window).width() || height < $(window).height()) {
- this.backgroundGrid.append(
- '
'
- );
- this.backgroundGrid.append(
- '
smallest screen participating
'
- );
+ updateSmallestScreenResolution() {
+ const { smallestScreenResolution } = InfoService;
+ const { showSmallestScreenIndicator } = ConfigService;
+ if (showSmallestScreenIndicator && smallestScreenResolution) {
+ const { w: width, h: height } = smallestScreenResolution;
+ this.backgroundGrid.empty();
+ if (width < $(window).width() || height < $(window).height()) {
+ this.backgroundGrid.append(
+ '
'
+ );
+ this.backgroundGrid.append(
+ '
smallest screen participating
'
+ );
+ }
}
},
handleEventsAndData: function (content, isNewData, doneCallback) {