[mirotalksfu] - add participant lists + eject

هذا الالتزام موجود في:
Miroslav Pejic
2021-09-03 14:09:38 +02:00
الأصل bfeb4a914a
التزام 57e925ea20
8 ملفات معدلة مع 195 إضافات و64 حذوفات

عرض الملف

@@ -77,7 +77,7 @@
<i class="fas fa-arrow-left"></i> <i class="fas fa-arrow-left"></i>
</button> </button>
<button id="shareButton" class="hidden"> <button id="shareButton" class="hidden">
<i class="fas fa-users"></i> <i class="fas fa-share-alt"></i>
</button> </button>
<div class="dropdown"> <div class="dropdown">
<button id="devicesButton" class="hidden"> <button id="devicesButton" class="hidden">
@@ -147,6 +147,9 @@
<button id="stopScreenButton" class="hidden"> <button id="stopScreenButton" class="hidden">
<i class="fas fa-stop-circle"></i> <i class="fas fa-stop-circle"></i>
</button> </button>
<button id="participantsButton" class="hidden">
<i class="fas fa-users"></i>
</button>
<button id="lockRoomButton" class="hidden"> <button id="lockRoomButton" class="hidden">
<i class="fas fa-lock-open"></i> <i class="fas fa-lock-open"></i>
</button> </button>

عرض الملف

@@ -530,6 +530,29 @@ button:hover {
color: rgb(0, 180, 50); color: rgb(0, 180, 50);
} }
/*--------------------------------------------------------------
# Room Participants
--------------------------------------------------------------*/
#roomParticipants {
max-height: 480px;
overflow: auto;
}
#roomParticipants ul {
text-align: justify;
list-style: inside;
}
#roomParticipants button {
color: red;
border-radius: 5px;
}
#roomParticipants button:hover {
color: white;
border-radius: 5px;
}
/*-------------------------------------------------------------- /*--------------------------------------------------------------
# Pulse class effect # Pulse class effect
--------------------------------------------------------------*/ --------------------------------------------------------------*/

عرض الملف

