Dhurgh commited on
Commit
36b75a5
Β·
1 Parent(s): 7fed1b7

Fix user profile undefined errors, enhance mobile layout, improve video call modal, fix QR code display, refine hover effects

Browse files
Files changed (2) hide show
  1. client.js +115 -75
  2. index.html +19 -11
client.js CHANGED
@@ -1058,21 +1058,29 @@ function updateMembersList(users) {
1058
  avatar.style.backgroundSize = 'cover';
1059
  avatar.style.backgroundPosition = 'center';
1060
  } else {
1061
- avatar.textContent = user.username.charAt(0).toUpperCase();
1062
  }
1063
 
1064
  const status = document.createElement('div');
1065
  status.className = 'status-indicator';
1066
 
1067
  const name = document.createElement('span');
1068
- name.textContent = user.username;
 
 
 
 
1069
 
1070
  // Make item clickable to view profile
1071
  item.onclick = () => {
1072
- if (user.id === currentUser.id) {
 
 
 
 
1073
  openProfile();
1074
  } else {
1075
- visitUserProfile(user.id, user.username);
1076
  }
1077
  };
1078
 
@@ -2933,20 +2941,17 @@ function changeGroupPhoto() {
2933
  // ==================== VIDEO CALLS ====================
2934
 
2935
  function startVideoCall() {
2936
- if (currentChatContext.type === 'none') {
2937
- showToast('Open a chat or group first', 'warning');
2938
  return;
2939
  }
2940
 
2941
- const targetName = currentChatContext.name || 'Unknown';
2942
- const callType = currentChatContext.type === 'group' ? 'Group' : '1-on-1';
2943
-
2944
- showToast(`πŸ“ž Starting ${callType} video call with ${targetName}...`, 'success');
2945
 
2946
- // TODO: Implement WebRTC video call
2947
- setTimeout(() => {
2948
- openVideoCallModal();
2949
- }, 500);
2950
  }
2951
 
2952
  // ==================== ARCHIVE CHATS ====================
@@ -3239,7 +3244,7 @@ function resolveCustomDialog(value) {
3239
 
3240
  function showQRCodeModal() {
3241
  const modal = document.getElementById('qrModal');
3242
- const canvas = document.getElementById('qrCodeCanvas');
3243
  const userIdSpan = document.getElementById('qrUserId');
3244
 
3245
  if (!currentUser || !currentUser.id) {
@@ -3247,28 +3252,28 @@ function showQRCodeModal() {
3247
  return;
3248
  }
3249
 
3250
- // Clear previous QR code by removing old canvas
3251
- const qrContainer = canvas.parentElement;
3252
- const oldCanvas = qrContainer.querySelector('canvas');
3253
- if (oldCanvas) {
3254
- oldCanvas.remove();
3255
- }
3256
 
3257
- // Create new canvas
3258
- const newCanvas = document.createElement('canvas');
3259
- newCanvas.id = 'qrCodeCanvas';
3260
- qrContainer.appendChild(newCanvas);
 
 
 
 
3261
 
3262
  // Display user ID
3263
- userIdSpan.textContent = currentUser.id;
3264
 
3265
  // Generate QR code with friend request data
3266
- const friendRequestData = `FRIEND_REQUEST:${currentUser.id}:${currentUser.username || 'User'}`;
3267
 
3268
  // Use QRCode library if available, otherwise use API
3269
  if (typeof QRCode !== 'undefined') {
3270
  try {
3271
- new QRCode(newCanvas, {
3272
  text: friendRequestData,
3273
  width: 200,
3274
  height: 200,
@@ -3276,39 +3281,50 @@ function showQRCodeModal() {
3276
  colorLight: '#ffffff',
3277
  correctLevel: QRCode.CorrectLevel.H
3278
  });
 
3279
  } catch (error) {
3280
- console.error('QRCode error:', error);
3281
- generateQRCodeFallback(newCanvas, friendRequestData);
3282
  }
3283
  } else {
 
3284
  // Use API fallback
3285
- generateQRCodeFallback(newCanvas, friendRequestData);
3286
  }
3287
 
3288
  modal.classList.add('show');
3289
  }
3290
 
3291
- function generateQRCodeFallback(canvas, data) {
3292
- const ctx = canvas.getContext('2d');
3293
- canvas.width = 200;
3294
- canvas.height = 200;
3295
 
3296
- // Use QR Code API
3297
  const img = new Image();
 
 
 
 
 
 
3298
  img.onload = () => {
3299
- ctx.drawImage(img, 0, 0, 200, 200);
 
 
3300
  };
 
3301
  img.onerror = () => {
3302
- // Final fallback - draw text
3303
- ctx.fillStyle = '#fff';
3304
- ctx.fillRect(0, 0, 200, 200);
3305
- ctx.fillStyle = '#000';
3306
- ctx.font = 'bold 16px monospace';
3307
- ctx.textAlign = 'center';
3308
- ctx.fillText('Scan QR Code', 100, 80);
3309
- ctx.fillText('User ID:', 100, 110);
3310
- ctx.fillText(currentUser.id.toString(), 100, 130);
 
3311
  };
 
3312
  img.src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(data)}`;
3313
  }
3314
 
@@ -3365,57 +3381,81 @@ function scanQRCodeForFriend() {
3365
 
3366
  // ==================== VIDEO CALL MODAL ====================
3367
 
3368
- function openVideoCallModal() {
3369
- const targetName = currentChatContext.name || 'Unknown';
 
 
3370
 
3371
- customAlert(
3372
- `πŸ“ž <strong>Video Call Starting...</strong><br><br>` +
3373
- `Calling: <strong>${targetName}</strong><br>` +
3374
- `Type: ${currentChatContext.type === 'group' ? 'Group Call' : '1-on-1 Call'}<br><br>` +
3375
- `<em>Waiting for ${targetName} to answer...</em><br><br>` +
3376
- `<small>⚠️ Video call uses WebRTC (P2P connection)</small>`,
3377
- 'πŸ“ž Video Call',
3378
- 'πŸ“ž'
3379
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3380
 
3381
- // Emit to server
3382
- if (socket && socket.connected && currentChatContext.id) {
3383
  socket.emit('start video call', {
3384
- targetId: currentChatContext.id,
3385
- type: currentChatContext.type,
3386
  targetName: targetName
3387
  });
 
3388
  }
3389
  }
3390
 
3391
  function visitUserProfile(userId, userName = 'User') {
 
 
 
 
 
 
3392
  // Create a more detailed profile view
3393
  const html = `
3394
  <div style="text-align: center; padding: 20px 0;">
3395
- <div style="width: 100px; height: 100px; background: var(--primary-color); border-radius: 50%; margin: 0 auto 20px; display: flex; align-items: center; justify-content: center; font-size: 48px; color: white;">
3396
- πŸ‘€
3397
  </div>
3398
  <h3 style="margin: 10px 0; color: var(--text-primary);">${userName}</h3>
3399
- <p style="margin: 5px 0; color: var(--text-secondary); font-size: 13px;">User ID: ${userId}</p>
3400
- <div style="margin-top: 20px; display: flex; gap: 10px; justify-content: center;">
3401
- <button onclick="{
3402
  currentChatContext = { id: '${userId}', name: '${userName}', type: 'dm' };
3403
  openDM('${userId}', '${userName}');
3404
  closeCustomDialog();
3405
- }" style="padding: 8px 16px; background: var(--success); color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 500;">
3406
- πŸ’¬ Message
3407
  </button>
3408
- <button onclick="{
3409
  currentChatContext = { id: '${userId}', name: '${userName}', type: 'dm' };
3410
- openVideoCallModal();
3411
  closeCustomDialog();
3412
- }" style="padding: 8px 16px; background: var(--primary-color); color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 500;">
3413
- πŸ“ž Call
 
3414
  </button>
3415
- <button onclick="{
3416
  sendFriendRequest('${userId}', '${userName}');
3417
- closeCustomDialog();
3418
- }" style="padding: 8px 16px; background: #8e44ad; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 500;">
3419
  πŸ‘₯ Add Friend
3420
  </button>
3421
  </div>
 
1058
  avatar.style.backgroundSize = 'cover';
1059
  avatar.style.backgroundPosition = 'center';
1060
  } else {
1061
+ avatar.textContent = user.username ? user.username.charAt(0).toUpperCase() : 'U';
1062
  }
