[mirotalksfu] - refactoring producer
هذا الالتزام موجود في:
@@ -55,7 +55,7 @@ dev dependencies: {
|
|||||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
* @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
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.7.00
|
* @version 1.7.01
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mirotalksfu",
|
"name": "mirotalksfu",
|
||||||
"version": "1.7.00",
|
"version": "1.7.01",
|
||||||
"description": "WebRTC SFU browser-based video calls",
|
"description": "WebRTC SFU browser-based video calls",
|
||||||
"main": "Server.js",
|
"main": "Server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
"ngrok": "^5.0.0-beta.2",
|
"ngrok": "^5.0.0-beta.2",
|
||||||
"nodemailer": "^6.9.16",
|
"nodemailer": "^6.9.16",
|
||||||
"openai": "^4.78.1",
|
"openai": "^4.78.1",
|
||||||
"qs": "6.13.1",
|
"qs": "6.14.0",
|
||||||
"socket.io": "4.8.1",
|
"socket.io": "4.8.1",
|
||||||
"swagger-ui-express": "5.0.1",
|
"swagger-ui-express": "5.0.1",
|
||||||
"uuid": "11.0.5"
|
"uuid": "11.0.5"
|
||||||
|
|||||||
@@ -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 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
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.7.00
|
* @version 1.7.01
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -4904,7 +4904,7 @@ function showAbout() {
|
|||||||
imageUrl: image.about,
|
imageUrl: image.about,
|
||||||
customClass: { image: 'img-about' },
|
customClass: { image: 'img-about' },
|
||||||
position: 'center',
|
position: 'center',
|
||||||
title: 'WebRTC SFU v1.7.00',
|
title: 'WebRTC SFU v1.7.01',
|
||||||
html: `
|
html: `
|
||||||
<br />
|
<br />
|
||||||
<div id="about">
|
<div id="about">
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
* @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
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.7.00
|
* @version 1.7.01
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1421,8 +1421,12 @@ class RoomClient {
|
|||||||
|
|
||||||
async produce(type, deviceId = null, swapCamera = false, init = false) {
|
async produce(type, deviceId = null, swapCamera = false, init = false) {
|
||||||
let mediaConstraints = {};
|
let mediaConstraints = {};
|
||||||
|
let elem;
|
||||||
|
let stream;
|
||||||
let audio = false;
|
let audio = false;
|
||||||
|
let video = false;
|
||||||
let screen = false;
|
let screen = false;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case mediaType.audio:
|
case mediaType.audio:
|
||||||
this.isAudioAllowed = true;
|
this.isAudioAllowed = true;
|
||||||
@@ -1434,6 +1438,7 @@ class RoomClient {
|
|||||||
swapCamera
|
swapCamera
|
||||||
? (mediaConstraints = this.getCameraConstraints())
|
? (mediaConstraints = this.getCameraConstraints())
|
||||||
: (mediaConstraints = this.getVideoConstraints(deviceId));
|
: (mediaConstraints = this.getVideoConstraints(deviceId));
|
||||||
|
video = true;
|
||||||
break;
|
break;
|
||||||
case mediaType.screen:
|
case mediaType.screen:
|
||||||
mediaConstraints = this.getScreenConstraints();
|
mediaConstraints = this.getScreenConstraints();
|
||||||
@@ -1442,9 +1447,11 @@ class RoomClient {
|
|||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.device.canProduce('video') && !audio) {
|
if (!this.device.canProduce('video') && !audio) {
|
||||||
return console.error('Cannot produce video');
|
return console.error('Cannot produce video');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.producerLabel.has(type)) {
|
if (this.producerLabel.has(type)) {
|
||||||
return console.warn('Producer already exists for this type ' + type);
|
return console.warn('Producer already exists for this type ' + type);
|
||||||
}
|
}
|
||||||
@@ -1454,7 +1461,6 @@ class RoomClient {
|
|||||||
|
|
||||||
console.log(`Media constraints ${type}:`, mediaConstraints);
|
console.log(`Media constraints ${type}:`, mediaConstraints);
|
||||||
|
|
||||||
let stream;
|
|
||||||
try {
|
try {
|
||||||
if (init) {
|
if (init) {
|
||||||
stream = initStream;
|
stream = initStream;
|
||||||
@@ -1487,7 +1493,7 @@ class RoomClient {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!audio && !screen) {
|
if (video) {
|
||||||
const { encodings, codec } = this.getWebCamEncoding();
|
const { encodings, codec } = this.getWebCamEncoding();
|
||||||
console.log('GET WEBCAM ENCODING', {
|
console.log('GET WEBCAM ENCODING', {
|
||||||
encodings: encodings,
|
encodings: encodings,
|
||||||
@@ -1500,7 +1506,7 @@ class RoomClient {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!audio && screen) {
|
if (screen) {
|
||||||
const { encodings, codec } = this.getScreenEncoding();
|
const { encodings, codec } = this.getScreenEncoding();
|
||||||
console.log('GET SCREEN ENCODING', {
|
console.log('GET SCREEN ENCODING', {
|
||||||
encodings: encodings,
|
encodings: encodings,
|
||||||
@@ -1535,84 +1541,42 @@ class RoomClient {
|
|||||||
this.produceScreenAudio(stream);
|
this.produceScreenAudio(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem, au;
|
|
||||||
if (!audio) {
|
if (!audio) {
|
||||||
this.localVideoStream = stream;
|
this.localVideoStream = stream;
|
||||||
if (type == mediaType.video) this.videoProducerId = producer.id;
|
|
||||||
if (type == mediaType.screen) this.screenProducerId = producer.id;
|
|
||||||
elem = await this.handleProducer(producer.id, type, stream);
|
elem = await this.handleProducer(producer.id, type, stream);
|
||||||
|
|
||||||
|
if (video) this.videoProducerId = producer.id;
|
||||||
|
if (screen) this.screenProducerId = producer.id;
|
||||||
|
|
||||||
// No mirror effect for producer
|
// No mirror effect for producer
|
||||||
if (!isInitVideoMirror && elem.classList.contains('mirror')) {
|
if (!isInitVideoMirror && elem.classList.contains('mirror')) {
|
||||||
elem.classList.remove('mirror');
|
elem.classList.remove('mirror');
|
||||||
}
|
}
|
||||||
//if (!screen && !isEnumerateDevices) enumerateVideoDevices(stream);
|
|
||||||
} else {
|
} else {
|
||||||
this.localAudioStream = stream;
|
this.localAudioStream = stream;
|
||||||
|
|
||||||
|
elem = await this.handleProducer(producer.id, type, stream);
|
||||||
|
|
||||||
this.audioProducerId = producer.id;
|
this.audioProducerId = producer.id;
|
||||||
au = await this.handleProducer(producer.id, type, stream);
|
|
||||||
//if (!isEnumerateDevices) enumerateAudioDevices(stream);
|
|
||||||
getMicrophoneVolumeIndicator(stream);
|
getMicrophoneVolumeIndicator(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == mediaType.video) {
|
if (video) {
|
||||||
this.handleHideMe();
|
this.handleHideMe();
|
||||||
}
|
}
|
||||||
|
|
||||||
producer.on('trackended', () => {
|
producer.on('trackended', () => {
|
||||||
console.log('Producer track ended', { id: producer.id, type });
|
this.closeProducer(type, 'trackended');
|
||||||
this.closeProducer(type);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
producer.on('transportclose', () => {
|
producer.on('transportclose', () => {
|
||||||
console.log('Producer transport close', { id: producer.id, type });
|
this.closeProducer(type, 'transportclose');
|
||||||
if (!audio) {
|
|
||||||
const d = this.getId(producer.id + '__video');
|
|
||||||
const vb = this.getId(producer.id + '__vb');
|
|
||||||
|
|
||||||
elem.srcObject.getTracks().forEach(function (track) {
|
|
||||||
track.stop();
|
|
||||||
});
|
|
||||||
elem.parentNode.removeChild(elem);
|
|
||||||
|
|
||||||
d.parentNode.removeChild(d);
|
|
||||||
vb.parentNode.removeChild(vb);
|
|
||||||
|
|
||||||
handleAspectRatio();
|
|
||||||
console.log('[transportClose] Video-element-count', this.videoMediaContainer.childElementCount);
|
|
||||||
} else {
|
|
||||||
au.srcObject.getTracks().forEach(function (track) {
|
|
||||||
track.stop();
|
|
||||||
});
|
|
||||||
au.parentNode.removeChild(au);
|
|
||||||
console.log('[transportClose] audio-element-count', this.localAudioEl.childElementCount);
|
|
||||||
}
|
|
||||||
this.closeProducer(type);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
producer.on('close', () => {
|
producer.on('close', () => {
|
||||||
console.log('Closing producer', { id: producer.id, type });
|
this.closeProducer(type, 'close');
|
||||||
if (!audio) {
|
|
||||||
const d = this.getId(producer.id + '__video');
|
|
||||||
const vb = this.getId(producer.id + '__vb');
|
|
||||||
|
|
||||||
elem.srcObject.getTracks().forEach(function (track) {
|
|
||||||
track.stop();
|
|
||||||
});
|
|
||||||
elem.parentNode.removeChild(elem);
|
|
||||||
|
|
||||||
d.parentNode.removeChild(d);
|
|
||||||
vb.parentNode.removeChild(vb);
|
|
||||||
|
|
||||||
handleAspectRatio();
|
|
||||||
console.log('[closingProducer] Video-element-count', this.videoMediaContainer.childElementCount);
|
|
||||||
} else {
|
|
||||||
au.srcObject.getTracks().forEach(function (track) {
|
|
||||||
track.stop();
|
|
||||||
});
|
|
||||||
au.parentNode.removeChild(au);
|
|
||||||
console.log('[closingProducer] audio-element-count', this.localAudioEl.childElementCount);
|
|
||||||
}
|
|
||||||
this.closeProducer(type);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -1987,7 +1951,7 @@ class RoomClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
closeThenProduce(type, deviceId = null, swapCamera = false) {
|
closeThenProduce(type, deviceId = null, swapCamera = false) {
|
||||||
this.closeProducer(type);
|
this.closeProducer(type, 'closeThenProduce');
|
||||||
setTimeout(async function () {
|
setTimeout(async function () {
|
||||||
await rc.produce(type, deviceId, swapCamera);
|
await rc.produce(type, deviceId, swapCamera);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
@@ -2122,7 +2086,7 @@ class RoomClient {
|
|||||||
case mediaType.audio:
|
case mediaType.audio:
|
||||||
elem = document.createElement('audio');
|
elem = document.createElement('audio');
|
||||||
elem.setAttribute('id', id);
|
elem.setAttribute('id', id);
|
||||||
elem.setAttribute('name', id + '__localAudio');
|
elem.setAttribute('name', 'LOCAL-AUDIO');
|
||||||
elem.setAttribute('volume', this.peer_id + '___pVolume');
|
elem.setAttribute('volume', this.peer_id + '___pVolume');
|
||||||
elem.controls = false;
|
elem.controls = false;
|
||||||
elem.autoplay = true;
|
elem.autoplay = true;
|
||||||
@@ -2209,7 +2173,7 @@ class RoomClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closeProducer(type) {
|
closeProducer(type, event = 'Close Producer') {
|
||||||
if (!this.producerLabel.has(type)) {
|
if (!this.producerLabel.has(type)) {
|
||||||
return console.warn('There is no producer for this type ' + type);
|
return console.warn('There is no producer for this type ' + type);
|
||||||
}
|
}
|
||||||
@@ -2222,7 +2186,7 @@ class RoomClient {
|
|||||||
type: type,
|
type: type,
|
||||||
status: false,
|
status: false,
|
||||||
};
|
};
|
||||||
console.log(`Close producer ${type}`, data);
|
console.log(`${event} ${type}`, data);
|
||||||
|
|
||||||
this.socket.emit('producerClosed', data);
|
this.socket.emit('producerClosed', data);
|
||||||
|
|
||||||
@@ -2230,19 +2194,9 @@ class RoomClient {
|
|||||||
this.producers.delete(producer_id);
|
this.producers.delete(producer_id);
|
||||||
this.producerLabel.delete(type);
|
this.producerLabel.delete(type);
|
||||||
|
|
||||||
console.log('[closeProducer] - PRODUCER LABEL', this.producerLabel);
|
console.log(`[${event}] - PRODUCER LABEL`, this.producerLabel);
|
||||||
|
|
||||||
if (type !== mediaType.audio) {
|
if (type === mediaType.video || type === mediaType.screen) {
|
||||||
const elem = this.getId(producer_id);
|
|
||||||
const d = this.getId(producer_id + '__video');
|
|
||||||
const vb = this.getId(producer_id + '__vb');
|
|
||||||
elem.srcObject.getTracks().forEach(function (track) {
|
|
||||||
track.stop();
|
|
||||||
});
|
|
||||||
d.parentNode.removeChild(d);
|
|
||||||
vb.parentNode.removeChild(vb);
|
|
||||||
|
|
||||||
//alert(this.pinnedVideoPlayerId + '==' + producer_id);
|
|
||||||
if (this.isVideoPinned && this.pinnedVideoPlayerId == producer_id) {
|
if (this.isVideoPinned && this.pinnedVideoPlayerId == producer_id) {
|
||||||
this.removeVideoPinMediaContainer();
|
this.removeVideoPinMediaContainer();
|
||||||
console.log('Remove pin container due the Producer close', {
|
console.log('Remove pin container due the Producer close', {
|
||||||
@@ -2251,21 +2205,24 @@ class RoomClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAspectRatio();
|
const video = this.getId(producer_id);
|
||||||
|
this.removeVideoProducer(video, event);
|
||||||
console.log('[producerClose] Video-element-count', this.videoMediaContainer.childElementCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === mediaType.audio) {
|
if (type === mediaType.audio) {
|
||||||
const au = this.getName(producer_id + '__localAudio');
|
const audio = this.getId(producer_id);
|
||||||
au.srcObject.getTracks().forEach(function (track) {
|
this.removeAudioProducer(audio, event);
|
||||||
track.stop();
|
}
|
||||||
});
|
|
||||||
this.localAudioEl.removeChild(au);
|
if (type === mediaType.audioTab) {
|
||||||
console.log('[producerClose] Audio-element-count', this.localAudioEl.childElementCount);
|
const auTab = this.getId(producer_id);
|
||||||
|
this.removeAudioProducer(auTab, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case mediaType.audioTab:
|
||||||
|
console.log('Closed audio tab');
|
||||||
|
break;
|
||||||
case mediaType.audio:
|
case mediaType.audio:
|
||||||
this.setIsAudio(this.peer_id, false);
|
this.setIsAudio(this.peer_id, false);
|
||||||
this.event(_EVENTS.stopAudio);
|
this.event(_EVENTS.stopAudio);
|
||||||
@@ -2311,34 +2268,51 @@ class RoomClient {
|
|||||||
const sa = await this.handleProducer(producerSa.id, mediaType.audio, stream);
|
const sa = await this.handleProducer(producerSa.id, mediaType.audio, stream);
|
||||||
|
|
||||||
producerSa.on('trackended', () => {
|
producerSa.on('trackended', () => {
|
||||||
console.log('Producer Screen audio track ended', { id: producerSa.id });
|
this.closeProducer(mediaType.audioTab, 'trackended');
|
||||||
this.closeProducer(mediaType.audioTab);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
producerSa.on('transportclose', () => {
|
producerSa.on('transportclose', () => {
|
||||||
console.log('Producer Screen audio transport close', { id: producerSa.id });
|
this.closeProducer(mediaType.audioTab, 'transportclose');
|
||||||
sa.srcObject.getTracks().forEach(function (track) {
|
|
||||||
track.stop();
|
|
||||||
});
|
|
||||||
sa.parentNode.removeChild(sa);
|
|
||||||
console.log('[transportClose] audio-element-count', this.localAudioEl.childElementCount);
|
|
||||||
this.closeProducer(mediaType.audioTab);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
producerSa.on('close', () => {
|
producerSa.on('close', () => {
|
||||||
console.log('Closing Screen audio producer', { id: producerSa.id });
|
this.closeProducer(mediaType.audioTab, 'close');
|
||||||
sa.srcObject.getTracks().forEach(function (track) {
|
|
||||||
track.stop();
|
|
||||||
});
|
|
||||||
sa.parentNode.removeChild(sa);
|
|
||||||
console.log('[closingProducer] audio-element-count', this.localAudioEl.childElementCount);
|
|
||||||
this.closeProducer(mediaType.audioTab);
|
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Produce Screen Audio error:', err);
|
console.error('Produce Screen Audio error:', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ####################################################
|
||||||
|
// REMOVE PRODUCER VIDEO/AUDIO
|
||||||
|
// ####################################################
|
||||||
|
|
||||||
|
removeVideoProducer(video, event) {
|
||||||
|
const d = this.getId(video.id + '__video');
|
||||||
|
const vb = this.getId(video.id + '__vb');
|
||||||
|
|
||||||
|
video.srcObject.getTracks().forEach(function (track) {
|
||||||
|
track.stop();
|
||||||
|
});
|
||||||
|
video.parentNode.removeChild(video);
|
||||||
|
|
||||||
|
d.parentNode.removeChild(d);
|
||||||
|
vb.parentNode.removeChild(vb);
|
||||||
|
|
||||||
|
handleAspectRatio();
|
||||||
|
|
||||||
|
console.log(`[${event}] Video-element-count`, this.videoMediaContainer.childElementCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeAudioProducer(audio, event) {
|
||||||
|
audio.srcObject.getTracks().forEach(function (track) {
|
||||||
|
track.stop();
|
||||||
|
});
|
||||||
|
audio.parentNode.removeChild(audio);
|
||||||
|
|
||||||
|
console.log(`[${event}] audio-element-count`, this.localAudioEl.childElementCount);
|
||||||
|
}
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// CONSUMER
|
// CONSUMER
|
||||||
// ####################################################
|
// ####################################################
|
||||||
@@ -7911,7 +7885,7 @@ class RoomClient {
|
|||||||
break;
|
break;
|
||||||
case 'hide':
|
case 'hide':
|
||||||
if (peerActionAllowed) {
|
if (peerActionAllowed) {
|
||||||
this.closeProducer(mediaType.video);
|
this.closeProducer(mediaType.video, 'moderator');
|
||||||
this.userLog(
|
this.userLog(
|
||||||
'warning',
|
'warning',
|
||||||
from_peer_name + ' ' + _PEER.videoOff + ' has closed yours video',
|
from_peer_name + ' ' + _PEER.videoOff + ' has closed yours video',
|
||||||
@@ -7933,7 +7907,7 @@ class RoomClient {
|
|||||||
case 'stop':
|
case 'stop':
|
||||||
if (this.isScreenShareSupported) {
|
if (this.isScreenShareSupported) {
|
||||||
if (peerActionAllowed) {
|
if (peerActionAllowed) {
|
||||||
this.closeProducer(mediaType.screen);
|
this.closeProducer(mediaType.screen, 'moderator');
|
||||||
this.userLog(
|
this.userLog(
|
||||||
'warning',
|
'warning',
|
||||||
from_peer_name + ' ' + _PEER.screenOff + ' has closed yours screen share',
|
from_peer_name + ' ' + _PEER.screenOff + ' has closed yours screen share',
|
||||||
@@ -8521,39 +8495,8 @@ class RoomClient {
|
|||||||
|
|
||||||
popupPeerInfo(id, peer_info) {
|
popupPeerInfo(id, peer_info) {
|
||||||
if (this.showPeerInfo && !this.isMobileDevice) {
|
if (this.showPeerInfo && !this.isMobileDevice) {
|
||||||
//console.log('POPUP_PEER_INFO', peer_info);
|
|
||||||
|
|
||||||
// Destructuring peer_info
|
|
||||||
const {
|
|
||||||
join_data_time,
|
|
||||||
peer_name,
|
|
||||||
peer_presenter,
|
|
||||||
is_desktop_device,
|
|
||||||
is_mobile_device,
|
|
||||||
is_tablet_device,
|
|
||||||
is_ipad_pro_device,
|
|
||||||
os_name,
|
|
||||||
os_version,
|
|
||||||
browser_name,
|
|
||||||
browser_version,
|
|
||||||
} = peer_info;
|
|
||||||
|
|
||||||
const emojiPeerInfo = [
|
|
||||||
{ label: 'Join Time', value: join_data_time, emoji: '⏰' },
|
|
||||||
{ label: 'Name', value: peer_name, emoji: '👤' },
|
|
||||||
{ label: 'Presenter', value: peer_presenter ? 'Yes' : 'No', emoji: peer_presenter ? '⭐' : '🎤' },
|
|
||||||
{ label: 'Desktop Device', value: is_desktop_device ? 'Yes' : 'No', emoji: '💻' },
|
|
||||||
{ label: 'Mobile Device', value: is_mobile_device ? 'Yes' : 'No', emoji: '📱' },
|
|
||||||
{ label: 'Tablet Device', value: is_tablet_device ? 'Yes' : 'No', emoji: '📲' },
|
|
||||||
{ label: 'iPad Pro', value: is_ipad_pro_device ? 'Yes' : 'No', emoji: '📱' },
|
|
||||||
{ label: 'OS', value: `${os_name} ${os_version}`, emoji: '🖥️' },
|
|
||||||
{ label: 'Browser', value: `${browser_name} ${browser_version}`, emoji: '🌐' },
|
|
||||||
];
|
|
||||||
|
|
||||||
// Format the peer info into a structured string
|
// Format the peer info into a structured string
|
||||||
const peerInfoFormatted = emojiPeerInfo
|
const peerInfoFormatted = this.getPeerUiInfos();
|
||||||
.map((item) => `${item.emoji} <b>${item.label}:</b> ${item.value}`)
|
|
||||||
.join('<br/>');
|
|
||||||
|
|
||||||
// Apply the improved Tippy.js tooltip
|
// Apply the improved Tippy.js tooltip
|
||||||
this.setTippy(
|
this.setTippy(
|
||||||
@@ -8565,6 +8508,38 @@ class RoomClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPeerUiInfos() {
|
||||||
|
// console.log('PEER_INFO', peer_info);
|
||||||
|
const {
|
||||||
|
join_data_time,
|
||||||
|
peer_name,
|
||||||
|
peer_presenter,
|
||||||
|
is_desktop_device,
|
||||||
|
is_mobile_device,
|
||||||
|
is_tablet_device,
|
||||||
|
is_ipad_pro_device,
|
||||||
|
os_name,
|
||||||
|
os_version,
|
||||||
|
browser_name,
|
||||||
|
browser_version,
|
||||||
|
} = peer_info;
|
||||||
|
|
||||||
|
const emojiPeerInfo = [
|
||||||
|
{ label: 'Join Time', value: join_data_time, emoji: '⏰' },
|
||||||
|
{ label: 'Name', value: peer_name, emoji: '👤' },
|
||||||
|
{ label: 'Presenter', value: peer_presenter ? 'Yes' : 'No', emoji: peer_presenter ? '⭐' : '🎤' },
|
||||||
|
{ label: 'Desktop Device', value: is_desktop_device ? 'Yes' : 'No', emoji: '💻' },
|
||||||
|
{ label: 'Mobile Device', value: is_mobile_device ? 'Yes' : 'No', emoji: '📱' },
|
||||||
|
{ label: 'Tablet Device', value: is_tablet_device ? 'Yes' : 'No', emoji: '📲' },
|
||||||
|
{ label: 'iPad Pro', value: is_ipad_pro_device ? 'Yes' : 'No', emoji: '📱' },
|
||||||
|
{ label: 'OS', value: `${os_name} ${os_version}`, emoji: '🖥️' },
|
||||||
|
{ label: 'Browser', value: `${browser_name} ${browser_version}`, emoji: '🌐' },
|
||||||
|
];
|
||||||
|
|
||||||
|
// Format the peer info into a structured string
|
||||||
|
return emojiPeerInfo.map((item) => `${item.emoji} <b>${item.label}:</b> ${item.value}`).join('<br/>');
|
||||||
|
}
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// HANDLE PEER GEOLOCATION
|
// HANDLE PEER GEOLOCATION
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم