From 8f36a24c028272610eae4c7156d0a01fdd83e294 Mon Sep 17 00:00:00 2001 From: Miroslav Pejic Date: Wed, 6 Dec 2023 19:37:30 +0100 Subject: [PATCH] [mirotalksfu] - #137 enable audio/video/screen to specified participant --- app/src/Server.js | 2 +- package.json | 2 +- public/images/start.png | Bin 0 -> 812 bytes public/images/unhide.png | Bin 0 -> 534 bytes public/images/unmute.png | Bin 0 -> 1288 bytes public/js/Room.js | 2 +- public/js/RoomClient.js | 117 +++++++++++++++++++++++++++++++++++---- 7 files changed, 110 insertions(+), 13 deletions(-) create mode 100644 public/images/start.png create mode 100644 public/images/unhide.png create mode 100644 public/images/unmute.png diff --git a/app/src/Server.js b/app/src/Server.js index 37bbc7c9..17da96a3 100644 --- a/app/src/Server.js +++ b/app/src/Server.js @@ -40,7 +40,7 @@ dependencies: { * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.3.2 + * @version 1.3.3 * */ diff --git a/package.json b/package.json index 4c437720..2370c9f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mirotalksfu", - "version": "1.3.2", + "version": "1.3.3", "description": "WebRTC SFU browser-based video calls", "main": "Server.js", "scripts": { diff --git a/public/images/start.png b/public/images/start.png new file mode 100644 index 0000000000000000000000000000000000000000..a7a3746e6182af6f995b827eeb6c02a500c4fffb GIT binary patch literal 812 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&^#=HaxB}__g9b2n8@B=-q*oH; z7tF9K)X)2m$5+-@<-q~AI~+KFTt8fEDEFa1@BHQ^K|1QA8EF?rBTkI zY9a#zlY*yNJV&2|uIeaL*N<7lGb>=u>m`#S1>|MgGjzU{fvrf1otFFvQP z-ZvGuXT2N1px7ed#G&}lzVM<9v)FO9!_L#y6x}?d4z0K=xcRRX+vJWLuB>diX-^L1 zG%Kb|^JkfcbxPLvXE1Gut>8Pb^P5bA(RYCbt9bSwX}sN# zQkt85$8s0;@ zJ9sM1-G(vzHR}Q4fY*9u-@X*Ry8QJo*Avcww}0n|p54@C$A8>HX<374-RoIZtLC38 z@De*#FSOy+#iId;{x=*j<^ad>!`uGu Y^+%3P=)bW7n93MDUHx3vIVCg!08ojk{{R30 literal 0 HcmV?d00001 diff --git a/public/images/unhide.png b/public/images/unhide.png new file mode 100644 index 0000000000000000000000000000000000000000..1c45dece8d9e7e328ba0d69759798fa0059c23ee GIT binary patch literal 534 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&MFseTxB}__v;mPu+xG%Zmn{kM z3uXvi`Dc|#fiC;U2M7ASRGu!dKXYtaum$VOLyi7w$3?`M7#JA+JY5_^DsH{G;$75i zAkgwKP{fnPgQHHh?#tixFJ*59tdmmSZT>el;h*dE869A-=Euy#Zr6jW{{2dH;@*Ad zrtmJqMN?m9YsPGZrNtu&wOk4*+i%6#m|`^u$J{TNa}xh z&tZ{d*p~Y(;zn0Uj_(1b8)ozQnZ4v!Fy4<}!1jbA&EY$@0rMq>EQgl|IahpM3>5Nn zm@99rz`KBLirkV0EBiEuzKZ+<>|&*LTN+Fnqynk}m|y+zU=)19py9yC6>wm0Z1GA) z1(rn-L5#2C-#u#JULp|1I@xk>JbQ@)yG?zAo=1u2vhJYxX}^yh*`C&9d34+J8;q=F zF3qw*iN{NBII5O~bjyY%AOCuzm38x}XJ;;Xt$+LFQPBFlzn^~H4!D2cG~t7~%&(5r qKM5~;o*z@Z%ow~55;D(!FwQ*Mc6+h!k7QsJFnGH9xvX? literal 0 HcmV?d00001 diff --git a/public/images/unmute.png b/public/images/unmute.png new file mode 100644 index 0000000000000000000000000000000000000000..6242cab913ba5e935c785b755fb957462eaaef82 GIT binary patch literal 1288 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&tqAZ5aRt)X%7+@{_*2P5f_Np9T8DYMMdpE9|6@Ti`)RJ^9J;mosYhrlL z?T8FJ(k`%BwR0Xf0|WC7PZ!6Kid%1PI_5Vy2(&#sudChV!PFUbg;_<4w^goc=Kufa zXB8wY2*{Ym7x!#uo?4}|QFX+EXB_i9MO6D4)+a1JV;o|9Pj^#9*sJ4L1b=HzEB;u1 zW%FnKh!fiuIJ!2uzTy3Q=*`B432rF@(=V&FY*|L*@k`>o^_f$15# z3gWW+cQ-iyJGiyT(a2@dVYQ0$Yb3-LOzvxUWj=GG!aGxB#iruT)l1UfIwiWjbh?|v9(CPhchrTvW!-NNv>eKvT35IBzpHr7*M&y9 zS_hfjcL~llP3C^udLPC(`{>6DjwHut}q#ircsS?Tgxx9;TZfR(TKe@tC&H8pqH<1C{^(h+Stf_5yq zJ)^X+^<6{WvAStL8gp)xcrR}2m5#wxe9*BllFu9h?lO@G2YN5HXP%V?I;zy$Cj~nz~)_I=5DQhsEs`hHbv(JO8kU&%E+|^6b@bfyD%a Mr>mdKI;Vst0QQZxXaE2J literal 0 HcmV?d00001 diff --git a/public/js/Room.js b/public/js/Room.js index 4fe16194..c2e3efe1 100644 --- a/public/js/Room.js +++ b/public/js/Room.js @@ -11,7 +11,7 @@ if (location.href.substr(0, 5) !== 'https') location.href = 'https' + location.h * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.3.2 + * @version 1.3.3 * */ diff --git a/public/js/RoomClient.js b/public/js/RoomClient.js index acbfbad0..017a8037 100644 --- a/public/js/RoomClient.js +++ b/public/js/RoomClient.js @@ -9,7 +9,7 @@ * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.3.2 + * @version 1.3.3 * */ @@ -74,6 +74,9 @@ const image = { mute: '../images/mute.png', hide: '../images/hide.png', stop: '../images/stop.png', + unmute: '../images/unmute.png', + unhide: '../images/unhide.png', + start: '../images/start.png', users: '../images/participants.png', user: '../images/participant.png', username: '../images/user.png', @@ -5358,6 +5361,10 @@ class RoomClient { case 'mute': const peerAudioStatus = this.getId(data.peer_id + '__audio'); if (!peerAudioStatus || peerAudioStatus.className == html.audioOff) { + if (isRulesActive && isPresenter) { + data.action = 'unmute'; + return this.confirmPeerAction(data.action, data); + } return this.userLog( 'info', 'The participant has been muted, and only they have the ability to unmute themselves', @@ -5368,6 +5375,10 @@ class RoomClient { case 'hide': const peerVideoOff = this.getId(data.peer_id + '__videoOff'); if (peerVideoOff) { + if (isRulesActive && isPresenter) { + data.action = 'unhide'; + return this.confirmPeerAction(data.action, data); + } return this.userLog( 'info', 'The participant is currently hidden, and only they have the option to unhide themselves', @@ -5379,6 +5390,10 @@ class RoomClient { if (peerScreenButton) { const peerScreenStatus = peerScreenButton.querySelector('i'); if (peerScreenStatus && peerScreenStatus.style.color == 'red') { + if (isRulesActive && isPresenter) { + data.action = 'start'; + return this.confirmPeerAction(data.action, data); + } return this.userLog( 'info', 'The participant screen is not shared, only the participant can initiate sharing', @@ -5391,11 +5406,12 @@ class RoomClient { break; } } - this.confirmPeerAction(action, data); + this.confirmPeerAction(data.action, data); } else { + const peerActionAllowed = peer_id === this.peer_id || broadcast; switch (action) { case 'eject': - if (peer_id === this.peer_id || broadcast) { + if (peerActionAllowed) { const message = `Will eject you from the room${ msg ? `