1063
 
1064
  const status = document.createElement('div');
1065
  status.className = 'status-indicator';
1066
 
1067
  const name = document.createElement('span');
1068
+ name.textContent = user.username || 'Unknown';
1069
+
1070
+ // Get correct user ID (handle different property names)
1071
+ const userId = user.id || user._id || user.userId;
1072
+ const username = user.username || 'User';
1073
 
1074
  // Make item clickable to view profile
1075
  item.onclick = () => {
1076
+ if (!userId) {
1077
+ showToast('❌ User ID not available', 'error');
1078
+ return;
1079
+ }
1080
+ if (userId === currentUser.id || userId === currentUser._id) {
1081
  openProfile();
1082
  } else {
1083
+ visitUserProfile(userId, username);
1084
  }
1085
  };
1086
 
 
2941
  // ==================== VIDEO CALLS ====================
2942
 
2943
  function startVideoCall() {
2944
+ if (!currentChatContext || currentChatContext.type === 'none' || !currentChatContext.id) {
2945
+ showToast('❌ Please open a chat first', 'warning');
2946
  return;
2947
  }
2948
 
2949
+ const targetName = currentChatContext.name || 'User';
2950
+ const targetId = currentChatContext.id;
2951
+ const callType = currentChatContext.type === 'group' ? 'Group Call' : 'Video Call';
 
2952
 
2953
+ // Open video call modal
2954
+ openVideoCallModal(targetName, targetId, callType);
 
 
2955
  }
