[mirotalksfu] - fix whiteboard & add lock functionality
هذا الالتزام موجود في:
@@ -159,9 +159,8 @@ $ PORT=3011 npm start
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
- Install docker engine: https://docs.docker.com/engine/install/
|
- Install [docker engine](https://docs.docker.com/engine/install/)
|
||||||
- Install docker compose: https://docs.docker.com/compose/install/
|
- Install [docker compose](https://docs.docker.com/compose/install/)
|
||||||
- Repository docker hub: https://hub.docker.com/r/mirotalk/sfu
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Copy app/src/config.template.js in app/src/config.js IMPORTANT (edit it according to your needs)
|
# Copy app/src/config.template.js in app/src/config.js IMPORTANT (edit it according to your needs)
|
||||||
@@ -177,6 +176,7 @@ $ docker-compose down
|
|||||||
```
|
```
|
||||||
|
|
||||||
- Open in browser https://localhost:3010
|
- Open in browser https://localhost:3010
|
||||||
|
- Repository [docker hub](https://hub.docker.com/r/mirotalk/sfu)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
@@ -987,6 +987,11 @@ progress {
|
|||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.whiteboard-header-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.whiteboard-header button {
|
.whiteboard-header button {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ let recTimer = null;
|
|||||||
let recElapsedTime = null;
|
let recElapsedTime = null;
|
||||||
|
|
||||||
let wbCanvas = null;
|
let wbCanvas = null;
|
||||||
|
let wbIsLock = false;
|
||||||
let wbIsDrawing = false;
|
let wbIsDrawing = false;
|
||||||
let wbIsOpen = false;
|
let wbIsOpen = false;
|
||||||
let wbIsRedoing = false;
|
let wbIsRedoing = false;
|
||||||
@@ -178,6 +179,7 @@ function initClient() {
|
|||||||
setTippy('whiteboardSaveBtn', 'Save', 'bottom');
|
setTippy('whiteboardSaveBtn', 'Save', 'bottom');
|
||||||
setTippy('whiteboardEraserBtn', 'Eraser', 'bottom');
|
setTippy('whiteboardEraserBtn', 'Eraser', 'bottom');
|
||||||
setTippy('whiteboardCleanBtn', 'Clean', 'bottom');
|
setTippy('whiteboardCleanBtn', 'Clean', 'bottom');
|
||||||
|
setTippy('whiteboardLockButton', 'If enabled, participants cannot interact', 'right');
|
||||||
setTippy('whiteboardCloseBtn', 'Close', 'right');
|
setTippy('whiteboardCloseBtn', 'Close', 'right');
|
||||||
setTippy('chatCleanTextButton', 'Clean', 'top');
|
setTippy('chatCleanTextButton', 'Clean', 'top');
|
||||||
setTippy('chatPasteButton', 'Paste', 'top');
|
setTippy('chatPasteButton', 'Paste', 'top');
|
||||||
@@ -851,6 +853,10 @@ function roomIsReady() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function elemDisplay(element, display, mode = 'block') {
|
||||||
|
element.style.display = display ? mode : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
function hide(elem) {
|
function hide(elem) {
|
||||||
elem.className = 'hidden';
|
elem.className = 'hidden';
|
||||||
}
|
}
|
||||||
@@ -1137,6 +1143,10 @@ function handleButtons() {
|
|||||||
whiteboardCleanBtn.onclick = () => {
|
whiteboardCleanBtn.onclick = () => {
|
||||||
confirmClearBoard();
|
confirmClearBoard();
|
||||||
};
|
};
|
||||||
|
whiteboardLockButton.onchange = () => {
|
||||||
|
wbIsLock = !wbIsLock;
|
||||||
|
whiteboardAction(getWhiteboardAction(wbIsLock ? 'lock' : 'unlock'));
|
||||||
|
};
|
||||||
whiteboardCloseBtn.onclick = () => {
|
whiteboardCloseBtn.onclick = () => {
|
||||||
whiteboardAction(getWhiteboardAction('close'));
|
whiteboardAction(getWhiteboardAction('close'));
|
||||||
};
|
};
|
||||||
@@ -2097,7 +2107,16 @@ function wbCanvasSaveImg() {
|
|||||||
saveDataToFile(dataURL, fileName);
|
saveDataToFile(dataURL, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function wbUpdate() {
|
||||||
|
if (wbIsOpen && (!isRulesActive || isPresenter)) {
|
||||||
|
console.log('IsPresenter: update whiteboard canvas to the participants in the room');
|
||||||
|
wbCanvasToJson();
|
||||||
|
whiteboardAction(getWhiteboardAction(wbIsLock ? 'lock' : 'unlock'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function wbCanvasToJson() {
|
function wbCanvasToJson() {
|
||||||
|
if (!isPresenter && wbIsLock) return;
|
||||||
if (rc.thereIsParticipants()) {
|
if (rc.thereIsParticipants()) {
|
||||||
let wbCanvasJson = JSON.stringify(wbCanvas.toJSON());
|
let wbCanvasJson = JSON.stringify(wbCanvas.toJSON());
|
||||||
rc.socket.emit('wbCanvasToJson', wbCanvasJson);
|
rc.socket.emit('wbCanvasToJson', wbCanvasJson);
|
||||||
@@ -2106,9 +2125,11 @@ function wbCanvasToJson() {
|
|||||||
|
|
||||||
function JsonToWbCanvas(json) {
|
function JsonToWbCanvas(json) {
|
||||||
if (!wbIsOpen) toggleWhiteboard();
|
if (!wbIsOpen) toggleWhiteboard();
|
||||||
|
|
||||||
wbCanvas.loadFromJSON(json);
|
wbCanvas.loadFromJSON(json);
|
||||||
wbCanvas.renderAll();
|
wbCanvas.renderAll();
|
||||||
|
if (!isPresenter && !wbCanvas.isDrawingMode && wbIsLock) {
|
||||||
|
wbDrawing(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWhiteboardAction(action) {
|
function getWhiteboardAction(action) {
|
||||||
@@ -2164,6 +2185,24 @@ function whiteboardAction(data, emit = true) {
|
|||||||
case 'clear':
|
case 'clear':
|
||||||
wbCanvas.clear();
|
wbCanvas.clear();
|
||||||
break;
|
break;
|
||||||
|
case 'lock':
|
||||||
|
if (!isPresenter) {
|
||||||
|
elemDisplay(whiteboardTitle, false);
|
||||||
|
elemDisplay(whiteboardOptions, false);
|
||||||
|
elemDisplay(whiteboardButton, false);
|
||||||
|
wbDrawing(false);
|
||||||
|
wbIsLock = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'unlock':
|
||||||
|
if (!isPresenter) {
|
||||||
|
elemDisplay(whiteboardTitle, true, 'flex');
|
||||||
|
elemDisplay(whiteboardOptions, true, 'inline');
|
||||||
|
elemDisplay(whiteboardButton, true);
|
||||||
|
wbDrawing(true);
|
||||||
|
wbIsLock = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'close':
|
case 'close':
|
||||||
if (wbIsOpen) toggleWhiteboard();
|
if (wbIsOpen) toggleWhiteboard();
|
||||||
break;
|
break;
|
||||||
@@ -2171,6 +2210,14 @@ function whiteboardAction(data, emit = true) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function wbDrawing(status) {
|
||||||
|
wbCanvas.isDrawingMode = status; // Disable free drawing
|
||||||
|
wbCanvas.selection = status; // Disable object selection
|
||||||
|
wbCanvas.forEachObject(function (obj) {
|
||||||
|
obj.selectable = status; // Make all objects unselectable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// HANDLE PARTICIPANTS
|
// HANDLE PARTICIPANTS
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|||||||
@@ -1624,10 +1624,8 @@ class RoomClient {
|
|||||||
|
|
||||||
async consume(producer_id, peer_name, peer_info, type) {
|
async consume(producer_id, peer_name, peer_info, type) {
|
||||||
//
|
//
|
||||||
if (wbIsOpen && (!isRulesActive || isPresenter)) {
|
wbUpdate();
|
||||||
console.log('Update whiteboard canvas to the participants in the room');
|
|
||||||
wbCanvasToJson();
|
|
||||||
}
|
|
||||||
this.getConsumeStream(producer_id, peer_info.peer_id, type).then(
|
this.getConsumeStream(producer_id, peer_info.peer_id, type).then(
|
||||||
function ({ consumer, stream, kind }) {
|
function ({ consumer, stream, kind }) {
|
||||||
console.log('CONSUMER MEDIA TYPE ----> ' + type);
|
console.log('CONSUMER MEDIA TYPE ----> ' + type);
|
||||||
@@ -1983,6 +1981,8 @@ class RoomClient {
|
|||||||
this.setTippy(ko.id, 'Eject', 'top-end');
|
this.setTippy(ko.id, 'Eject', 'top-end');
|
||||||
}
|
}
|
||||||
console.log('[setVideoOff] Video-element-count', this.videoMediaContainer.childElementCount);
|
console.log('[setVideoOff] Video-element-count', this.videoMediaContainer.childElementCount);
|
||||||
|
//
|
||||||
|
wbUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
removeVideoOff(peer_id) {
|
removeVideoOff(peer_id) {
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ const BUTTONS = {
|
|||||||
participantsList: {
|
participantsList: {
|
||||||
saveInfoButton: true,
|
saveInfoButton: true,
|
||||||
},
|
},
|
||||||
|
whiteboard: {
|
||||||
|
whiteboardLockButton: false,
|
||||||
|
},
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,6 +87,7 @@ function handleRules(isPresenter) {
|
|||||||
BUTTONS.consumerVideo.ejectButton = false;
|
BUTTONS.consumerVideo.ejectButton = false;
|
||||||
BUTTONS.consumerVideo.muteAudioButton = false;
|
BUTTONS.consumerVideo.muteAudioButton = false;
|
||||||
BUTTONS.consumerVideo.muteVideoButton = false;
|
BUTTONS.consumerVideo.muteVideoButton = false;
|
||||||
|
BUTTONS.whiteboard.whiteboardLockButton = false;
|
||||||
//...
|
//...
|
||||||
} else {
|
} else {
|
||||||
BUTTONS.participantsList.saveInfoButton = true;
|
BUTTONS.participantsList.saveInfoButton = true;
|
||||||
@@ -95,6 +99,7 @@ function handleRules(isPresenter) {
|
|||||||
BUTTONS.consumerVideo.ejectButton = true;
|
BUTTONS.consumerVideo.ejectButton = true;
|
||||||
BUTTONS.consumerVideo.muteAudioButton = true;
|
BUTTONS.consumerVideo.muteAudioButton = true;
|
||||||
BUTTONS.consumerVideo.muteVideoButton = true;
|
BUTTONS.consumerVideo.muteVideoButton = true;
|
||||||
|
BUTTONS.whiteboard.whiteboardLockButton = true;
|
||||||
//...
|
//...
|
||||||
}
|
}
|
||||||
// main. settings...
|
// main. settings...
|
||||||
@@ -102,5 +107,8 @@ function handleRules(isPresenter) {
|
|||||||
BUTTONS.settings.unlockRoomButton ? show(unlockRoomButton) : hide(unlockRoomButton);
|
BUTTONS.settings.unlockRoomButton ? show(unlockRoomButton) : hide(unlockRoomButton);
|
||||||
BUTTONS.settings.lobbyButton ? show(lobbyButton) : hide(lobbyButton);
|
BUTTONS.settings.lobbyButton ? show(lobbyButton) : hide(lobbyButton);
|
||||||
BUTTONS.participantsList.saveInfoButton ? show(participantsSaveBtn) : hide(participantsSaveBtn);
|
BUTTONS.participantsList.saveInfoButton ? show(participantsSaveBtn) : hide(participantsSaveBtn);
|
||||||
|
BUTTONS.whiteboard.whiteboardLockButton
|
||||||
|
? elemDisplay(whiteboardLockButton, true)
|
||||||
|
: elemDisplay(whiteboardLockButton, false, 'flex');
|
||||||
//...
|
//...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -412,8 +412,11 @@ access to use this app.
|
|||||||
<header id="whiteboardHeader" class="whiteboard-header">
|
<header id="whiteboardHeader" class="whiteboard-header">
|
||||||
<div id="whiteboardTitle" class="whiteboard-header-title">
|
<div id="whiteboardTitle" class="whiteboard-header-title">
|
||||||
<button id="whiteboardCloseBtn" class="fas fa-times"></button>
|
<button id="whiteboardCloseBtn" class="fas fa-times"></button>
|
||||||
|
<div class="form-check form-switch form-switch-md" style="margin-left: 10px">
|
||||||
|
<input id="whiteboardLockButton" class="form-check-input" type="checkbox" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="whiteboard-header-options">
|
<div id="whiteboardOptions" class="whiteboard-header-options">
|
||||||
<button id="whiteboardGhostButton" class="fas fa-circle-half-stroke"></button>
|
<button id="whiteboardGhostButton" class="fas fa-circle-half-stroke"></button>
|
||||||
<input id="wbBackgroundColorEl" class="whiteboardColorPicker" type="color" value="#000000" />
|
<input id="wbBackgroundColorEl" class="whiteboardColorPicker" type="color" value="#000000" />
|
||||||
<input id="wbDrawingColorEl" class="whiteboardColorPicker" type="color" value="#FFFFFF" />
|
<input id="wbDrawingColorEl" class="whiteboardColorPicker" type="color" value="#FFFFFF" />
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم