[mirotalk] - add geoLocation, update dep
This commit is contained in:
@@ -142,6 +142,7 @@ module.exports = {
|
||||
showSnapShotBtn: true,
|
||||
showFileShareBtn: true,
|
||||
showShareVideoAudioBtn: true,
|
||||
showGeoLocationBtn: true,
|
||||
showPrivateMessageBtn: true,
|
||||
showZoomInOutBtn: false,
|
||||
showVideoFocusBtn: true,
|
||||
|
||||
+37
-1
@@ -45,7 +45,7 @@ dependencies: {
|
||||
* @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon
|
||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661
|
||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||
* @version 1.5.18
|
||||
* @version 1.5.19
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1512,6 +1512,42 @@ io.sockets.on('connect', async (socket) => {
|
||||
await sendToRoom(data.room_id, socket.id, 'message', data);
|
||||
});
|
||||
|
||||
/**
|
||||
* Relay commands to peers or specific peer in the same room
|
||||
* @param {Object} cfg - The configuration object containing command details.
|
||||
* @param {string} cfg.action - The action to be performed (e.g., 'geoLocation').
|
||||
* @param {boolean} cfg.send_to_all - Whether to send the command to all peers in the room.
|
||||
* @param {Object} cfg.data - The data associated with the command.
|
||||
*/
|
||||
socket.on('cmd', async (cfg) => {
|
||||
const config = checkXSS(cfg);
|
||||
|
||||
const { action, send_to_all, data } = config;
|
||||
|
||||
const { room_id, peer_id, peer_name, peer_uuid, to_peer_id } = data;
|
||||
|
||||
log.info('cmd', config);
|
||||
|
||||
// Only the presenter can do this actions
|
||||
const presenterActions = ['geoLocation'];
|
||||
if (presenterActions.some((v) => action === v)) {
|
||||
// Check if peer is presenter
|
||||
const isPresenter = isPeerPresenter(room_id, peer_id, peer_name, peer_uuid);
|
||||
// if not presenter do nothing
|
||||
if (!isPresenter) return;
|
||||
}
|
||||
|
||||
if (send_to_all) {
|
||||
log.debug('[' + socket.id + '] emit cmd to [room_id: ' + room_id + ']', config);
|
||||
|
||||
await sendToRoom(room_id, socket.id, 'cmd', config);
|
||||
} else {
|
||||
log.debug('[' + socket.id + '] emit cmd to [' + to_peer_id + '] from room_id [' + room_id + ']');
|
||||
|
||||
await sendToPeer(to_peer_id, sockets, 'cmd', config);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Relay Audio Video Hand ... Status to peers
|
||||
*/
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mirotalk",
|
||||
"version": "1.5.18",
|
||||
"version": "1.5.19",
|
||||
"description": "A free WebRTC browser-based video call",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
@@ -61,14 +61,14 @@
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
"nodemailer": "^7.0.3",
|
||||
"openai": "^5.1.1",
|
||||
"openai": "^5.2.0",
|
||||
"qs": "^6.14.0",
|
||||
"socket.io": "^4.8.1",
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
"uuid": "11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^11.5.0",
|
||||
"mocha": "^11.6.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"nodemon": "^3.1.10",
|
||||
"prettier": "3.5.3",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
+1
-1
@@ -73,7 +73,7 @@ let brand = {
|
||||
},
|
||||
about: {
|
||||
imageUrl: '../images/mirotalk-logo.gif',
|
||||
title: 'WebRTC P2P v1.5.18',
|
||||
title: 'WebRTC P2P v1.5.19',
|
||||
html: `
|
||||
<button
|
||||
id="support-button"
|
||||
|
||||
@@ -62,6 +62,7 @@ let buttons = {
|
||||
showSnapShotBtn: true,
|
||||
showFileShareBtn: true,
|
||||
showShareVideoAudioBtn: true,
|
||||
showGeoLocationBtn: true,
|
||||
showPrivateMessageBtn: true,
|
||||
showZoomInOutBtn: false,
|
||||
showVideoFocusBtn: true,
|
||||
|
||||
+74
-2
@@ -15,7 +15,7 @@
|
||||
* @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon
|
||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661
|
||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||
* @version 1.5.18
|
||||
* @version 1.5.19
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -51,6 +51,7 @@ const images = {
|
||||
avatar: '../images/mirotalk-logo.png',
|
||||
recording: '../images/recording.png',
|
||||
poster: '../images/loader.gif',
|
||||
geoLocation: '../images/geolocation.png',
|
||||
}; // nice free icon: https://www.iconfinder.com
|
||||
|
||||
const className = {
|
||||
@@ -75,6 +76,7 @@ const className = {
|
||||
fsOn: 'fas fa-compress-alt',
|
||||
fsOff: 'fas fa-expand-alt',
|
||||
msgPrivate: 'fas fa-paper-plane',
|
||||
geoLocation: 'fas fa-location-dot',
|
||||
shareFile: 'fas fa-upload',
|
||||
shareVideoAudio: 'fab fa-youtube',
|
||||
kickOut: 'fas fa-sign-out-alt',
|
||||
@@ -687,6 +689,29 @@ let surveyURL = 'https://www.questionpro.com/t/AUs7VZq00L';
|
||||
let redirectActive = false;
|
||||
let redirectURL = '/newcall';
|
||||
|
||||
// GeoLocation
|
||||
const notificationService = new NotificationService({ Swal, swBg, images, playSound });
|
||||
const geoService = GeoService;
|
||||
let geo;
|
||||
|
||||
/**
|
||||
* Load GeoLocation service
|
||||
* @returns {void}
|
||||
*/
|
||||
function loadGeo() {
|
||||
geo = new PeerGeoLocation({
|
||||
room_id: roomId,
|
||||
peer_name: myPeerName,
|
||||
peer_id: myPeerId,
|
||||
peer_uuid: myPeerUUID,
|
||||
sendToServer,
|
||||
msgPopup,
|
||||
notificationService,
|
||||
geoService,
|
||||
openURL,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all Html elements by Id
|
||||
*/
|
||||
@@ -1168,6 +1193,7 @@ function initClientPeer() {
|
||||
signalingSocket.on('peerName', handlePeerName);
|
||||
signalingSocket.on('peerStatus', handlePeerStatus);
|
||||
signalingSocket.on('peerAction', handlePeerAction);
|
||||
signalingSocket.on('cmd', handleCmd);
|
||||
signalingSocket.on('message', handleMessage);
|
||||
signalingSocket.on('wbCanvasToJson', handleJsonToWbCanvas);
|
||||
signalingSocket.on('whiteboardAction', handleWhiteboardAction);
|
||||
@@ -1339,6 +1365,7 @@ function handleRules(isPresenter) {
|
||||
buttons.settings.showTabRoomSecurity = false;
|
||||
buttons.settings.showTabEmailInvitation = false;
|
||||
buttons.remote.showKickOutBtn = false;
|
||||
buttons.remote.showGeoLocationBtn = false;
|
||||
buttons.whiteboard.whiteboardLockBtn = false;
|
||||
//...
|
||||
} else {
|
||||
@@ -1471,6 +1498,7 @@ async function whoAreYou() {
|
||||
if (!myToken) return userNameAlreadyInRoom(); // #209 Hack...
|
||||
}
|
||||
|
||||
loadGeo();
|
||||
checkPeerAudioVideo();
|
||||
whoAreYouJoin();
|
||||
playSound('addPeer');
|
||||
@@ -1567,6 +1595,7 @@ async function whoAreYou() {
|
||||
usernameEmoji.classList.add('hidden');
|
||||
}
|
||||
window.localStorage.peer_name = myPeerName;
|
||||
loadGeo();
|
||||
whoAreYouJoin();
|
||||
}
|
||||
},
|
||||
@@ -3354,6 +3383,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
const remoteVideoAudioUrlBtn = document.createElement('button');
|
||||
const remoteFileShareBtn = document.createElement('button');
|
||||
const remotePrivateMsgBtn = document.createElement('button');
|
||||
const remoteGeoLocationBtn = document.createElement('button');
|
||||
const remotePeerKickOut = document.createElement('button');
|
||||
const remoteVideoToImgBtn = document.createElement('button');
|
||||
const remoteVideoFullScreenBtn = document.createElement('button');
|
||||
@@ -3406,6 +3436,10 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
remotePrivateMsgBtn.setAttribute('id', peer_id + '_privateMsg');
|
||||
remotePrivateMsgBtn.className = className.msgPrivate;
|
||||
|
||||
// remote geo location
|
||||
remoteGeoLocationBtn.setAttribute('id', peer_id + '_geoLocation');
|
||||
remoteGeoLocationBtn.className = className.geoLocation;
|
||||
|
||||
// remote share file
|
||||
remoteFileShareBtn.setAttribute('id', peer_id + '_shareFile');
|
||||
remoteFileShareBtn.className = className.shareFile;
|
||||
@@ -3457,6 +3491,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
setTippy(remoteAudioVolume, '🔊 Volume', 'top');
|
||||
setTippy(remoteVideoAudioUrlBtn, 'Send Video or Audio', 'bottom');
|
||||
setTippy(remotePrivateMsgBtn, 'Send private message', 'bottom');
|
||||
setTippy(remoteGeoLocationBtn, 'Get Geo Location', 'bottom');
|
||||
setTippy(remoteFileShareBtn, 'Send file', 'bottom');
|
||||
setTippy(remoteVideoToImgBtn, 'Take a snapshot', 'bottom');
|
||||
setTippy(remotePeerKickOut, 'Kick out', 'bottom');
|
||||
@@ -3506,6 +3541,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
remoteExpandContainerDiv.appendChild(remoteVideoZoomOutBtn);
|
||||
}
|
||||
buttons.remote.showPrivateMessageBtn && remoteExpandContainerDiv.appendChild(remotePrivateMsgBtn);
|
||||
buttons.remote.showGeoLocationBtn && remoteExpandContainerDiv.appendChild(remoteGeoLocationBtn);
|
||||
buttons.remote.showFileShareBtn && remoteExpandContainerDiv.appendChild(remoteFileShareBtn);
|
||||
buttons.remote.showShareVideoAudioBtn && remoteExpandContainerDiv.appendChild(remoteVideoAudioUrlBtn);
|
||||
buttons.remote.showKickOutBtn && remoteExpandContainerDiv.appendChild(remotePeerKickOut);
|
||||
@@ -3608,6 +3644,8 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
// handle remote peers video on-off
|
||||
handlePeerVideoBtn(peer_id);
|
||||
|
||||
// handle remote geo location
|
||||
buttons.remote.showGeoLocationBtn && handlePeerGeoLocation(peer_id, peer_name);
|
||||
// handle remote private messages
|
||||
buttons.remote.showPrivateMessageBtn && handlePeerPrivateMsg(peer_id, peer_name);
|
||||
// handle remote send file
|
||||
@@ -9035,6 +9073,15 @@ function handlePeerVideoBtn(peer_id) {
|
||||
};
|
||||
}
|
||||
|
||||
function handlePeerGeoLocation(peer_id) {
|
||||
const remoteGeoLocationBtn = getId(peer_id + '_geoLocation');
|
||||
remoteGeoLocationBtn.onclick = () => {
|
||||
isPresenter
|
||||
? geo.askPeerGeoLocation(peer_id)
|
||||
: msgPopup('warning', 'Only the presenter can ask geolocation to the participants', 'top-end', 4000);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Private Message to specific peer
|
||||
* @param {string} peer_id socket.id
|
||||
@@ -9202,6 +9249,31 @@ function handlePeerAction(config) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle commands from the server
|
||||
* @param {object} config data
|
||||
*/
|
||||
function handleCmd(config) {
|
||||
console.log('Handle cmd: ', config);
|
||||
|
||||
const { action, data } = config;
|
||||
|
||||
switch (action) {
|
||||
case 'geoLocation':
|
||||
// Peer is requesting your location
|
||||
geo.confirmPeerGeoLocation(data);
|
||||
break;
|
||||
case 'geoLocationOK':
|
||||
case 'geoLocationKO':
|
||||
// Peer responded with their location or an error/denial
|
||||
geo.handleGeoPeerLocation(config);
|
||||
break;
|
||||
//....
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incoming message
|
||||
* @param {object} message
|
||||
@@ -11168,7 +11240,7 @@ function showAbout() {
|
||||
Swal.fire({
|
||||
background: swBg,
|
||||
position: 'center',
|
||||
title: brand.about?.title && brand.about.title.trim() !== '' ? brand.about.title : 'WebRTC P2P v1.5.18',
|
||||
title: brand.about?.title && brand.about.title.trim() !== '' ? brand.about.title : 'WebRTC P2P v1.5.19',
|
||||
imageUrl: brand.about?.imageUrl && brand.about.imageUrl.trim() !== '' ? brand.about.imageUrl : images.about,
|
||||
customClass: { image: 'img-about' },
|
||||
html: `
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* NotificationService
|
||||
* Handles all user notifications and popups related to geolocation actions.
|
||||
* @class
|
||||
*/
|
||||
class NotificationService {
|
||||
/**
|
||||
* @param {Object} options
|
||||
* @param {Object} options.Swal - SweetAlert2 instance.
|
||||
* @param {string} options.swBg - Background color for Swal.
|
||||
* @param {Object} options.images - Images object containing geoLocation image.
|
||||
* @param {Function} options.playSound - Function to play notification sounds.
|
||||
*/
|
||||
constructor({ Swal, swBg, images, playSound }) {
|
||||
this.Swal = Swal;
|
||||
this.swalBackground = swBg;
|
||||
this.image = images.geoLocation;
|
||||
this.playSound = playSound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a progress popup with a timer.
|
||||
* @param {string} title
|
||||
* @param {string} message
|
||||
* @param {number} timeout - Duration in ms.
|
||||
* @param {string} [icon='success']
|
||||
*/
|
||||
showProgress(title, message, timeout, icon = 'success') {
|
||||
this.Swal.fire({
|
||||
allowOutsideClick: false,
|
||||
background: this.swalBackground,
|
||||
icon,
|
||||
title,
|
||||
html: message,
|
||||
timer: timeout,
|
||||
timerProgressBar: true,
|
||||
didOpen: () => {
|
||||
this.Swal.showLoading();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a confirmation popup asking the user to share their location.
|
||||
* @param {string} from_peer_name - Name of the peer requesting location.
|
||||
* @returns {Promise<Object>} Swal result promise.
|
||||
*/
|
||||
showConfirmLocation(from_peer_name) {
|
||||
this.playSound('notify');
|
||||
return this.Swal.fire({
|
||||
allowOutsideClick: false,
|
||||
allowEscapeKey: false,
|
||||
background: this.swalBackground,
|
||||
imageUrl: this.image,
|
||||
position: 'center',
|
||||
title: 'Geo Location',
|
||||
html: `Would you like to share your location to ${from_peer_name}?`,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: `Yes`,
|
||||
denyButtonText: `No`,
|
||||
showClass: { popup: 'animate__animated animate__fadeInDown' },
|
||||
hideClass: { popup: 'animate__animated animate__fadeOutUp' },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a popup asking the user if they want to open a peer's geolocation.
|
||||
* @param {string} peer_name - Name of the peer whose location is shared.
|
||||
* @returns {Promise<Object>} Swal result promise.
|
||||
*/
|
||||
showOpenLocation(peer_name) {
|
||||
this.playSound('notify');
|
||||
return this.Swal.fire({
|
||||
allowOutsideClick: false,
|
||||
allowEscapeKey: false,
|
||||
background: this.swalBackground,
|
||||
imageUrl: this.image,
|
||||
position: 'center',
|
||||
title: 'Geo Location',
|
||||
html: `Would you like to open ${peer_name} geolocation?`,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: `Yes`,
|
||||
denyButtonText: `No`,
|
||||
showClass: { popup: 'animate__animated animate__fadeInDown' },
|
||||
hideClass: { popup: 'animate__animated animate__fadeOutUp' },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GeoService
|
||||
* Static utility for accessing browser geolocation.
|
||||
* @class
|
||||
*/
|
||||
class GeoService {
|
||||
/**
|
||||
* Get the current position using the browser's geolocation API.
|
||||
* @param {Function} success - Success callback.
|
||||
* @param {Function} error - Error callback.
|
||||
* @param {PositionOptions} [options] - Geolocation options.
|
||||
*/
|
||||
static getCurrentPosition(success, error, options = {}) {
|
||||
if (typeof navigator !== 'undefined' && 'geolocation' in navigator) {
|
||||
navigator.geolocation.getCurrentPosition(success, error, {
|
||||
enableHighAccuracy: true,
|
||||
timeout: 10000,
|
||||
maximumAge: 0,
|
||||
...options,
|
||||
});
|
||||
} else {
|
||||
error({ code: 'NOT_SUPPORTED' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PeerGeoLocation
|
||||
* Handles all peer-to-peer geolocation request/response logic.
|
||||
* @class
|
||||
*/
|
||||
class PeerGeoLocation {
|
||||
/**
|
||||
* @param {Object} options
|
||||
* @param {string} options.room_id - Room identifier.
|
||||
* @param {string} options.peer_name - Local peer name.
|
||||
* @param {string} options.peer_id - Local peer ID.
|
||||
* @param {string} options.peer_uuid - Local peer UUID.
|
||||
* @param {Function} options.sendToServer - Function to send data to the server.
|
||||
* @param {Function} options.msgPopup - Function to show message popups.
|
||||
* @param {NotificationService} options.notificationService - Notification service instance.
|
||||
* @param {GeoService} options.geoService - Geolocation service instance.
|
||||
* @param {Function} options.openURL - Function to open URLs.
|
||||
*/
|
||||
constructor({
|
||||
room_id,
|
||||
peer_name,
|
||||
peer_id,
|
||||
peer_uuid,
|
||||
sendToServer,
|
||||
msgPopup,
|
||||
notificationService,
|
||||
geoService,
|
||||
openURL,
|
||||
}) {
|
||||
this.room_id = room_id;
|
||||
this.peer_name = peer_name;
|
||||
this.peer_id = peer_id;
|
||||
this.peer_uuid = peer_uuid;
|
||||
this.sendToServer = sendToServer;
|
||||
this.msgPopup = msgPopup;
|
||||
this.notificationService = notificationService;
|
||||
this.geoService = geoService;
|
||||
this.openURL = openURL;
|
||||
this._geoResponded = {}; // Guard for each request
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique request key for each geo request.
|
||||
* @param {string} requester_peer_id
|
||||
* @returns {string}
|
||||
*/
|
||||
_makeRequestKey(requester_peer_id) {
|
||||
// You can use timestamp or a random string for uniqueness
|
||||
return `${requester_peer_id}:${Date.now()}:${Math.random().toString(36).substr(2, 6)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a progress popup for peer actions.
|
||||
* @param {string} title
|
||||
* @param {string} message
|
||||
* @param {number} timeout
|
||||
* @param {string} [action='na']
|
||||
*/
|
||||
peerActionProgress(title, message, timeout, action = 'na') {
|
||||
const icon = action === 'eject' ? 'warning' : 'success';
|
||||
this.notificationService.showProgress(title, message, timeout, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a geolocation request to a peer.
|
||||
* @param {string} to_peer_id - The peer to request location from.
|
||||
*/
|
||||
askPeerGeoLocation(to_peer_id) {
|
||||
this.sendToServer('cmd', {
|
||||
action: 'geoLocation',
|
||||
send_to_all: false,
|
||||
data: {
|
||||
room_id: this.room_id,
|
||||
peer_name: this.peer_name,
|
||||
peer_id: this.peer_id,
|
||||
peer_uuid: this.peer_uuid,
|
||||
to_peer_id: to_peer_id,
|
||||
request_id: this._makeRequestKey(this.peer_id), // Add unique request id
|
||||
},
|
||||
});
|
||||
this.peerActionProgress(
|
||||
'Geolocation',
|
||||
'Geolocation requested. Please wait for confirmation...',
|
||||
6000,
|
||||
'geolocation'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a geolocation response (OK or KO) to the requester.
|
||||
* @param {string} requester_peer_id - The peer who requested location.
|
||||
* @param {string} action - 'geoLocationOK' or 'geoLocationKO'.
|
||||
* @param {Object|null} geoLocation - Geolocation data or null.
|
||||
* @param {string|boolean} [error=false] - Error message or false.
|
||||
* @param {string} [request_id] - Unique request id.
|
||||
*/
|
||||
sendPeerGeoLocation(requester_peer_id, action, geoLocation = null, error = false, request_id = null) {
|
||||
this.sendToServer('cmd', {
|
||||
action: action,
|
||||
send_to_all: false,
|
||||
data: {
|
||||
room_id: this.room_id,
|
||||
peer_name: this.peer_name,
|
||||
peer_id: this.peer_id,
|
||||
peer_uuid: this.peer_uuid,
|
||||
to_peer_id: requester_peer_id,
|
||||
geoLocation,
|
||||
request_id,
|
||||
},
|
||||
error,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt the user to confirm sharing their location.
|
||||
* @param {Object} data - Data from the geoLocation request.
|
||||
*/
|
||||
confirmPeerGeoLocation(data) {
|
||||
const request_id = data.request_id || this._makeRequestKey(data.peer_id);
|
||||
if (this._geoResponded[request_id]) return;
|
||||
this._geoResponded[request_id] = false;
|
||||
this.notificationService.showConfirmLocation(data.peer_name).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
this.getPeerGeoLocation(data.peer_id, request_id);
|
||||
} else {
|
||||
this.denyPeerGeoLocation(data.peer_id, request_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the user's geolocation and send the result.
|
||||
* @param {string} requester_peer_id - The peer who requested location.
|
||||
* @param {string} request_id - Unique request id.
|
||||
*/
|
||||
getPeerGeoLocation(requester_peer_id, request_id) {
|
||||
this.geoService.getCurrentPosition(
|
||||
(position) => this.handleGeoLocationSuccess(requester_peer_id, position, request_id),
|
||||
(error) => this.handleGeoLocationError(requester_peer_id, error, request_id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle successful geolocation retrieval.
|
||||
* @param {string} requester_peer_id
|
||||
* @param {Object} position
|
||||
* @param {string} request_id
|
||||
*/
|
||||
handleGeoLocationSuccess(requester_peer_id, position, request_id) {
|
||||
if (this._geoResponded[request_id]) return;
|
||||
this._geoResponded[request_id] = true;
|
||||
setTimeout(() => {
|
||||
delete this._geoResponded[request_id];
|
||||
}, 60000); // Cleanup after 1 min
|
||||
const geoLocation = {
|
||||
latitude: position.coords.latitude,
|
||||
longitude: position.coords.longitude,
|
||||
};
|
||||
this.sendPeerGeoLocation(requester_peer_id, 'geoLocationOK', geoLocation, false, request_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle geolocation errors.
|
||||
* @param {string} requester_peer_id
|
||||
* @param {Object} error
|
||||
* @param {string} request_id
|
||||
*/
|
||||
handleGeoLocationError(requester_peer_id, error, request_id) {
|
||||
console.error('GeoLocation Error:', error);
|
||||
if (this._geoResponded[request_id]) return;
|
||||
this._geoResponded[request_id] = true;
|
||||
setTimeout(() => {
|
||||
delete this._geoResponded[request_id];
|
||||
}, 60000); // Cleanup after 1 min
|
||||
let geoError;
|
||||
switch (error.code) {
|
||||
case error.PERMISSION_DENIED:
|
||||
geoError = 'User denied the request for Geolocation';
|
||||
break;
|
||||
case error.POSITION_UNAVAILABLE:
|
||||
geoError = 'Location information is unavailable';
|
||||
break;
|
||||
case error.TIMEOUT:
|
||||
geoError = 'The request to get user location timed out';
|
||||
break;
|
||||
case error.UNKNOWN_ERROR:
|
||||
geoError = 'An unknown error occurred';
|
||||
break;
|
||||
case 'NOT_SUPPORTED':
|
||||
geoError = 'Geolocation is not supported by this browser';
|
||||
break;
|
||||
default:
|
||||
geoError = 'Geolocation error';
|
||||
break;
|
||||
}
|
||||
this.sendPeerGeoLocation(requester_peer_id, 'geoLocationKO', null, geoError, request_id);
|
||||
this.msgPopup('warning', geoError, 'top-end', 5000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a denial response for geolocation sharing.
|
||||
* @param {string} requester_peer_id
|
||||
* @param {string} request_id
|
||||
*/
|
||||
denyPeerGeoLocation(requester_peer_id, request_id) {
|
||||
if (this._geoResponded[request_id]) return;
|
||||
this._geoResponded[request_id] = true;
|
||||
setTimeout(() => {
|
||||
delete this._geoResponded[request_id];
|
||||
}, 60000); // Cleanup after 1 min
|
||||
this.sendPeerGeoLocation(
|
||||
requester_peer_id,
|
||||
'geoLocationKO',
|
||||
null,
|
||||
`${this.peer_name}: Has declined permission for geolocation`,
|
||||
request_id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle receiving a peer's geolocation response.
|
||||
* @param {Object} config - The command config received from the server.
|
||||
*/
|
||||
handleGeoPeerLocation(config) {
|
||||
if (config.error) {
|
||||
this.msgPopup('warning', config.error, 'top-end', 5000);
|
||||
return;
|
||||
}
|
||||
if (!config.data || !config.data.geoLocation) {
|
||||
this.msgPopup('warning', 'Geolocation data is not available', 'top-end', 5000);
|
||||
return;
|
||||
}
|
||||
const geoLocation = config.data.geoLocation;
|
||||
this.notificationService.showOpenLocation(config.data.peer_name).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
this.openURL(
|
||||
`https://www.google.com/maps/search/?api=1&query=${geoLocation.latitude},${geoLocation.longitude}`,
|
||||
true
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1173,6 +1173,7 @@ access to use this app.
|
||||
<script defer src="../js/common.js"></script>
|
||||
<script defer src="../js/brand.js"></script>
|
||||
<script defer src="../js/buttons.js"></script>
|
||||
<script defer src="../js/geoLocation.js"></script>
|
||||
<script defer src="../js/client.js"></script>
|
||||
<script defer src="../js/detectSpeaking.js"></script>
|
||||
<script defer src="../js/speechRecognition.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user