2956
 
2957
  // ==================== ARCHIVE CHATS ====================
 
3244
 
3245
  function showQRCodeModal() {
3246
  const modal = document.getElementById('qrModal');
3247
+ const qrContainer = document.querySelector('.qr-code-container');
3248
  const userIdSpan = document.getElementById('qrUserId');
3249
 
3250
  if (!currentUser || !currentUser.id) {
 
3252
  return;
3253
  }
3254
 
3255
+ // Clear previous QR code completely
3256
+ qrContainer.innerHTML = '';
 
 
 
 
3257
 
3258
+ // Create new container div for QR code
3259
+ const qrDiv = document.createElement('div');
3260
+ qrDiv.id = 'qrCodeCanvas';
3261
+ qrDiv.style.backgroundColor = '#ffffff';
3262
+ qrDiv.style.padding = '10px';
3263
+ qrDiv.style.borderRadius = '8px';
3264
+ qrDiv.style.display = 'inline-block';
3265
+ qrContainer.appendChild(qrDiv);
3266
 
3267
  // Display user ID
3268
+ userIdSpan.textContent = currentUser.id || currentUser._id || 'Unknown';
3269
 
3270
  // Generate QR code with friend request data
3271
+ const friendRequestData = `FRIEND_REQUEST:${currentUser.id || currentUser._id}:${currentUser.username || 'User'}`;
3272
 
3273
  // Use QRCode library if available, otherwise use API
3274
  if (typeof QRCode !== 'undefined') {
3275
  try {
3276
+ new QRCode(qrDiv, {
3277
  text: friendRequestData,
3278
  width: 200,
3279
  height: 200,
 
3281
  colorLight: '#ffffff',
3282
  correctLevel: QRCode.CorrectLevel.H
3283
  });
3284
+ console.log('βœ… QR Code generated successfully');
3285
  } catch (error) {
3286
+ console.error('❌ QRCode library error:', error);
3287
+ generateQRCodeFallback(qrDiv, friendRequestData);
3288
  }
3289
  } else {
3290
+ console.warn('⚠️ QRCode library not loaded, using fallback');
3291
  // Use API fallback
3292
+ generateQRCodeFallback(qrDiv, friendRequestData);
3293
  }
3294
 
3295
  modal.classList.add('show');
3296
  }
3297
 