@@ -67,6 +67,7 @@ function initClient() {
setTippy('stopVideoButton', 'Stop Video', 'bottom'); setTippy('stopVideoButton', 'Stop Video', 'bottom');
setTippy('startScreenButton', 'Start Screen', 'bottom'); setTippy('startScreenButton', 'Start Screen', 'bottom');
setTippy('stopScreenButton', 'Stop Screen', 'bottom'); setTippy('stopScreenButton', 'Stop Screen', 'bottom');
setTippy('participantsButton', 'Show participants', 'bottom');
setTippy('lockRoomButton', 'Room Lock', 'bottom'); setTippy('lockRoomButton', 'Room Lock', 'bottom');
setTippy('unlockRoomButton', 'Room Unlock', 'bottom'); setTippy('unlockRoomButton', 'Room Unlock', 'bottom');
setTippy('aboutButton', 'About', 'bottom'); setTippy('aboutButton', 'About', 'bottom');
@@ -114,7 +115,6 @@ async function initEnumerateDevices() {
if (!isAudioAllowed && !isVideoAllowed) { if (!isAudioAllowed && !isVideoAllowed) {
window.location.href = `/permission?room_id=${room_id}&message=Not allowed both Audio and Video`; window.location.href = `/permission?room_id=${room_id}&message=Not allowed both Audio and Video`;
} else { } else {
getPeerInfo();
getPeerGeoLocation(); getPeerGeoLocation();
whoAreYou(); whoAreYou();
} }
@@ -182,13 +182,17 @@ function appenChild(device, el) {
function getPeerInfo() { function getPeerInfo() {
peer_info = { peer_info = {
detectRTCversion: DetectRTC.version, detect_rtc_version: DetectRTC.version,
isWebRTCSupported: DetectRTC.isWebRTCSupported, is_webrtc_Supported: DetectRTC.isWebRTCSupported,
isMobileDevice: DetectRTC.isMobileDevice, is_mobile_device: DetectRTC.isMobileDevice,
osName: DetectRTC.osName, os_name: DetectRTC.osName,
osVersion: DetectRTC.osVersion, os_version: DetectRTC.osVersion,
browserName: DetectRTC.browser.name, browser_name: DetectRTC.browser.name,
browserVersion: DetectRTC.browser.version, browser_version: DetectRTC.browser.version,
peer_id: socket.id,
peer_name: peer_name,
peer_audio: isAudioOn,
peer_video: isVideoOn,
}; };
} }
@@ -229,6 +233,7 @@ function whoAreYou() {
peer_name = name; peer_name = name;
}, },
}).then(() => { }).then(() => {
getPeerInfo();
shareRoom(); shareRoom();
joinRoom(peer_name, room_id); joinRoom(peer_name, room_id);
}); });
@@ -244,12 +249,12 @@ function whoAreYou() {
} }
function handleAudio(e) { function handleAudio(e) {
isAudioOn ? (isAudioOn = false) : (isAudioOn = true); isAudioOn = isAudioOn ? false : true;
e.target.className = 'fas fa-microphone' + (isAudioOn ? '' : '-slash'); e.target.className = 'fas fa-microphone' + (isAudioOn ? '' : '-slash');
} }
function handleVideo(e) { function handleVideo(e) {
isVideoOn ? (isVideoOn = false) : (isVideoOn = true); isVideoOn = isVideoOn ? false : true;
e.target.className = 'fas fa-video' + (isVideoOn ? '' : '-slash'); e.target.className = 'fas fa-video' + (isVideoOn ? '' : '-slash');
} }
@@ -273,9 +278,6 @@ async function shareRoom(useNavigator = false) {
Swal.fire({ Swal.fire({
background: swalBackground, background: swalBackground,
imageUrl: swalImageUrl,
imageWidth: 300,
imageHeight: 150,
position: 'center', position: 'center',
title: '<strong>Hello ' + peer_name + '</strong>', title: '<strong>Hello ' + peer_name + '</strong>',
html: html:
@@ -326,7 +328,7 @@ function makeRoomQR() {
value: RoomURL, value: RoomURL,
}); });
qr.set({ qr.set({
size: 128, size: 256,
}); });
} }
@@ -402,6 +404,7 @@ function roomIsReady() {
if (isAudioAllowed) show(startAudioButton); if (isAudioAllowed) show(startAudioButton);
if (isVideoAllowed) show(startVideoButton); if (isVideoAllowed) show(startVideoButton);
show(videoMedia); show(videoMedia);
show(participantsButton);
show(lockRoomButton); show(lockRoomButton);
show(aboutButton); show(aboutButton);
handleButtons(); handleButtons();
@@ -556,6 +559,9 @@ function handleButtons() {
stopScreenButton.onclick = () => { stopScreenButton.onclick = () => {
rc.closeProducer(RoomClient.mediaType.screen); rc.closeProducer(RoomClient.mediaType.screen);
}; };
participantsButton.onclick = () => {
getRoomParticipants();
};
lockRoomButton.onclick = () => { lockRoomButton.onclick = () => {
rc.roomAction('lock'); rc.roomAction('lock');
}; };
@@ -713,14 +719,49 @@ function userLog(icon, message, position) {
async function sound(name) { async function sound(name) {
let sound = '../sounds/' + name + '.wav'; let sound = '../sounds/' + name + '.wav';
let audioToPlay = new Audio(sound); let audio = new Audio(sound);
try { try {
await audioToPlay.play(); await audio.play();
} catch (err) { } catch (err) {
return false; return false;
} }
} }
// ####################################################
// HANDLE PARTICIPANTS
// ####################################################
async function getRoomParticipants() {
let room_info = await rc.getRoomInfo();
let peers = new Map(JSON.parse(room_info.peers));
let lists = `<div id="roomParticipants"><ul>`;
for (let peer of Array.from(peers.keys())) {
let peer_info = peers.get(peer).peer_info;
let peer_name = peer_info.peer_name;
let peer_id = peer_info.peer_id;
rc.peer_id === peer_id
? (lists += `<li>👤 ${peer_name} (me)</li>`)
: (lists += `<li id='${peer_id}'>👤 ${peer_name} <button id='${peer_id}' onclick="rc.peerAction('me',this.id,'eject')">eject</button></li>`);
}
lists += `</ul></div>`;
sound('open');
Swal.fire({
background: swalBackground,
position: 'center',
title: `Participants ${peers.size}`,
html: lists,
showClass: {
popup: 'animate__animated animate__fadeInDown',
},
hideClass: {
popup: 'animate__animated animate__fadeOutUp',
},
});
}
// #################################################### // ####################################################
// ABOUT // ABOUT
// #################################################### // ####################################################

عرض الملف

@@ -70,10 +70,10 @@ class RoomClient {
this.socket = socket; this.socket = socket;
this.room_id = room_id; this.room_id = room_id;
this.peer_id = socket.id;
this.peer_name = peer_name; this.peer_name = peer_name;
this.peer_geo = peer_geo; this.peer_geo = peer_geo;
this.peer_info = peer_info; this.peer_info = peer_info;
this.peer_info.peerName = peer_name;
this.isAudioAllowed = isAudioAllowed; this.isAudioAllowed = isAudioAllowed;
this.isVideoAllowed = isVideoAllowed; this.isVideoAllowed = isVideoAllowed;
@@ -86,8 +86,6 @@ class RoomClient {
this.isMobileDevice = DetectRTC.isMobileDevice; this.isMobileDevice = DetectRTC.isMobileDevice;
this._isConnected = false; this._isConnected = false;
this.peerGeo = null;
this.peerInfo = null;
this.isVideoOnFullScreen = false; this.isVideoOnFullScreen = false;
this.isDocumentOnFullScreen = false; this.isDocumentOnFullScreen = false;
this.isChatOpen = false; this.isChatOpen = false;
@@ -141,9 +139,6 @@ class RoomClient {
async function () { async function () {
let data = { let data = {
room_id: this.room_id, room_id: this.room_id,
peer_name: this.peer_name,
peer_audio: this.isAudioOn,
peer_video: this.isVideoOn,
peer_info: this.peer_info, peer_info: this.peer_info,
peer_geo: this.peer_geo, peer_geo: this.peer_geo,
}; };
@@ -379,6 +374,14 @@ class RoomClient {
}.bind(this), }.bind(this),
); );
this.socket.on(
'peerAction',
function (data) {
console.log('Peer action:', data);
this.peerAction(data.from_peer_name, data.peer_id, data.action, false);
}.bind(this),
);
this.socket.on( this.socket.on(
'disconnect', 'disconnect',
function () { function () {
@@ -618,17 +621,7 @@ class RoomClient {
this.attachMediaStream(elem, stream, type, 'Producer'); this.attachMediaStream(elem, stream, type, 'Producer');
this.handleFS(elem.id); this.handleFS(elem.id);
this.setTippy(elem.id, 'Full Screen', 'top-end'); this.setTippy(elem.id, 'Full Screen', 'top-end');
if (this.debug) { this.popupPeerInfo(p.id, this.peer_info);
this.setTippy(
p.id,
JSON.stringify(
this.peer_info,
['peerName', 'isMobileDevice', 'osName', 'osVersion', 'browserName', 'browserVersion'],
2,
),
'top-start',
);
}
this.sound('joined'); this.sound('joined');
return elem; return elem;
} }
@@ -804,17 +797,7 @@ class RoomClient {
this.attachMediaStream(elem, stream, type, 'Consumer'); this.attachMediaStream(elem, stream, type, 'Consumer');
this.handleFS(elem.id); this.handleFS(elem.id);
this.setTippy(elem.id, 'Full Screen', 'top-end'); this.setTippy(elem.id, 'Full Screen', 'top-end');
if (this.debug) { this.popupPeerInfo(p.id, peer_info);
this.setTippy(
p.id,
JSON.stringify(
peer_info,
['peerName', 'isMobileDevice', 'osName', 'osVersion', 'browserName', 'browserVersion'],
2,
),
'top-start',
);
}
this.sound('joined'); this.sound('joined');
break; break;
case mediaType.audio: case mediaType.audio:
@@ -966,10 +949,9 @@ class RoomClient {
return document.getElementById(id); return document.getElementById(id);
} }
async getMyRoomInfo() { async getRoomInfo() {
let roomInfo = await this.socket.request('getMyRoomInfo'); let room_info = await this.socket.request('getRoomInfo');
console.log('Room info', roomInfo); return room_info;
return roomInfo;
} }
// #################################################### // ####################################################
@@ -982,9 +964,9 @@ class RoomClient {
async sound(name) { async sound(name) {
let sound = '../sounds/' + name + '.wav'; let sound = '../sounds/' + name + '.wav';
let audioToPlay = new Audio(sound); let audio = new Audio(sound);
try { try {
await audioToPlay.play(); await audio.play();
} catch (err) { } catch (err) {
return false; return false;
} }
@@ -1441,4 +1423,73 @@ class RoomClient {
if (result.isConfirmed) this.exit(); if (result.isConfirmed) this.exit();
}); });
} }
// ####################################################
// PEER ACTION
// ####################################################
peerAction(from_peer_name, peer_id, action, emit = true) {
switch (action) {
case 'eject':
let peer = this.getId(peer_id);
if (peer) peer.parentNode.removeChild(peer);
if (peer_id === this.peer_id) {
this.sound(action);
let timerInterval;
Swal.fire({
allowOutsideClick: false,
background: swalBackground,
title: from_peer_name,
html: 'Will eject you from the room after <b style="color: red;"></b> milliseconds.',
timer: 5000,
timerProgressBar: true,
didOpen: () => {
Swal.showLoading();
const b = Swal.getHtmlContainer().querySelector('b');
timerInterval = setInterval(() => {
b.textContent = Swal.getTimerLeft();
}, 100);
},
willClose: () => {
clearInterval(timerInterval);
},
}).then(() => {
this.exit();
});
}
break;
// ...
}
if (emit) {
let data = {
from_peer_name: this.peer_name,
peer_id: peer_id,
action: action,
};
this.socket.emit('peerAction', data);
}
}
popupPeerInfo(id, peer_info) {
if (this.debug) {
this.setTippy(
id,
JSON.stringify(
peer_info,
[
'peer_name',
'peer_audio',
'peer_video',
'is_mobile_device',
'os_name',
'os_version',
'browser_name',
'browser_version',
],
2,
),
'top-start',
);
}
}
} }

ثنائية
public/sounds/eject.wav Normal file

ملف ثنائي غير معروض.

عرض الملف

@@ -6,10 +6,10 @@ const log = new Logger('Peer');
module.exports = class Peer { module.exports = class Peer {
constructor(socket_id, data) { constructor(socket_id, data) {
this.id = socket_id; this.id = socket_id;
this.peer_name = data.peer_name;
this.peer_audio = data.peer_audio;
this.peer_video = data.peer_video;
this.peer_info = data.peer_info; this.peer_info = data.peer_info;
this.peer_name = data.peer_info.peer_name;
this.peer_audio = data.peer_info.peer_audio;
this.peer_video = data.peer_info.peer_video;
this.transports = new Map(); this.transports = new Map();
this.consumers = new Map(); this.consumers = new Map();
this.producers = new Map(); this.producers = new Map();
@@ -55,7 +55,7 @@ module.exports = class Peer {
'transportclose', 'transportclose',
function () { function () {
log.debug('Producer transport close', { log.debug('Producer transport close', {
peer_name: this.peer_name, peer_name: this.peer_info.peer_name,
consumer_id: producer.id, consumer_id: producer.id,
}); });
producer.close(); producer.close();
@@ -107,7 +107,7 @@ module.exports = class Peer {
'transportclose', 'transportclose',
function () { function () {
log.debug('Consumer transport close', { log.debug('Consumer transport close', {
peer_name: this.peer_name, peer_name: this.peer_info.peer_name,
consumer_id: consumer.id, consumer_id: consumer.id,
}); });
this.consumers.delete(consumer.id); this.consumers.delete(consumer.id);

عرض الملف

@@ -203,13 +203,19 @@ module.exports = class Room {
// SENDER // SENDER
// #################################################### // ####################################################
broadCast(socket_id, peer_name, data) { broadCast(socket_id, action, data) {
for (let otherID of Array.from(this.peers.keys()).filter((id) => id !== socket_id)) { for (let otherID of Array.from(this.peers.keys()).filter((id) => id !== socket_id)) {
this.send(otherID, peer_name, data); this.send(otherID, action, data);
} }
} }
send(socket_id, peer_name, data) { sendTo(socket_id, action, data) {
this.io.to(socket_id).emit(peer_name, data); for (let peer_id of Array.from(this.peers.keys()).filter((id) => id === socket_id)) {
this.send(peer_id, action, data);
}
}
send(socket_id, action, data) {
this.io.to(socket_id).emit(action, data);
} }
}; };

عرض الملف

@@ -213,10 +213,14 @@ io.on('connection', (socket) => {
break; break;
} }
log.debug('Room locked:', roomList.get(socket.room_id).isLocked()); log.debug('Room locked:', roomList.get(socket.room_id).isLocked());
// send to all participants
roomList.get(socket.room_id).broadCast(socket.id, 'roomAction', action); roomList.get(socket.room_id).broadCast(socket.id, 'roomAction', action);
}); });
socket.on('peerAction', (data) => {
log.debug('Peer action:', data);
roomList.get(socket.room_id).sendTo(data.peer_id, 'peerAction', data);
});
socket.on('join', (data, cb) => { socket.on('join', (data, cb) => {
if (!roomList.has(socket.room_id)) { if (!roomList.has(socket.room_id)) {
return cb({ return cb({
@@ -329,7 +333,7 @@ io.on('connection', (socket) => {
callback(); callback();
}); });
socket.on('getMyRoomInfo', (_, cb) => { socket.on('getRoomInfo', (_, cb) => {
cb(roomList.get(socket.room_id).toJson()); cb(roomList.get(socket.room_id).toJson());
}); });
@@ -378,9 +382,12 @@ io.on('connection', (socket) => {
if (json) { if (json) {
return { return {
peer_name: peer_name:
roomList.get(socket.room_id) && roomList.get(socket.room_id).getPeers().get(socket.id).peer_name, roomList.get(socket.room_id) &&
roomList.get(socket.room_id).getPeers().get(socket.id).peer_info.peer_name,
}; };
} }
return roomList.get(socket.room_id) && roomList.get(socket.room_id).getPeers().get(socket.id).peer_name; return (
roomList.get(socket.room_id) && roomList.get(socket.room_id).getPeers().get(socket.id).peer_info.peer_name
);
} }
}); });