Reason: ${msg}` : '' }`; @@ -5405,7 +5421,7 @@ class RoomClient { } break; case 'mute': - if (peer_id === this.peer_id || broadcast) { + if (peerActionAllowed) { this.closeProducer(mediaType.audio); this.updatePeerInfo(this.peer_name, this.peer_id, 'audio', false); this.userLog( @@ -5416,8 +5432,18 @@ class RoomClient { ); } break; + case 'unmute': + if (peerActionAllowed) { + this.peerMediaStartConfirm( + mediaType.audio, + image.unmute, + 'Enable Microphone', + 'Allow the presenter enable your microphone?', + ); + } + break; case 'hide': - if (peer_id === this.peer_id || broadcast) { + if (peerActionAllowed) { this.closeProducer(mediaType.video); this.userLog( 'warning', @@ -5427,9 +5453,19 @@ class RoomClient { ); } break; + case 'unhide': + if (peerActionAllowed) { + this.peerMediaStartConfirm( + mediaType.video, + image.unhide, + 'Enable Camera', + 'Allow the presenter enable your camera?', + ); + } + break; case 'stop': if (this.isScreenShareSupported) { - if (peer_id === this.peer_id || broadcast) { + if (peerActionAllowed) { this.closeProducer(mediaType.screen); this.userLog( 'warning', @@ -5440,6 +5476,16 @@ class RoomClient { } } break; + case 'start': + if (peerActionAllowed) { + this.peerMediaStartConfirm( + mediaType.screen, + image.start, + 'Start Screen share', + 'Allow the presenter start your screen share?', + ); + } + break; default: break; //... @@ -5447,6 +5493,38 @@ class RoomClient { } } + peerMediaStartConfirm(type, imageUrl, title, text) { + Swal.fire({ + background: swalBackground, + position: 'center', + imageUrl: imageUrl, + title: title, + text: text, + showDenyButton: true, + confirmButtonText: `Yes`, + denyButtonText: `No`, + showClass: { popup: 'animate__animated animate__fadeInDown' }, + hideClass: { popup: 'animate__animated animate__fadeOutUp' }, + }).then((result) => { + if (result.isConfirmed) { + switch (type) { + case mediaType.audio: + this.produce(mediaType.audio, microphoneSelect.value); + this.updatePeerInfo(this.peer_name, this.peer_id, 'audio', true); + break; + case mediaType.video: + this.produce(mediaType.video, videoSelect.value); + break; + case mediaType.screen: + this.produce(mediaType.screen); + break; + default: + break; + } + } + }); + } + peerActionProgress(tt, msg, time, action = 'na') { Swal.fire({ allowOutsideClick: false, @@ -5474,6 +5552,7 @@ class RoomClient { } confirmPeerAction(action, data) { + console.log('Confirm peer action', action); switch (action) { case 'eject': let ejectConfirmed = false; @@ -5518,29 +5597,47 @@ class RoomClient { }); break; case 'mute': + case 'unmute': case 'hide': + case 'unhide': case 'stop': + case 'start': let muteHideStopConfirmed = false; - let whoMuteHideStop = data.broadcast ? 'everyone except yourself?' : 'current participant?'; + let who = data.broadcast ? 'everyone except yourself?' : 'current participant?'; let imageUrl, title, text; switch (action) { case 'mute': imageUrl = image.mute; - title = 'Mute ' + whoMuteHideStop; + title = 'Mute ' + who; text = "Once muted, you won't be able to unmute them, but they can unmute themselves at any time."; break; + case 'unmute': + imageUrl = image.unmute; + title = 'Unmute ' + who; + text = 'A pop-up message will appear to prompt and allow this action.'; + break; case 'hide': - title = 'Hide ' + whoMuteHideStop; + title = 'Hide ' + who; imageUrl = image.hide; text = "Once hided, you won't be able to unhide them, but they can unhide themselves at any time."; break; + case 'unhide': + title = 'Unhide ' + who; + imageUrl = image.unhide; + text = 'A pop-up message will appear to prompt and allow this action.'; + break; case 'stop': imageUrl = image.stop; - title = 'Stop screen share to the ' + whoMuteHideStop; + title = 'Stop screen share to the ' + who; text = "Once stop, you won't be able to start them, but they can start themselves at any time."; break; + case 'start': + imageUrl = image.start; + title = 'Start screen share to the ' + who; + text = 'A pop-up message will appear to prompt and allow this action.'; + break; default: break; }