3298
+ function generateQRCodeFallback(container, data) {
3299
+ console.log('πŸ“± Using QR Code API fallback');
 
 
3300
 
3301
+ // Use QR Code API with image
3302
  const img = new Image();
3303
+ img.style.width = '200px';
3304
+ img.style.height = '200px';
3305
+ img.style.display = 'block';
3306
+ img.style.backgroundColor = '#ffffff';
3307
+ img.style.borderRadius = '8px';
3308
+
3309
  img.onload = () => {
3310
+ console.log('βœ… QR Code loaded from API');
3311
+ container.innerHTML = '';
3312
+ container.appendChild(img);
3313
  };
3314
+
3315
  img.onerror = () => {
3316
+ console.error('❌ QR Code API failed');
3317
+ // Final fallback - show text
3318
+ container.innerHTML = `
3319
+ <div style="width: 200px; height: 200px; background: white; border: 2px solid #000; border-radius: 8px; display: flex; align-items: center; justify-content: center; flex-direction: column; padding: 20px; box-sizing: border-box;">
3320
+ <div style="font-size: 24px; margin-bottom: 10px;">πŸ“±</div>
3321
+ <div style="font-weight: bold; color: #000; margin-bottom: 8px;">Friend Request</div>
3322
+ <div style="font-size: 12px; color: #666; word-break: break-all; text-align: center;">${currentUser.username || 'User'}</div>
3323
+ <div style="font-size: 10px; color: #999; margin-top: 8px;">ID: ${(currentUser.id || currentUser._id || 'N/A').substring(0, 8)}...</div>
3324
+ </div>
3325
+ `;
3326
  };
3327
+
3328
  img.src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(data)}`;
3329
  }
3330
 
 
3381
 
3382
  // ==================== VIDEO CALL MODAL ====================
3383
 
3384
+ function openVideoCallModal(targetName, targetId, callType) {
3385
+ targetName = targetName || currentChatContext.name || 'User';
3386
+ targetId = targetId || currentChatContext.id;
3387
+ callType = callType || 'Video Call';
3388
 
3389
+ const html = `
3390
+ <div style="text-align: center; padding: 20px;">
3391
+ <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;">
3392
+ πŸ“ž
3393
+ </div>
3394
+ <h3 style="margin: 15px 0; color: var(--text-primary); font-size: 24px;">${callType}</h3>
3395
+ <p style="margin: 10px 0; color: var(--text-secondary); font-size: 16px;">Calling <strong style="color: var(--primary-color);">${targetName}</strong></p>
3396
+ <p style="margin: 20px 0; color: var(--text-secondary); font-size: 14px; font-style: italic;">πŸ”Š Ringing...</p>
3397
+ <div style="margin-top: 30px; padding: 15px; background: rgba(88, 101, 242, 0.1); border-radius: 8px; border: 1px solid var(--primary-color);">
3398
+ <p style="color: var(--text-secondary); font-size: 13px; margin: 0;">πŸ’‘ <strong>Video Call Ready!</strong></p>
3399
+ <p style="color: var(--text-secondary); font-size: 12px; margin: 8px 0 0 0;">Full WebRTC integration will enable live video/audio streaming</p>
3400
+ </div>
3401
+ <button onclick="closeCustomDialog();" 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;">
3402
+ ❌ End Call
3403
+ </button>
3404
+ </div>
3405
+ <style>
3406
+ @keyframes pulse {
3407
+ 0%, 100% { transform: scale(1); }
3408
+ 50% { transform: scale(1.05); }
3409
+ }
3410
+ </style>
3411
+ `;
3412
+
3413
+ customAlert(html, 'πŸ“ž Video Call', 'πŸ“ž');
3414
 
3415
+ // Emit to server if connected
3416
+ if (socket && socket.connected && targetId) {
3417
  socket.emit('start video call', {
3418
+ targetId: targetId,
3419
+ type: currentChatContext.type || 'dm',
3420
  targetName: targetName
3421
  });
3422
+ showToast(`πŸ“ž Calling ${targetName}...`, 'success');
3423
  }
3424
  }
3425
 
3426
  function visitUserProfile(userId, userName = 'User') {
3427
+ // Validate inputs
3428
+ if (!userId || userId === 'undefined') {
3429
+ showToast('❌ Invalid user ID', 'error');
3430
+ return;
3431
+ }
3432
+
3433
  // Create a more detailed profile view
3434
  const html = `
3435
  <div style="text-align: center; padding: 20px 0;">
3436
+ <div style="width: 100px; height: 100px; background: linear-gradient(135deg, var(--primary-color), #4752c4); border-radius: 50%; margin: 0 auto 20px; display: flex; align-items: center; justify-content: center; font-size: 48px; color: white;">
3437
+ ${userName.charAt(0).toUpperCase()}
3438
  </div>
3439
  <h3 style="margin: 10px 0; color: var(--text-primary);">${userName}</h3>
3440
+ <p style="margin: 5px 0; color: var(--text-secondary); font-size: 13px;">Status: <span style="color: var(--success);">●</span> Online</p>
3441
+ <div style="margin-top: 20px; display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;">
3442
+ <button onclick="(function() {
3443
  currentChatContext = { id: '${userId}', name: '${userName}', type: 'dm' };
3444
  openDM('${userId}', '${userName}');
3445
  closeCustomDialog();
3446
+ })()" style="padding: 10px 20px; background: var(--success); color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: 600; transition: all 0.2s;">
3447
+ πŸ’¬ Send Message
3448
  </button>
3449
+ <button onclick="(function() {
3450
  currentChatContext = { id: '${userId}', name: '${userName}', type: 'dm' };
 
3451
  closeCustomDialog();
3452
+ setTimeout(() => startVideoCall(), 200);
3453
+ })()" style="padding: 10px 20px; background: var(--primary-color); color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: 600; transition: all 0.2s;">
3454
+ πŸ“ž Video Call
3455
  </button>
3456
+ <button onclick="(function() {
3457
  sendFriendRequest('${userId}', '${userName}');
