Spaces:
Runtime error
Runtime error
Allow receive-only calls when camera/mic access fails (v2.7.0)
Browse files- client.js +24 -2
- index.html +2 -2
- package.json +1 -1
client.js
CHANGED
|
@@ -6209,13 +6209,26 @@ function createPeerConnection(peerId) {
|
|
| 6209 |
remoteVideo.volume = 1.0;
|
| 6210 |
}
|
| 6211 |
|
|
|
|
|
|
|
|
|
|
| 6212 |
if (localCallStream) {
|
| 6213 |
localCallStream.getTracks().forEach((track) => {
|
| 6214 |
track.enabled = true;
|
| 6215 |
peerConnection.addTrack(track, localCallStream);
|
|
|
|
|
|
|
| 6216 |
});
|
| 6217 |
}
|
| 6218 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6219 |
peerConnection.onicecandidate = (event) => {
|
| 6220 |
if (event.candidate && socket && socket.connected) {
|
| 6221 |
socket.emit('video signal', {
|
|
@@ -6423,12 +6436,21 @@ async function startCallSession(peerName, peerId, isCaller) {
|
|
| 6423 |
|
| 6424 |
openCallDialog(peerName);
|
| 6425 |
await ensureRtcConfigLoaded();
|
| 6426 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6427 |
|
| 6428 |
const localVideo = document.getElementById('localCallVideo');
|
| 6429 |
-
if (localVideo) {
|
| 6430 |
localVideo.srcObject = localCallStream;
|
| 6431 |
localVideo.play().catch(() => {});
|
|
|
|
|
|
|
| 6432 |
}
|
| 6433 |
|
| 6434 |
createPeerConnection(peerId);
|
|
|
|
| 6209 |
remoteVideo.volume = 1.0;
|
| 6210 |
}
|
| 6211 |
|
| 6212 |
+
let hasLocalAudio = false;
|
| 6213 |
+
let hasLocalVideo = false;
|
| 6214 |
+
|
| 6215 |
if (localCallStream) {
|
| 6216 |
localCallStream.getTracks().forEach((track) => {
|
| 6217 |
track.enabled = true;
|
| 6218 |
peerConnection.addTrack(track, localCallStream);
|
| 6219 |
+
if (track.kind === 'audio') hasLocalAudio = true;
|
| 6220 |
+
if (track.kind === 'video') hasLocalVideo = true;
|
| 6221 |
});
|
| 6222 |
}
|
| 6223 |
|
| 6224 |
+
// Keep remote receiving path alive even when local media permissions fail.
|
| 6225 |
+
if (!hasLocalAudio) {
|
| 6226 |
+
peerConnection.addTransceiver('audio', { direction: 'recvonly' });
|
| 6227 |
+
}
|
| 6228 |
+
if (!hasLocalVideo) {
|
| 6229 |
+
peerConnection.addTransceiver('video', { direction: 'recvonly' });
|
| 6230 |
+
}
|
| 6231 |
+
|
| 6232 |
peerConnection.onicecandidate = (event) => {
|
| 6233 |
if (event.candidate && socket && socket.connected) {
|
| 6234 |
socket.emit('video signal', {
|
|
|
|
| 6436 |
|
| 6437 |
openCallDialog(peerName);
|
| 6438 |
await ensureRtcConfigLoaded();
|
| 6439 |
+
try {
|
| 6440 |
+
await ensureLocalCallStream();
|
| 6441 |
+
} catch (mediaError) {
|
| 6442 |
+
// Do not abort the call - continue in receive-only mode so user can still hear/see remote party.
|
| 6443 |
+
console.warn('Local media unavailable, continuing receive-only call:', mediaError);
|
| 6444 |
+
localCallStream = null;
|
| 6445 |
+
showToast('Starting call in receive-only mode (local camera/mic unavailable)', 'warning');
|
| 6446 |
+
}
|
| 6447 |
|
| 6448 |
const localVideo = document.getElementById('localCallVideo');
|
| 6449 |
+
if (localVideo && localCallStream) {
|
| 6450 |
localVideo.srcObject = localCallStream;
|
| 6451 |
localVideo.play().catch(() => {});
|
| 6452 |
+
} else if (localVideo) {
|
| 6453 |
+
localVideo.srcObject = null;
|
| 6454 |
}
|
| 6455 |
|
| 6456 |
createPeerConnection(peerId);
|
index.html
CHANGED
|
@@ -3048,7 +3048,7 @@
|
|
| 3048 |
<div class="chat-header-title" id="chatTitle">💬 Select a friend to chat</div>
|
| 3049 |
</div>
|
| 3050 |
<div class="chat-header-actions">
|
| 3051 |
-
<span class="build-badge mobile-essential" id="buildVersionBadge" title="Frontend build version">v2.
|
| 3052 |
<button class="header-btn mobile-essential" onclick="toggleArchiveChat()" title="Archive chat">
|
| 3053 |
<i class="fas fa-archive"></i>
|
| 3054 |
</button>
|
|
@@ -3665,7 +3665,7 @@
|
|
| 3665 |
|
| 3666 |
<script src="/socket.io/socket.io.js"></script>
|
| 3667 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
|
| 3668 |
-
<script src="client.js?v=2.
|
| 3669 |
</body>
|
| 3670 |
</html>
|
| 3671 |
|
|
|
|
| 3048 |
<div class="chat-header-title" id="chatTitle">💬 Select a friend to chat</div>
|
| 3049 |
</div>
|
| 3050 |
<div class="chat-header-actions">
|
| 3051 |
+
<span class="build-badge mobile-essential" id="buildVersionBadge" title="Frontend build version">v2.7.0</span>
|
| 3052 |
<button class="header-btn mobile-essential" onclick="toggleArchiveChat()" title="Archive chat">
|
| 3053 |
<i class="fas fa-archive"></i>
|
| 3054 |
</button>
|
|
|
|
| 3665 |
|
| 3666 |
<script src="/socket.io/socket.io.js"></script>
|
| 3667 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
|
| 3668 |
+
<script src="client.js?v=2.7.0"></script>
|
| 3669 |
</body>
|
| 3670 |
</html>
|
| 3671 |
|
package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"name": "discord-like-app",
|
| 3 |
-
"version": "2.
|
| 4 |
"main": "server.js",
|
| 5 |
"scripts": {
|
| 6 |
"dev": "nodemon server.js",
|
|
|
|
| 1 |
{
|
| 2 |
"name": "discord-like-app",
|
| 3 |
+
"version": "2.7.0",
|
| 4 |
"main": "server.js",
|
| 5 |
"scripts": {
|
| 6 |
"dev": "nodemon server.js",
|