Dhurgh commited on
Commit
02c81f5
Β·
1 Parent(s): 8c6f70f

Simplify call flow: use live call window with in-app status and event logs (v2.8.4)

Browse files
Files changed (3) hide show
  1. client.js +62 -27
  2. index.html +16 -2
  3. package.json +1 -1
client.js CHANGED
@@ -33,6 +33,7 @@ let forceRelayOnly = false;
33
  let pendingIceRecoveryTimer = null;
34
  let pendingRelayFallbackTimer = null;
35
  let pendingRemoteIceCandidates = [];
 
36
  let hasUserInteractedWithPage = false;
37
  let activeRoomSubscription = null;
38
  let roomMessages = JSON.parse(localStorage.getItem('roomMessages') || '{}');
@@ -366,6 +367,22 @@ function ensureLocalPreviewPlayback(videoEl) {
366
  setTimeout(tryPlay, 500);
367
  }
368
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  let callControlBindingsDone = false;
370
  function bindCallControlButtons() {
371
  if (callControlBindingsDone) return;
@@ -6111,34 +6128,24 @@ function openVideoCallModal(targetName, targetId, callType) {
6111
  targetName = targetName || currentChatContext.name || 'User';
6112
  targetId = targetId || currentChatContext.id;
6113
  callType = callType || 'Video Call';
6114
-
6115
- const html = `
6116
- <div style="text-align: center; padding: 20px;">
6117
- <div style="width: 120px; height: 120px; background: linear-gradient(135deg, #667eea, #764ba2); border-radius: 50%; margin: 0 auto 20px; display: flex; align-items: center; justify-content: center; font-size: 60px; animation: pulse 2s infinite;">
6118
- πŸ“ž
6119
- </div>
6120
- <h3 style="margin: 15px 0; color: var(--text-primary); font-size: 24px;">${callType}</h3>
6121
- <p style="margin: 10px 0; color: var(--text-secondary); font-size: 16px;">Calling <strong style="color: var(--primary-color);">${targetName}</strong></p>
6122
- <p style="margin: 20px 0; color: var(--text-secondary); font-size: 14px; font-style: italic;">πŸ”Š Ringing...</p>
6123
- <div style="margin-top: 30px; padding: 15px; background: rgba(88, 101, 242, 0.1); border-radius: 8px; border: 1px solid var(--primary-color);">
6124
- <p style="color: var(--text-secondary); font-size: 13px; margin: 0;">πŸ’‘ <strong>Video Call Ready!</strong></p>
6125
- <p style="color: var(--text-secondary); font-size: 12px; margin: 8px 0 0 0;">Waiting for the other user to accept...</p>
6126
- </div>
6127
- <button onclick="endVideoCall();" style="margin-top: 20px; padding: 12px 30px; background: var(--danger); color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: 600; font-size: 14px;">
6128
- ❌ Cancel Call
6129
- </button>
6130
- </div>
6131
- <style>
6132
- @keyframes pulse {
6133
- 0%, 100% { transform: scale(1); }
6134
- 50% { transform: scale(1.05); }
6135
  }
6136
- </style>
6137
- `;
6138
-
6139
- customAlert(html, 'πŸ“ž Video Call', 'πŸ“ž');
6140
-
6141
-
6142
  if (socket && socket.connected && targetId) {
6143
  socket.emit('start video call', {
6144
  targetId: targetId,
@@ -6147,6 +6154,7 @@ function openVideoCallModal(targetName, targetId, callType) {
6147
  });
6148
  activeCallState = { callId: null, peerId: targetId, direction: 'outgoing' };
6149
  showToast(`πŸ“ž Calling ${targetName}...`, 'success');
 
6150
  }
6151
  }
6152
 
@@ -6170,6 +6178,7 @@ function handleIncomingVideoCall(payload) {
6170
 
6171
  if (accepted) {
6172
  stopIncomingCallAlert();
 
6173
  socket.emit('accept video call', {
6174
  callId: activeCallState.callId,
6175
  toId: activeCallState.peerId
@@ -6325,6 +6334,7 @@ function createPeerConnection(peerId) {
6325
  if (event.track && remoteCallStream) {
6326
  if (!remoteCallStream.getTrackById(event.track.id)) {
6327
  remoteCallStream.addTrack(event.track);
 
6328
  }
6329
  }
6330
  const remoteVideo = document.getElementById('remoteCallVideo');
@@ -6353,9 +6363,12 @@ function createPeerConnection(peerId) {
6353
  return;
6354
  }
6355
  if (peerConnection.connectionState === 'connecting') {
 
6356
  showToast('πŸ“ž Connecting call...', 'info');
6357
  } else if (peerConnection.connectionState === 'connected') {
6358
  callIceFailureCount = 0;
 
 
6359
  showToast('πŸ“ž Call connected!', 'success');
6360
  // Start timer only if not already running (avoids resetting a running clock)
6361
  if (!callTimerInterval) {
@@ -6374,6 +6387,8 @@ function createPeerConnection(peerId) {
6374
  }
6375
  }
6376
  } else if (peerConnection.connectionState === 'failed') {
 
 
6377
  showCallWarningThrottled('⚠️ Network issue detected, retrying call connection...');
6378
  attemptIceRecovery(peerId);
6379
  } else if (peerConnection.connectionState === 'closed') {
@@ -6385,6 +6400,7 @@ function createPeerConnection(peerId) {
6385
  peerConnection.oniceconnectionstatechange = () => {
6386
  if (!peerConnection) return;
6387
  console.log('ICE connection state:', peerConnection.iceConnectionState);
 
6388
 
6389
  if (peerConnection.iceConnectionState === 'connected' || peerConnection.iceConnectionState === 'completed') {
6390
  callIceFailureCount = 0;
@@ -6412,6 +6428,7 @@ function createPeerConnection(peerId) {
6412
  iceTransportPolicy: 'all'
6413
  });
6414
  showToast('Retrying call with mixed network mode...', 'warning');
 
6415
  attemptIceRecovery(peerId);
6416
  } catch (fallbackError) {
6417
  console.warn('Relay fallback failed:', fallbackError);
@@ -6460,8 +6477,10 @@ function createPeerConnection(peerId) {
6460
  iceTransportPolicy: 'relay'
6461
  });
6462
  showToast('Switching call to relay mode for network compatibility...', 'warning');
 
6463
  } else if (callIceFailureCount >= 2 && !hasTurnServersConfigured) {
6464
  showToast('Retrying call without relay fallback...', 'warning');
 
6465
  }
6466
 
6467
  peerConnection.restartIce?.();
@@ -6473,6 +6492,7 @@ function createPeerConnection(peerId) {
6473
  offerToReceiveVideo: true
6474
  });
6475
  await peerConnection.setLocalDescription(recoveryOffer);
 
6476
 
6477
  socket.emit('video signal', {
6478
  toId: recoveryPeerId,
@@ -6491,14 +6511,19 @@ function openCallDialog(peerName) {
6491
  const overlay = document.getElementById('callOverlay');
6492
  if (overlay) {
6493
  overlay.classList.toggle('desktop-window', window.innerWidth > 700);
 
6494
  document.getElementById('callOverlayPeerName').textContent = `πŸ“ž ${peerName}`;
6495
  document.getElementById('callTimerLabel').textContent = '00:00:00';
 
6496
  const muteBtn = document.getElementById('muteBtn');
6497
  if (muteBtn) { muteBtn.textContent = '🎀'; muteBtn.classList.remove('muted'); }
6498
  const camBtn = document.getElementById('cameraBtn');
6499
  if (camBtn) { camBtn.textContent = 'πŸ“·'; camBtn.classList.remove('cam-off'); }
6500
  isCallCameraOff = false;
6501
  overlay.classList.add('active');
 
 
 
6502
  }
6503
  }
6504
 
@@ -6515,6 +6540,7 @@ async function startCallSession(peerName, peerId, isCaller) {
6515
  callIceFailureCount = 0;
6516
  await ensureRtcConfigLoaded();
6517
  forceRelayOnly = rtcRuntimeConfig?.iceTransportPolicy === 'relay';
 
6518
 
6519
  openCallDialog(peerName);
6520
  // Start timer from session start to avoid "stuck at 00:00" perception on unstable networks.
@@ -6527,6 +6553,7 @@ async function startCallSession(peerName, peerId, isCaller) {
6527
  // Do not abort the call - continue in receive-only mode so user can still hear/see remote party.
6528
  console.warn('Local media unavailable, continuing receive-only call:', mediaError);
6529
  localCallStream = null;
 
6530
  showToast('Starting call in receive-only mode (local camera/mic unavailable)', 'warning');
6531
  }
6532
 
@@ -6539,6 +6566,7 @@ async function startCallSession(peerName, peerId, isCaller) {
6539
  }
6540
 
6541
  createPeerConnection(peerId);
 
6542
 
6543
  if (isCaller && peerConnection) {
6544
  makingOffer = true;
@@ -6548,6 +6576,7 @@ async function startCallSession(peerName, peerId, isCaller) {
6548
  offerToReceiveVideo: true
6549
  });
6550
  await peerConnection.setLocalDescription(offer);
 
6551
  socket.emit('video signal', {
6552
  toId: peerId,
6553
  callId: activeCallState?.callId,
@@ -6564,9 +6593,11 @@ async function startCallSession(peerName, peerId, isCaller) {
6564
  pendingSignalOffer = null;
6565
  try {
6566
  await peerConnection.setRemoteDescription(new RTCSessionDescription(po.offer));
 
6567
  await flushQueuedIceCandidates();
6568
  const answer = await peerConnection.createAnswer();
6569
  await peerConnection.setLocalDescription(answer);
 
6570
  socket.emit('video signal', {
6571
  toId: po.fromId,
6572
  callId: activeCallState?.callId,
@@ -6676,6 +6707,8 @@ function refreshCallDebug() {
6676
  <div class="dbg-row">πŸ“Ί Remote Video: ${vidState}</div>
6677
  <div class="dbg-row">πŸ”Œ Socket: ${socketStr}</div>
6678
  <div class="dbg-row">⏱ Call duration: ${document.getElementById('callTimerLabel')?.textContent || 'n/a'}</div>
 
 
6679
  <div style="margin-top:8px;">
6680
  <button onclick="forceRestartIce()" style="background:#00ff88;color:#000;border:none;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:10px;font-weight:700;">πŸ”„ Restart ICE</button>
6681
  <button onclick="refreshCallDebug()" style="background:rgba(255,255,255,0.2);color:#fff;border:none;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:10px;margin-left:4px;">↻ Refresh</button>
@@ -6740,6 +6773,8 @@ function cleanupCallSession(keepDialogOpen = false) {
6740
  currentCallPeerId = null;
6741
  currentCallPeerName = null;
6742
  activeCallState = null;
 
 
6743
 
6744
  // Close the overlay
6745
  const overlay = document.getElementById('callOverlay');
 
33
  let pendingIceRecoveryTimer = null;
34
  let pendingRelayFallbackTimer = null;
35
  let pendingRemoteIceCandidates = [];
36
+ let callEventLog = [];
37
  let hasUserInteractedWithPage = false;
38
  let activeRoomSubscription = null;
39
  let roomMessages = JSON.parse(localStorage.getItem('roomMessages') || '{}');
 
367
  setTimeout(tryPlay, 500);
368
  }
369
 
370
+ function appendCallLog(message) {
371
+ const entry = `[${new Date().toLocaleTimeString()}] ${message}`;
372
+ callEventLog.push(entry);
373
+ if (callEventLog.length > 20) {
374
+ callEventLog = callEventLog.slice(-20);
375
+ }
376
+ refreshCallDebug();
377
+ }
378
+
379
+ function setCallStatus(statusText) {
380
+ const statusLabel = document.getElementById('callStatusLabel');
381
+ if (statusLabel) {
382
+ statusLabel.textContent = statusText || '';
383
+ }
384
+ }
385
+
386
  let callControlBindingsDone = false;
387
  function bindCallControlButtons() {
388
  if (callControlBindingsDone) return;
 
6128
  targetName = targetName || currentChatContext.name || 'User';
6129
  targetId = targetId || currentChatContext.id;
6130
  callType = callType || 'Video Call';
6131
+ openCallDialog(targetName);
6132
+ setCallStatus('Dialing...');
6133
+ appendCallLog(`Outgoing ${callType.toLowerCase()} to ${targetName}`);
6134
+
6135
+ ensureRtcConfigLoaded()
6136
+ .then(() => ensureLocalCallStream())
6137
+ .then(() => {
6138
+ const localVideo = document.getElementById('localCallVideo');
6139
+ if (localVideo && localCallStream) {
6140
+ localVideo.srcObject = localCallStream;
6141
+ ensureLocalPreviewPlayback(localVideo);
6142
+ appendCallLog('Local preview started before answer');
 
 
 
 
 
 
 
 
 
6143
  }
6144
+ })
6145
+ .catch((error) => {
6146
+ appendCallLog(`Local preview unavailable: ${error?.message || error}`);
6147
+ });
6148
+
 
6149
  if (socket && socket.connected && targetId) {
6150
  socket.emit('start video call', {
6151
  targetId: targetId,
 
6154
  });
6155
  activeCallState = { callId: null, peerId: targetId, direction: 'outgoing' };
6156
  showToast(`πŸ“ž Calling ${targetName}...`, 'success');
6157
+ appendCallLog('Call request emitted to signaling server');
6158
  }
6159
  }
6160
 
 
6178
 
6179
  if (accepted) {
6180
  stopIncomingCallAlert();
6181
+ appendCallLog(`Accepted incoming call from ${callerName}`);
6182
  socket.emit('accept video call', {
6183
  callId: activeCallState.callId,
6184
  toId: activeCallState.peerId
 
6334
  if (event.track && remoteCallStream) {
6335
  if (!remoteCallStream.getTrackById(event.track.id)) {
6336
  remoteCallStream.addTrack(event.track);
6337
+ appendCallLog(`Remote ${event.track.kind} track received`);
6338
  }
6339
  }
6340
  const remoteVideo = document.getElementById('remoteCallVideo');
 
6363
  return;
6364
  }
6365
  if (peerConnection.connectionState === 'connecting') {
6366
+ setCallStatus('Connecting...');
6367
  showToast('πŸ“ž Connecting call...', 'info');
6368
  } else if (peerConnection.connectionState === 'connected') {
6369
  callIceFailureCount = 0;
6370
+ setCallStatus('Connected');
6371
+ appendCallLog('Peer connection connected');
6372
  showToast('πŸ“ž Call connected!', 'success');
6373
  // Start timer only if not already running (avoids resetting a running clock)
6374
  if (!callTimerInterval) {
 
6387
  }
6388
  }
6389
  } else if (peerConnection.connectionState === 'failed') {
6390
+ setCallStatus('Connection failed');
6391
+ appendCallLog('Peer connection failed, starting recovery');
6392
  showCallWarningThrottled('⚠️ Network issue detected, retrying call connection...');
6393
  attemptIceRecovery(peerId);
6394
  } else if (peerConnection.connectionState === 'closed') {
 
6400
  peerConnection.oniceconnectionstatechange = () => {
6401
  if (!peerConnection) return;
6402
  console.log('ICE connection state:', peerConnection.iceConnectionState);
6403
+ appendCallLog(`ICE state: ${peerConnection.iceConnectionState}`);
6404
 
6405
  if (peerConnection.iceConnectionState === 'connected' || peerConnection.iceConnectionState === 'completed') {
6406
  callIceFailureCount = 0;
 
6428
  iceTransportPolicy: 'all'
6429
  });
6430
  showToast('Retrying call with mixed network mode...', 'warning');
6431
+ appendCallLog('Fallback from relay-only to mixed mode');
6432
  attemptIceRecovery(peerId);
6433
  } catch (fallbackError) {
6434
  console.warn('Relay fallback failed:', fallbackError);
 
6477
  iceTransportPolicy: 'relay'
6478
  });
6479
  showToast('Switching call to relay mode for network compatibility...', 'warning');
6480
+ appendCallLog('Switching to relay mode for recovery');
6481
  } else if (callIceFailureCount >= 2 && !hasTurnServersConfigured) {
6482
  showToast('Retrying call without relay fallback...', 'warning');
6483
+ appendCallLog('No TURN available, retrying direct ICE only');
6484
  }
6485
 
6486
  peerConnection.restartIce?.();
 
6492
  offerToReceiveVideo: true
6493
  });
6494
  await peerConnection.setLocalDescription(recoveryOffer);
6495
+ appendCallLog('ICE restart offer created and sent');
6496
 
6497
  socket.emit('video signal', {
6498
  toId: recoveryPeerId,
 
6511
  const overlay = document.getElementById('callOverlay');
6512
  if (overlay) {
6513
  overlay.classList.toggle('desktop-window', window.innerWidth > 700);
6514
+ callEventLog = [];
6515
  document.getElementById('callOverlayPeerName').textContent = `πŸ“ž ${peerName}`;
6516
  document.getElementById('callTimerLabel').textContent = '00:00:00';
6517
+ setCallStatus('Preparing call...');
6518
  const muteBtn = document.getElementById('muteBtn');
6519
  if (muteBtn) { muteBtn.textContent = '🎀'; muteBtn.classList.remove('muted'); }
6520
  const camBtn = document.getElementById('cameraBtn');
6521
  if (camBtn) { camBtn.textContent = 'πŸ“·'; camBtn.classList.remove('cam-off'); }
6522
  isCallCameraOff = false;
6523
  overlay.classList.add('active');
6524
+ const dbg = document.getElementById('callDebugPanel');
6525
+ if (dbg) dbg.style.display = 'block';
6526
+ appendCallLog(`Call window opened for ${peerName}`);
6527
  }
6528
  }
6529
 
 
6540
  callIceFailureCount = 0;
6541
  await ensureRtcConfigLoaded();
6542
  forceRelayOnly = rtcRuntimeConfig?.iceTransportPolicy === 'relay';
6543
+ appendCallLog(`Starting session as ${isCaller ? 'caller' : 'callee'}`);
6544
 
6545
  openCallDialog(peerName);
6546
  // Start timer from session start to avoid "stuck at 00:00" perception on unstable networks.
 
6553
  // Do not abort the call - continue in receive-only mode so user can still hear/see remote party.
6554
  console.warn('Local media unavailable, continuing receive-only call:', mediaError);
6555
  localCallStream = null;
6556
+ appendCallLog(`Local media unavailable: ${mediaError?.message || mediaError}`);
6557
  showToast('Starting call in receive-only mode (local camera/mic unavailable)', 'warning');
6558
  }
6559
 
 
6566
  }
6567
 
6568
  createPeerConnection(peerId);
6569
+ appendCallLog('Peer connection created');
6570
 
6571
  if (isCaller && peerConnection) {
6572
  makingOffer = true;
 
6576
  offerToReceiveVideo: true
6577
  });
6578
  await peerConnection.setLocalDescription(offer);
6579
+ appendCallLog('Offer created and sent');
6580
  socket.emit('video signal', {
6581
  toId: peerId,
6582
  callId: activeCallState?.callId,
 
6593
  pendingSignalOffer = null;
6594
  try {
6595
  await peerConnection.setRemoteDescription(new RTCSessionDescription(po.offer));
6596
+ appendCallLog('Pending remote offer applied');
6597
  await flushQueuedIceCandidates();
6598
  const answer = await peerConnection.createAnswer();
6599
  await peerConnection.setLocalDescription(answer);
6600
+ appendCallLog('Answer created for pending offer');
6601
  socket.emit('video signal', {
6602
  toId: po.fromId,
6603
  callId: activeCallState?.callId,
 
6707
  <div class="dbg-row">πŸ“Ί Remote Video: ${vidState}</div>
6708
  <div class="dbg-row">πŸ”Œ Socket: ${socketStr}</div>
6709
  <div class="dbg-row">⏱ Call duration: ${document.getElementById('callTimerLabel')?.textContent || 'n/a'}</div>
6710
+ <div class="dbg-row">πŸ“‹ Status: ${document.getElementById('callStatusLabel')?.textContent || 'n/a'}</div>
6711
+ <div class="dbg-log">${callEventLog.map((entry) => `<div>${entry}</div>`).join('')}</div>
6712
  <div style="margin-top:8px;">
6713
  <button onclick="forceRestartIce()" style="background:#00ff88;color:#000;border:none;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:10px;font-weight:700;">πŸ”„ Restart ICE</button>
6714
  <button onclick="refreshCallDebug()" style="background:rgba(255,255,255,0.2);color:#fff;border:none;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:10px;margin-left:4px;">↻ Refresh</button>
 
6773
  currentCallPeerId = null;
6774
  currentCallPeerName = null;
6775
  activeCallState = null;
6776
+ callEventLog = [];
6777
+ setCallStatus('');
6778
 
6779
  // Close the overlay
6780
  const overlay = document.getElementById('callOverlay');
index.html CHANGED
@@ -1055,6 +1055,19 @@
1055
  display: none;
1056
  }
1057
  #callDebugPanel .dbg-row { margin-bottom: 4px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
1058
 
1059
  /* ==================== NOTIFICATION PANEL ==================== */
1060
  .notif-bell-btn {
@@ -3098,7 +3111,7 @@
3098
  <div class="chat-header-title" id="chatTitle">πŸ’¬ Select a friend to chat</div>
3099
  </div>
3100
  <div class="chat-header-actions">
3101
- <span class="build-badge mobile-essential" id="buildVersionBadge" title="Frontend build version">v2.8.3</span>
3102
  <button class="header-btn mobile-essential" onclick="toggleArchiveChat()" title="Archive chat">
3103
  <i class="fas fa-archive"></i>
3104
  </button>
@@ -3687,6 +3700,7 @@
3687
  <div>
3688
  <div id="callOverlayPeerName" style="color:#fff; font-size:18px; font-weight:700;"></div>
3689
  <div id="callTimerLabel" style="color:rgba(255,255,255,0.7); font-size:13px; margin-top:4px;">00:00:00</div>
 
3690
  </div>
3691
  <button id="callDebugBtn" style="background:rgba(255,255,255,0.18); border:none; color:white; padding:7px 13px; border-radius:8px; cursor:pointer; font-size:12px; font-weight:600;">πŸ”§ Debug</button>
3692
  </div>
@@ -3717,7 +3731,7 @@
3717
 
3718
  <script src="/socket.io/socket.io.js"></script>
3719
  <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
3720
- <script src="client.js?v=2.8.3"></script>
3721
  </body>
3722
  </html>
3723
 
 
1055
  display: none;
1056
  }
1057
  #callDebugPanel .dbg-row { margin-bottom: 4px; }
1058
+ #callDebugPanel .dbg-log {
1059
+ margin-top: 8px;
1060
+ max-height: 180px;
1061
+ overflow-y: auto;
1062
+ border-top: 1px solid rgba(0,255,136,0.35);
1063
+ padding-top: 8px;
1064
+ color: #c7ffd9;
1065
+ }
1066
+ #callDebugPanel .dbg-log div {
1067
+ margin-bottom: 4px;
1068
+ line-height: 1.35;
1069
+ word-break: break-word;
1070
+ }
1071
 
1072
  /* ==================== NOTIFICATION PANEL ==================== */
1073
  .notif-bell-btn {
 
3111
  <div class="chat-header-title" id="chatTitle">πŸ’¬ Select a friend to chat</div>
3112
  </div>
3113
  <div class="chat-header-actions">
3114
+ <span class="build-badge mobile-essential" id="buildVersionBadge" title="Frontend build version">v2.8.4</span>
3115
  <button class="header-btn mobile-essential" onclick="toggleArchiveChat()" title="Archive chat">
3116
  <i class="fas fa-archive"></i>
3117
  </button>
 
3700
  <div>
3701
  <div id="callOverlayPeerName" style="color:#fff; font-size:18px; font-weight:700;"></div>
3702
  <div id="callTimerLabel" style="color:rgba(255,255,255,0.7); font-size:13px; margin-top:4px;">00:00:00</div>
3703
+ <div id="callStatusLabel" style="color:#8fffc2; font-size:12px; margin-top:4px;">Preparing call...</div>
3704
  </div>
3705
  <button id="callDebugBtn" style="background:rgba(255,255,255,0.18); border:none; color:white; padding:7px 13px; border-radius:8px; cursor:pointer; font-size:12px; font-weight:600;">πŸ”§ Debug</button>
3706
  </div>
 
3731
 
3732
  <script src="/socket.io/socket.io.js"></script>
3733
  <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
3734
+ <script src="client.js?v=2.8.4"></script>
3735
  </body>
3736
  </html>
3737
 
package.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "name": "discord-like-app",
3
- "version": "2.8.3",
4
  "main": "server.js",
5
  "scripts": {
6
  "dev": "nodemon server.js",
 
1
  {
2
  "name": "discord-like-app",
3
+ "version": "2.8.4",
4
  "main": "server.js",
5
  "scripts": {
6
  "dev": "nodemon server.js",