3458
+ })()" style="padding: 10px 20px; background: #8e44ad; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: 600; transition: all 0.2s;">
 
3459
  πŸ‘₯ Add Friend
3460
  </button>
3461
  </div>
index.html CHANGED
@@ -1402,27 +1402,28 @@
1402
  }
1403
 
1404
  .main-container {
1405
- grid-template-columns: 60px 1fr;
1406
  height: 100vh;
1407
  height: 100dvh;
1408
  max-height: -webkit-fill-available;
1409
  }
1410
 
1411
- /* Mobile Guild Sidebar */
1412
  .guild-sidebar {
1413
- padding: 4px 0;
 
1414
  }
1415
 
1416
  .guild-item {
1417
- width: 48px;
1418
- height: 48px;
1419
- font-size: 20px;
1420
- margin-bottom: 6px;
1421
  }
1422
 
1423
  .guild-divider {
1424
- width: 28px;
1425
- margin: 6px 0;
1426
  }
1427
 
1428
  /* Mobile Channel Sidebar */
@@ -1939,10 +1940,16 @@
1939
  /* ==================== ENHANCED HOVER EFFECTS ==================== */
1940
  .danger-hover:hover {
1941
  color: var(--danger) !important;
1942
- transform: scale(1.1);
1943
  filter: drop-shadow(0 0 8px rgba(240, 71, 71, 0.6));
1944
  }
1945
 
 
 
 
 
 
 
1946
  .success-hover:hover {
1947
  color: var(--success) !important;
1948
  transform: scale(1.1);
@@ -2129,7 +2136,7 @@
2129
  <button class="header-btn success" onclick="addCurrentChatToList()" title="Add chat to list">
2130
  <i class="fas fa-bookmark"></i>
2131
  </button>
2132
- <button class="header-btn" onclick="closeCurrentChat()" title="Close Chat" id="closeChatBtn" style="display: none;">
2133
  <i class="fas fa-times-circle"></i>
2134
  </button>
2135
  <button class="header-btn" onclick="openSettings()" title="Settings">
@@ -2556,6 +2563,7 @@
2556
  <div id="groupsList" style="margin-top: 16px;"></div>
2557
  <button class="save-btn" onclick="closeGroupsModal()" style="margin-top: 20px;">Close</button>
2558
  </div>
 
2559
  </div>
2560
 
2561
  <!-- QR CODE MODAL -->
 
1402
  }
1403
 
1404
  .main-container {
1405
+ grid-template-columns: 45px 1fr;
1406
  height: 100vh;
1407
  height: 100dvh;
1408
  max-height: -webkit-fill-available;
1409
  }
1410
 
1411
+ /* Mobile Guild Sidebar - Compact */
1412
  .guild-sidebar {
1413
+ padding: 2px 0;
1414
+ width: 45px;
1415
  }
1416
 
1417
  .guild-item {
1418
+ width: 40px;
1419
+ height: 40px;
1420
+ font-size: 18px;
1421
+ margin-bottom: 4px;
1422
  }
1423
 
1424
  .guild-divider {
1425
+ width: 24px;
1426
+ margin: 4px 0;
1427
  }
1428
 
1429
  /* Mobile Channel Sidebar */
 
1940
  /* ==================== ENHANCED HOVER EFFECTS ==================== */
1941
  .danger-hover:hover {
1942
  color: var(--danger) !important;
1943
+ transform: scale(1.08);
1944
  filter: drop-shadow(0 0 8px rgba(240, 71, 71, 0.6));
1945
  }
1946
 
1947
+ /* Keep text white on danger button hover */
1948
+ .save-btn.danger-hover:hover {
1949
+ color: white !important;
1950
+ transform: scale(1.02) !important;
1951
+ }
1952
+
1953
  .success-hover:hover {
1954
  color: var(--success) !important;
1955
  transform: scale(1.1);
 
2136
  <button class="header-btn success" onclick="addCurrentChatToList()" title="Add chat to list">
2137
  <i class="fas fa-bookmark"></i>
2138
  </button>
2139
+ <button class="header-btn danger-hover" onclick="closeCurrentChat()" title="Close Chat" id="closeChatBtn" style="display: none;">
2140
  <i class="fas fa-times-circle"></i>
2141
  </button>
2142
  <button class="header-btn" onclick="openSettings()" title="Settings">
 
2563
  <div id="groupsList" style="margin-top: 16px;"></div>
2564
  <button class="save-btn" onclick="closeGroupsModal()" style="margin-top: 20px;">Close</button>
2565
  </div>
2566
+
2567
  </div>
2568
 
2569
  <!-- QR CODE MODAL -->