diff --git a/public/Room.html b/public/Room.html index 39033386..12229a56 100644 --- a/public/Room.html +++ b/public/Room.html @@ -147,6 +147,12 @@ + + diff --git a/public/images/locked.png b/public/images/locked.png new file mode 100644 index 00000000..42524443 Binary files /dev/null and b/public/images/locked.png differ diff --git a/public/js/Room.js b/public/js/Room.js index f80247be..1232650a 100644 --- a/public/js/Room.js +++ b/public/js/Room.js @@ -67,6 +67,8 @@ function initClient() { setTippy('stopVideoButton', 'Stop Video', 'bottom'); setTippy('startScreenButton', 'Start Screen', 'bottom'); setTippy('stopScreenButton', 'Stop Screen', 'bottom'); + setTippy('lockRoomButton', 'Room Lock', 'bottom'); + setTippy('unlockRoomButton', 'Room Unlock', 'bottom'); setTippy('aboutButton', 'About', 'bottom'); } initEnumerateDevices(); @@ -273,7 +275,7 @@ async function shareRoom(useNavigator = false) { background: swalBackground, imageUrl: swalImageUrl, imageWidth: 300, - imageHeight: 200, + imageHeight: 150, position: 'center', title: 'Hello ' + peer_name + '', html: @@ -400,6 +402,7 @@ function roomIsReady() { if (isAudioAllowed) show(startAudioButton); if (isVideoAllowed) show(startVideoButton); show(videoMedia); + show(lockRoomButton); show(aboutButton); handleButtons(); handleSelects(); @@ -553,6 +556,12 @@ function handleButtons() { stopScreenButton.onclick = () => { rc.closeProducer(RoomClient.mediaType.screen); }; + lockRoomButton.onclick = () => { + rc.roomAction('lock'); + }; + unlockRoomButton.onclick = () => { + rc.roomAction('unlock'); + }; aboutButton.onclick = () => { showAbout(); }; @@ -667,6 +676,14 @@ function handleRoomClientEvents() { hide(stopScreenButton); show(startScreenButton); }); + rc.on(RoomClient.EVENTS.roomLock, () => { + hide(lockRoomButton); + show(unlockRoomButton); + }); + rc.on(RoomClient.EVENTS.roomUnlock, () => { + hide(unlockRoomButton); + show(lockRoomButton); + }); rc.on(RoomClient.EVENTS.exitRoom, () => { window.location.href = '/newroom'; }); @@ -715,7 +732,7 @@ function showAbout() { background: swalBackground, imageUrl: swalImageUrl, imageWidth: 300, - imageHeight: 200, + imageHeight: 150, position: 'center', html: `
diff --git a/public/js/RoomClient.js b/public/js/RoomClient.js index e114b54c..d3937c6c 100644 --- a/public/js/RoomClient.js +++ b/public/js/RoomClient.js @@ -11,6 +11,7 @@ const html = { const image = { poster: '../images/loader.gif', delete: '../images/delete.png', + locked: '../images/locked.png', }; const mediaType = { @@ -39,6 +40,8 @@ const _EVENTS = { pauseScreen: 'pauseScreen', resumeScreen: 'resumeScreen', stopScreen: 'stopScreen', + roomLock: 'roomLock', + roomUnlock: 'roomUnlock', }; let recordedBlobs; @@ -171,6 +174,10 @@ class RoomClient { .request('join', data) .then( async function (room) { + if (room === 'isLocked') { + this.roomIsLocked(); + return; + } this.connectedRoom = room; console.log('07 ----> Joined to room', this.connectedRoom); const data = await this.socket.request('getRouterRtpCapabilities'); @@ -359,11 +366,19 @@ class RoomClient { this.socket.on( 'message', function (data) { - console.log('message', data); + console.log('Message', data); this.showMessage(data); }.bind(this), ); + this.socket.on( + 'roomAction', + function (data) { + console.log('Room action:', data); + this.roomAction(data, false); + }.bind(this), + ); + this.socket.on( 'disconnect', function () { @@ -1365,4 +1380,51 @@ class RoomClient { this.event(_EVENTS.stopRec); this.sound('recStop'); } + + // #################################################### + // ROOM ACTION + // #################################################### + + roomAction(action, emit = true) { + if (emit) this.socket.emit('roomAction', action); + switch (action) { + case 'lock': + this.sound('locked'); + this.event(_EVENTS.roomLock); + this.userLog('info', '🔒 LOCKED the room, no one can access!', 'top-end'); + break; + case 'unlock': + this.event(_EVENTS.roomUnlock); + this.userLog('info', '🔓 UNLOCKED the room', 'top-end'); + break; + } + } + + // #################################################### + // HANDLE ROOM ACTION + // #################################################### + + roomIsLocked() { + this.sound('locked'); + this.event(_EVENTS.roomLock); + console.log('Room is Locked, try with another one'); + Swal.fire({ + allowOutsideClick: false, + background: swalBackground, + position: 'center', + imageUrl: image.locked, + title: 'Oops, Room Locked', + text: 'The room is locked, try with another one.', + showDenyButton: false, + confirmButtonText: `Ok`, + showClass: { + popup: 'animate__animated animate__fadeInDown', + }, + hideClass: { + popup: 'animate__animated animate__fadeOutUp', + }, + }).then((result) => { + if (result.isConfirmed) this.exit(); + }); + } } diff --git a/public/sounds/locked.wav b/public/sounds/locked.wav new file mode 100644 index 00000000..de7439c8 Binary files /dev/null and b/public/sounds/locked.wav differ diff --git a/src/Room.js b/src/Room.js index 52fd3f07..3b153bca 100644 --- a/src/Room.js +++ b/src/Room.js @@ -10,6 +10,7 @@ module.exports = class Room { this.worker = worker; this.router = null; this.io = io; + this._isLocked = false; this.peers = new Map(); this.createTheRouter(); } @@ -187,6 +188,17 @@ module.exports = class Room { this.peers.get(socket_id).closeProducer(producer_id); } + // #################################################### + // ROOM STATUS + // #################################################### + + isLocked() { + return this._isLocked; + } + setLocked(status) { + this._isLocked = status; + } + // #################################################### // SENDER // #################################################### diff --git a/src/Server.js b/src/Server.js index 27a21be5..b5967dc7 100644 --- a/src/Server.js +++ b/src/Server.js @@ -203,16 +203,36 @@ io.on('connection', (socket) => { } }); - socket.on('join', (data, cb) => { - log.debug('User joined', data); + socket.on('roomAction', (action) => { + switch (action) { + case 'lock': + roomList.get(socket.room_id).setLocked(true); + break; + case 'unlock': + roomList.get(socket.room_id).setLocked(false); + break; + } + log.debug('Room locked:', roomList.get(socket.room_id).isLocked()); + // send to all participants + roomList.get(socket.room_id).broadCast(socket.id, 'roomAction', action); + }); + socket.on('join', (data, cb) => { if (!roomList.has(socket.room_id)) { return cb({ error: 'Room does not exist', }); } + log.debug('User joined', data); roomList.get(socket.room_id).addPeer(new Peer(socket.id, data)); + + if (roomList.get(socket.room_id).isLocked()) { + log.debug('User rejected because room is locked'); + cb('isLocked'); + return; + } + cb(roomList.get(socket.room_id).toJson()); }); @@ -327,6 +347,10 @@ io.on('connection', (socket) => { log.debug('Disconnect', getPeerName()); roomList.get(socket.room_id).removePeer(socket.id); + + if (roomList.get(socket.room_id).getPeers().size === 0 && roomList.get(socket.room_id).isLocked()) { + roomList.get(socket.room_id).setLocked(false); + } }); socket.on('exitRoom', async (_, callback) => {