Index: lams_build/conf/whiteboard/scripts/s_whiteboard.js =================================================================== diff -u -r1cb71fb7cfd13ce1de802d0a069ebe849466a7fc -r63061fed615977a3a7e768fa11cf4e7f0db9dade --- lams_build/conf/whiteboard/scripts/s_whiteboard.js (.../s_whiteboard.js) (revision 1cb71fb7cfd13ce1de802d0a069ebe849466a7fc) +++ lams_build/conf/whiteboard/scripts/s_whiteboard.js (.../s_whiteboard.js) (revision 63061fed615977a3a7e768fa11cf4e7f0db9dade) @@ -59,6 +59,7 @@ if (!savedUndos[wid]) { savedUndos[wid] = []; } + console.log("undo wid: " + wid, savedUndos[wid]); let savedBoard = this.loadStoredData(wid); for (var i = savedUndos[wid].length - 1; i >= 0; i--) { if (savedUndos[wid][i]["username"] == username) { @@ -161,6 +162,15 @@ return; } savedBoards[targetWid] = sourceData.slice(); + + // LAMS: after load prefix author so his steps can not be undone + for (var i = 0; i < savedBoards[targetWid].length; i++) { + let username = savedBoards[targetWid][i]["username"]; + if (username && !username.startsWith('authored-')) { + savedBoards[targetWid][i]["username"] = 'authored-' + username; + } + } + this.saveToDB(targetWid); }, saveData: function(wid, data, processEmbeddedImages) { Index: lams_build/conf/whiteboard/src/js/whiteboard.js =================================================================== diff -u --- lams_build/conf/whiteboard/src/js/whiteboard.js (revision 0) +++ lams_build/conf/whiteboard/src/js/whiteboard.js (revision 63061fed615977a3a7e768fa11cf4e7f0db9dade) @@ -0,0 +1,1523 @@ +import { dom } from "@fortawesome/fontawesome-svg-core"; +import Point from "./classes/Point"; +import ReadOnlyService from "./services/ReadOnlyService"; +import InfoService from "./services/InfoService"; +import ThrottlingService from "./services/ThrottlingService"; +import ConfigService from "./services/ConfigService"; +import html2canvas from "html2canvas"; + +const RAD_TO_DEG = 180.0 / Math.PI; +const DEG_TO_RAD = Math.PI / 180.0; +const _45_DEG_IN_RAD = 45 * DEG_TO_RAD; + +const whiteboard = { + canvas: null, + ctx: null, + drawcolor: "black", + previousToolHtmlElem: null, // useful for handling read-only mode + tool: "mouse", + thickness: 4, + /** + * @type Point + */ + prevPos: new Point(0, 0), + /** + * @type Point + */ + startCoords: new Point(0, 0), + drawFlag: false, + oldGCO: null, + mouseover: false, + lineCap: "round", //butt, square + backgroundGrid: null, + canvasElement: null, + cursorContainer: null, + imgContainer: null, + svgContainer: null, //For draw prev + mouseOverlay: null, + ownCursor: null, + penSmoothLastCoords: [], + svgLine: null, + svgRect: null, + svgCirle: null, + drawBuffer: [], + undoBuffer: [], + drawId: 0, //Used for undo/redo functions + imgDragActive: false, + latestActiveTextBoxId: false, //The id of the latest clicked Textbox (for font and color change) + pressedKeys: {}, + settings: { + whiteboardId: "0", + username: "unknown", + sendFunction: null, + backgroundGridUrl: "./images/gb_grid.png", + }, + lastPointerSentTime: 0, + /** + * @type Point + */ + lastPointerPosition: new Point(0, 0), + loadWhiteboard: function (whiteboardContainer, newSettings) { + const svgns = "http://www.w3.org/2000/svg"; + const _this = this; + for (const i in newSettings) { + this.settings[i] = newSettings[i]; + } + this.settings["username"] = this.settings["username"].replace(/[^0-9a-z]/gi, ""); + + //background grid (repeating image) and smallest screen indication + _this.backgroundGrid = $( + `
` + ); + // container for background images + _this.imgContainer = $( + '' + ); + // whiteboard canvas + _this.canvasElement = $( + '' + ); + // SVG container holding drawing or moving previews + _this.svgContainer = $( + '' + ); + // drag and drop indicator, hidden by default + _this.dropIndicator = $( + ' ' + ); + // container for other users cursors + _this.cursorContainer = $( + '' + ); + // container for texts by users + _this.textContainer = $( + '' + ); + // mouse overlay for draw callbacks + _this.mouseOverlay = $( + '' + ); + + $(whiteboardContainer) + .append(_this.backgroundGrid) + .append(_this.imgContainer) + .append(_this.canvasElement) + .append(_this.svgContainer) + .append(_this.dropIndicator) + .append(_this.cursorContainer) + .append(_this.textContainer) + .append(_this.mouseOverlay); + + // render newly added icons + dom.i2svg(); + + this.canvas = $("#whiteboardCanvas")[0]; + this.canvas.height = $(window).height(); + this.canvas.width = $(window).width(); + this.ctx = this.canvas.getContext("2d"); + this.oldGCO = this.ctx.globalCompositeOperation; + + window.addEventListener("resize", function () { + // Handle resize + const dbCp = JSON.parse(JSON.stringify(_this.drawBuffer)); // Copy the buffer + _this.canvas.width = $(window).width(); + _this.canvas.height = $(window).height(); // Set new canvas height + _this.drawBuffer = []; + _this.textContainer.empty(); + _this.loadData(dbCp); // draw old content in + }); + + $(_this.mouseOverlay).on("mousedown touchstart", function (e) { + _this.mousedown(e); + }); + + _this.mousedown = function (e) { + if (_this.imgDragActive || _this.drawFlag) { + return; + } + if (ReadOnlyService.readOnlyActive) return; + + _this.drawFlag = true; + + const currentPos = Point.fromEvent(e); + + if (_this.tool === "pen") { + _this.penSmoothLastCoords = [ + currentPos.x, + currentPos.y, + currentPos.x, + currentPos.y, + currentPos.x, + currentPos.y, + ]; + } else if (_this.tool === "eraser") { + _this.drawEraserLine( + currentPos.x, + currentPos.y, + currentPos.x, + currentPos.y, + _this.thickness + ); + _this.sendFunction({ + t: _this.tool, + d: [currentPos.x, currentPos.y, currentPos.x, currentPos.y], + th: _this.thickness, + }); + } else if (_this.tool === "line") { + _this.startCoords = currentPos; + _this.svgLine = document.createElementNS(svgns, "line"); + _this.svgLine.setAttribute("stroke", "gray"); + _this.svgLine.setAttribute("stroke-dasharray", "5, 5"); + _this.svgLine.setAttribute("x1", currentPos.x); + _this.svgLine.setAttribute("y1", currentPos.y); + _this.svgLine.setAttribute("x2", currentPos.x); + _this.svgLine.setAttribute("y2", currentPos.y); + _this.svgContainer.append(_this.svgLine); + } else if (_this.tool === "rect" || _this.tool === "recSelect") { + _this.svgContainer.find("rect").remove(); + _this.svgRect = document.createElementNS(svgns, "rect"); + _this.svgRect.setAttribute("stroke", "gray"); + _this.svgRect.setAttribute("stroke-dasharray", "5, 5"); + _this.svgRect.setAttribute("style", "fill-opacity:0.0;"); + _this.svgRect.setAttribute("x", currentPos.x); + _this.svgRect.setAttribute("y", currentPos.y); + _this.svgRect.setAttribute("width", 0); + _this.svgRect.setAttribute("height", 0); + _this.svgContainer.append(_this.svgRect); + _this.startCoords = currentPos; + } else if (_this.tool === "circle") { + _this.svgCirle = document.createElementNS(svgns, "circle"); + _this.svgCirle.setAttribute("stroke", "gray"); + _this.svgCirle.setAttribute("stroke-dasharray", "5, 5"); + _this.svgCirle.setAttribute("style", "fill-opacity:0.0;"); + _this.svgCirle.setAttribute("cx", currentPos.x); + _this.svgCirle.setAttribute("cy", currentPos.y); + _this.svgCirle.setAttribute("r", 0); + _this.svgContainer.append(_this.svgCirle); + _this.startCoords = currentPos; + } + + _this.prevPos = currentPos; + }; + + _this.textContainer.on("mousemove touchmove", function (e) { + e.preventDefault(); + + if (_this.imgDragActive || !$(e.target).hasClass("textcontainer")) { + return; + } + if (ReadOnlyService.readOnlyActive) return; + + const currentPos = Point.fromEvent(e); + + 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) { + e.preventDefault(); + if (ReadOnlyService.readOnlyActive) return; + _this.triggerMouseMove(e); + }); + + _this.mouseOverlay.on("mouseup touchend touchcancel", function (e) { + _this.mouseup(e); + }); + + _this.mouseup = function (e) { + if (_this.imgDragActive) { + return; + } + if (ReadOnlyService.readOnlyActive) return; + _this.drawFlag = false; + _this.drawId++; + _this.ctx.globalCompositeOperation = _this.oldGCO; + + let currentPos = Point.fromEvent(e); + + if (currentPos.isZeroZero) { + _this.sendFunction({ + t: "cursor", + event: "out", + username: _this.settings.username, + }); + } + + if (_this.tool === "line") { + if (_this.pressedKeys.shift) { + currentPos = _this.getRoundedAngles(currentPos); + } + _this.drawPenLine( + currentPos.x, + currentPos.y, + _this.startCoords.x, + _this.startCoords.y, + _this.drawcolor, + _this.thickness + ); + _this.sendFunction({ + t: _this.tool, + d: [currentPos.x, currentPos.y, _this.startCoords.x, _this.startCoords.y], + c: _this.drawcolor, + th: _this.thickness, + }); + _this.svgContainer.find("line").remove(); + } else if (_this.tool === "pen") { + _this.drawId--; + _this.pushPointSmoothPen(currentPos.x, currentPos.y); + _this.drawId++; + } else if (_this.tool === "rect") { + if (_this.pressedKeys.shift) { + if ( + (currentPos.x - _this.startCoords.x) * + (currentPos.y - _this.startCoords.y) > + 0 + ) { + currentPos = new Point( + currentPos.x, + _this.startCoords.y + (currentPos.x - _this.startCoords.x) + ); + } else { + currentPos = new Point( + currentPos.x, + _this.startCoords.y - (currentPos.x - _this.startCoords.x) + ); + } + } + _this.drawRec( + _this.startCoords.x, + _this.startCoords.y, + currentPos.x, + currentPos.y, + _this.drawcolor, + _this.thickness + ); + _this.sendFunction({ + t: _this.tool, + d: [_this.startCoords.x, _this.startCoords.y, currentPos.x, currentPos.y], + c: _this.drawcolor, + th: _this.thickness, + }); + _this.svgContainer.find("rect").remove(); + } else if (_this.tool === "circle") { + const r = currentPos.distTo(_this.startCoords); + _this.drawCircle( + _this.startCoords.x, + _this.startCoords.y, + r, + _this.drawcolor, + _this.thickness + ); + _this.sendFunction({ + t: _this.tool, + d: [_this.startCoords.x, _this.startCoords.y, r], + c: _this.drawcolor, + th: _this.thickness, + }); + _this.svgContainer.find("circle").remove(); + } else if (_this.tool === "recSelect") { + _this.imgDragActive = true; + if (_this.pressedKeys.shift) { + if ( + (currentPos.x - _this.startCoords.x) * + (currentPos.y - _this.startCoords.y) > + 0 + ) { + currentPos = new Point( + currentPos.x, + _this.startCoords.y + (currentPos.x - _this.startCoords.x) + ); + } else { + currentPos = new Point( + currentPos.x, + _this.startCoords.y - (currentPos.x - _this.startCoords.x) + ); + } + } + + const width = Math.abs(_this.startCoords.x - currentPos.x); + const height = Math.abs(_this.startCoords.y - currentPos.y); + const left = + _this.startCoords.x < currentPos.x ? _this.startCoords.x : currentPos.x; + const top = _this.startCoords.y < currentPos.y ? _this.startCoords.y : currentPos.y; + _this.mouseOverlay.css({ cursor: "default" }); + const imgDiv = $( + ` ` + ); + const dragCanvas = $(imgDiv).find("canvas"); + const dragOutOverlay = $( + `` + ); + _this.mouseOverlay.append(dragOutOverlay); + _this.mouseOverlay.append(imgDiv); + + const destCanvasContext = dragCanvas[0].getContext("2d"); + destCanvasContext.drawImage( + _this.canvas, + left, + top, + width, + height, + 0, + 0, + width, + height + ); + imgDiv + .find(".xCanvasBtn") + .off("click") + .click(function () { + _this.imgDragActive = false; + _this.refreshCursorAppearance(); + imgDiv.remove(); + dragOutOverlay.remove(); + }); + imgDiv + .find(".addToCanvasBtn") + .off("click") + .click(function () { + _this.imgDragActive = false; + _this.refreshCursorAppearance(); + const p = imgDiv.position(); + const leftT = Math.round(p.left * 100) / 100; + const topT = Math.round(p.top * 100) / 100; + _this.drawId++; + _this.sendFunction({ + t: _this.tool, + d: [left, top, leftT, topT, width, height], + }); + _this.dragCanvasRectContent(left, top, leftT, topT, width, height); + imgDiv.remove(); + dragOutOverlay.remove(); + }); + imgDiv.draggable(); + _this.svgContainer.find("rect").remove(); + } + }; + + _this.mouseOverlay.on("mouseout", function (e) { + if (ReadOnlyService.readOnlyActive) return; + _this.triggerMouseOut(); + }); + + _this.mouseOverlay.on("mouseover", function (e) { + if (ReadOnlyService.readOnlyActive) return; + _this.triggerMouseOver(); + }); + + // On text container click (Add a new textbox) + _this.textContainer.on("click", function (e) { + const currentPos = Point.fromEvent(e); + const fontsize = _this.thickness * 0.5; + const txId = "tx" + +new Date(); + const isStickyNote = _this.tool === "stickynote"; + _this.sendFunction({ + t: "addTextBox", + d: [ + _this.drawcolor, + _this.textboxBackgroundColor, + fontsize, + currentPos.x, + currentPos.y, + txId, + isStickyNote, + ], + }); + _this.addTextBox( + _this.drawcolor, + _this.textboxBackgroundColor, + fontsize, + currentPos.x, + currentPos.y, + txId, + isStickyNote, + true + ); + }); + }, + /** + * For drawing lines at 0,45,90° .... + * @param {Point} currentPos + * @returns {Point} + */ + getRoundedAngles: function (currentPos) { + const { startCoords } = this; + + // these transformations operate in the standard coordinate system + // y goes from bottom to up, x goes left to right + const dx = currentPos.x - startCoords.x; // browser x is reversed + const dy = startCoords.y - currentPos.y; + + const angle = Math.atan2(dy, dx); + const angle45 = Math.round(angle / _45_DEG_IN_RAD) * _45_DEG_IN_RAD; + + const dist = currentPos.distTo(startCoords); + let outX = startCoords.x + dist * Math.cos(angle45); + let outY = startCoords.y - dist * Math.sin(angle45); + + return new Point(outX, outY); + }, + triggerMouseMove: function (e) { + const _this = this; + if (_this.imgDragActive) { + return; + } + + let currentPos = Point.fromEvent(e); + + window.requestAnimationFrame(function () { + // update position + currentPos = Point.fromEvent(e); + + if (_this.drawFlag) { + if (_this.tool === "pen") { + _this.pushPointSmoothPen(currentPos.x, currentPos.y); + } else if (_this.tool === "eraser") { + _this.drawEraserLine( + currentPos.x, + currentPos.y, + _this.prevPos.x, + _this.prevPos.y, + _this.thickness + ); + _this.sendFunction({ + t: _this.tool, + d: [currentPos.x, currentPos.y, _this.prevPos.x, _this.prevPos.y], + th: _this.thickness, + }); + } + } + + if (_this.tool === "eraser") { + const left = currentPos.x - _this.thickness; + const top = currentPos.y - _this.thickness; + if (_this.ownCursor) _this.ownCursor.css({ top: top + "px", left: left + "px" }); + } else if (_this.tool === "pen") { + const left = currentPos.x - _this.thickness / 2; + const top = currentPos.y - _this.thickness / 2; + if (_this.ownCursor) _this.ownCursor.css({ top: top + "px", left: left + "px" }); + } else if (_this.tool === "line") { + if (_this.svgLine) { + let posToUse = currentPos; + if (_this.pressedKeys.shift) { + posToUse = _this.getRoundedAngles(currentPos); + } + _this.svgLine.setAttribute("x2", posToUse.x); + _this.svgLine.setAttribute("y2", posToUse.y); + } + } else if (_this.tool === "rect" || (_this.tool === "recSelect" && _this.drawFlag)) { + if (_this.svgRect) { + const width = Math.abs(currentPos.x - _this.startCoords.x); + let height = Math.abs(currentPos.y - _this.startCoords.y); + if (_this.pressedKeys.shift) { + height = width; + const x = + currentPos.x < _this.startCoords.x + ? _this.startCoords.x - width + : _this.startCoords.x; + const y = + currentPos.y < _this.startCoords.y + ? _this.startCoords.y - width + : _this.startCoords.y; + _this.svgRect.setAttribute("x", x); + _this.svgRect.setAttribute("y", y); + } else { + const x = + currentPos.x < _this.startCoords.x ? currentPos.x : _this.startCoords.x; + const y = + currentPos.y < _this.startCoords.y ? currentPos.y : _this.startCoords.y; + _this.svgRect.setAttribute("x", x); + _this.svgRect.setAttribute("y", y); + } + + _this.svgRect.setAttribute("width", width); + _this.svgRect.setAttribute("height", height); + } + } else if (_this.tool === "circle") { + const r = currentPos.distTo(_this.startCoords); + if (_this.svgCirle) { + _this.svgCirle.setAttribute("r", r); + } + } + + _this.prevPos = currentPos; + }); + + 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; + if (_this.imgDragActive) { + return; + } + if (!_this.mouseover) { + var color = _this.drawcolor; + var widthHeight = _this.thickness; + if (_this.tool === "eraser") { + color = "#00000000"; + widthHeight = widthHeight * 2; + } + if (_this.tool === "eraser" || _this.tool === "pen") { + _this.ownCursor = $( + '' + ); + _this.cursorContainer.append(_this.ownCursor); + } + } + _this.mouseover = true; + }, + triggerMouseOut: function () { + var _this = this; + if (_this.imgDragActive) { + return; + } + _this.drawFlag = false; + _this.mouseover = false; + _this.ctx.globalCompositeOperation = _this.oldGCO; + if (_this.ownCursor) _this.ownCursor.remove(); + _this.svgContainer.find("line").remove(); + _this.svgContainer.find("rect").remove(); + _this.svgContainer.find("circle").remove(); + _this.sendFunction({ t: "cursor", event: "out" }); + }, + redrawMouseCursor: function () { + const _this = this; + _this.triggerMouseOut(); + _this.triggerMouseOver(); + _this.triggerMouseMove({ offsetX: _this.prevPos.x, offsetY: _this.prevPos.y }); + }, + delKeyAction: function () { + var _this = this; + $.each(_this.mouseOverlay.find(".dragOutOverlay"), function () { + var width = $(this).width(); + var height = $(this).height(); + var p = $(this).position(); + var left = Math.round(p.left * 100) / 100; + var top = Math.round(p.top * 100) / 100; + _this.drawId++; + _this.sendFunction({ t: "eraseRec", d: [left, top, width, height] }); + _this.eraseRec(left, top, width, height); + }); + _this.mouseOverlay.find(".xCanvasBtn").click(); //Remove all current drops + _this.textContainer + .find("#" + _this.latestActiveTextBoxId) + .find(".removeIcon") + .click(); + }, + escKeyAction: function () { + var _this = this; + if (!_this.drawFlag) { + _this.svgContainer.empty(); + } + _this.mouseOverlay.find(".xCanvasBtn").click(); //Remove all current drops + }, + pushPointSmoothPen: function (X, Y) { + var _this = this; + if (_this.penSmoothLastCoords.length >= 8) { + _this.penSmoothLastCoords = [ + _this.penSmoothLastCoords[2], + _this.penSmoothLastCoords[3], + _this.penSmoothLastCoords[4], + _this.penSmoothLastCoords[5], + _this.penSmoothLastCoords[6], + _this.penSmoothLastCoords[7], + ]; + } + _this.penSmoothLastCoords.push(X, Y); + if (_this.penSmoothLastCoords.length >= 8) { + _this.drawPenSmoothLine(_this.penSmoothLastCoords, _this.drawcolor, _this.thickness); + _this.sendFunction({ + t: _this.tool, + d: _this.penSmoothLastCoords, + c: _this.drawcolor, + th: _this.thickness, + }); + } + }, + dragCanvasRectContent: function (xf, yf, xt, yt, width, height) { + var tempCanvas = document.createElement("canvas"); + tempCanvas.width = width; + tempCanvas.height = height; + var tempCanvasContext = tempCanvas.getContext("2d"); + tempCanvasContext.drawImage(this.canvas, xf, yf, width, height, 0, 0, width, height); + this.eraseRec(xf, yf, width, height); + this.ctx.drawImage(tempCanvas, xt, yt); + }, + eraseRec: function (fromX, fromY, width, height) { + var _this = this; + _this.ctx.beginPath(); + _this.ctx.rect(fromX, fromY, width, height); + _this.ctx.fillStyle = "rgba(0,0,0,1)"; + _this.ctx.globalCompositeOperation = "destination-out"; + _this.ctx.fill(); + _this.ctx.closePath(); + _this.ctx.globalCompositeOperation = _this.oldGCO; + }, + drawPenLine: function (fromX, fromY, toX, toY, color, thickness) { + var _this = this; + _this.ctx.beginPath(); + _this.ctx.moveTo(fromX, fromY); + _this.ctx.lineTo(toX, toY); + _this.ctx.strokeStyle = color; + _this.ctx.lineWidth = thickness; + _this.ctx.lineCap = _this.lineCap; + _this.ctx.stroke(); + _this.ctx.closePath(); + }, + drawPenSmoothLine: function (coords, color, thickness) { + var _this = this; + var xm1 = coords[0]; + var ym1 = coords[1]; + var x0 = coords[2]; + var y0 = coords[3]; + var x1 = coords[4]; + var y1 = coords[5]; + var x2 = coords[6]; + var y2 = coords[7]; + var length = Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2)); + var steps = Math.ceil(length / 5); + _this.ctx.beginPath(); + _this.ctx.moveTo(x0, y0); + if (steps == 0) { + _this.ctx.lineTo(x0, y0); + } + for (var i = 0; i < steps; i++) { + var point = lanczosInterpolate(xm1, ym1, x0, y0, x1, y1, x2, y2, (i + 1) / steps); + _this.ctx.lineTo(point[0], point[1]); + } + _this.ctx.strokeStyle = color; + _this.ctx.lineWidth = thickness; + _this.ctx.lineCap = _this.lineCap; + _this.ctx.stroke(); + _this.ctx.closePath(); + }, + drawEraserLine: function (fromX, fromY, toX, toY, thickness) { + var _this = this; + _this.ctx.beginPath(); + _this.ctx.moveTo(fromX, fromY); + _this.ctx.lineTo(toX, toY); + _this.ctx.strokeStyle = "rgba(0,0,0,1)"; + _this.ctx.lineWidth = thickness * 2; + _this.ctx.lineCap = _this.lineCap; + _this.ctx.globalCompositeOperation = "destination-out"; + _this.ctx.stroke(); + _this.ctx.closePath(); + _this.ctx.globalCompositeOperation = _this.oldGCO; + }, + drawRec: function (fromX, fromY, toX, toY, color, thickness) { + var _this = this; + toX = toX - fromX; + toY = toY - fromY; + _this.ctx.beginPath(); + _this.ctx.rect(fromX, fromY, toX, toY); + _this.ctx.strokeStyle = color; + _this.ctx.lineWidth = thickness; + _this.ctx.lineCap = _this.lineCap; + _this.ctx.stroke(); + _this.ctx.closePath(); + }, + drawCircle: function (fromX, fromY, radius, color, thickness) { + var _this = this; + _this.ctx.beginPath(); + _this.ctx.arc(fromX, fromY, radius, 0, 2 * Math.PI, false); + _this.ctx.lineWidth = thickness; + _this.ctx.strokeStyle = color; + _this.ctx.stroke(); + }, + clearWhiteboard: function () { + var _this = this; + if (ReadOnlyService.readOnlyActive) return; + _this.canvas.height = _this.canvas.height; + _this.imgContainer.empty(); + _this.textContainer.empty(); + _this.sendFunction({ t: "clear" }); + _this.drawBuffer = []; + _this.undoBuffer = []; + _this.drawId = 0; + }, + setStrokeThickness(thickness) { + var _this = this; + _this.thickness = thickness; + + if ((_this.tool == "text" || this.tool === "stickynote") && _this.latestActiveTextBoxId) { + _this.sendFunction({ + t: "setTextboxFontSize", + d: [_this.latestActiveTextBoxId, thickness], + }); + _this.setTextboxFontSize(_this.latestActiveTextBoxId, thickness); + } + }, + addImgToCanvasByUrl: function (url) { + var _this = this; + var oldTool = _this.tool; + + const { imageURL } = ConfigService; + var finalURL = url; + if (imageURL && url.startsWith("/uploads/")) { + finalURL = imageURL + url; + } + + _this.setTool("mouse"); //Set to mouse tool while dropping to prevent errors + _this.imgDragActive = true; + _this.mouseOverlay.css({ cursor: "default" }); + var imgDiv = $( + '