Starchik1 commited on
Commit
7aeb84b
·
verified ·
1 Parent(s): a37d85e

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +127 -73
main.py CHANGED
@@ -113,6 +113,7 @@ HTML_TEMPLATE = '''
113
  margin-top: 10px;
114
  border-radius: 15px;
115
  font-size: 14px;
 
116
  }
117
 
118
  .messages-container {
@@ -299,12 +300,14 @@ HTML_TEMPLATE = '''
299
  z-index: 100;
300
  max-height: 200px;
301
  overflow-y: auto;
 
302
  }
303
 
304
  .user-item {
305
- padding: 10px;
306
  border-bottom: 1px solid #eee;
307
  cursor: pointer;
 
308
  }
309
 
310
  .user-item:last-child {
@@ -314,6 +317,20 @@ HTML_TEMPLATE = '''
314
  .user-item:active {
315
  background: #f0f0f0;
316
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  </style>
318
  </head>
319
  <body>
@@ -336,6 +353,10 @@ HTML_TEMPLATE = '''
336
  <h2>💬 Мессенджер</h2>
337
  <div class="online-users" onclick="toggleUserList()">
338
  Онлайн: <span id="onlineCount">0</span> пользователей
 
 
 
 
339
  </div>
340
  <div id="userList" class="user-list"></div>
341
  </div>
@@ -362,7 +383,7 @@ HTML_TEMPLATE = '''
362
  <div id="recordingOverlay" class="recording-overlay">
363
  <div class="recording-animation"></div>
364
  <h3>Запись голосового сообщения...</h3>
365
- <p>Отпустите для отправки</p>
366
  </div>
367
 
368
  <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>
@@ -377,6 +398,7 @@ HTML_TEMPLATE = '''
377
  let peerConnection = null;
378
  let currentCall = null;
379
  let selectedUser = null;
 
380
 
381
  // WebRTC configuration
382
  const rtcConfig = {
@@ -395,11 +417,11 @@ HTML_TEMPLATE = '''
395
  currentUser = data;
396
  document.getElementById('loginScreen').style.display = 'none';
397
  document.getElementById('chatScreen').style.display = 'flex';
398
- updateUserList();
399
  });
400
 
401
  socket.on('user_list_update', (data) => {
402
  document.getElementById('onlineCount').textContent = data.count;
 
403
  updateUserList();
404
  });
405
 
@@ -499,6 +521,12 @@ HTML_TEMPLATE = '''
499
 
500
  container.appendChild(messageDiv);
501
  container.scrollTop = container.scrollHeight;
 
 
 
 
 
 
502
  }
503
 
504
  function displayVoiceMessage(data) {
@@ -526,13 +554,25 @@ HTML_TEMPLATE = '''
526
  const userList = document.getElementById('userList');
527
  userList.innerHTML = '';
528
 
529
- Object.values(users).forEach(user => {
530
- if (user.username !== currentUser.username) {
 
 
 
 
 
 
 
 
 
 
531
  const userItem = document.createElement('div');
532
  userItem.className = 'user-item';
533
- userItem.textContent = user.username;
534
  userItem.onclick = () => {
535
- selectedUser = user.username;
 
 
536
  userList.style.display = 'none';
537
  };
538
  userList.appendChild(userItem);
@@ -542,6 +582,10 @@ HTML_TEMPLATE = '''
542
 
543
  function toggleUserList() {
544
  const userList = document.getElementById('userList');
 
 
 
 
545
  userList.style.display = userList.style.display === 'block' ? 'none' : 'block';
546
  }
547
 
@@ -617,42 +661,48 @@ HTML_TEMPLATE = '''
617
 
618
  function playVoiceMessage(filename) {
619
  const audio = new Audio(`/voice/${filename}`);
620
- audio.play();
621
  }
622
 
623
  // WebRTC Functions
624
  async function createPeerConnection(isCaller) {
625
- peerConnection = new RTCPeerConnection(rtcConfig);
626
-
627
- // Add local stream if available
628
- if (localStream) {
629
- localStream.getTracks().forEach(track => {
630
- peerConnection.addTrack(track, localStream);
631
- });
632
- }
633
 
634
- // Handle incoming tracks
635
- peerConnection.ontrack = (event) => {
636
- remoteStream = event.streams[0];
637
- // Здесь можно добавить отображение удаленного видео
638
- };
639
-
640
- // Handle ICE candidates
641
- peerConnection.onicecandidate = (event) => {
642
- if (event.candidate) {
643
- socket.emit('webrtc_ice_candidate', {
644
- candidate: event.candidate,
645
- to_user: selectedUser || Object.values(users).find(u => u.username !== currentUser.username)?.username
646
  });
647
  }
648
- };
649
 
650
- return peerConnection;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
  }
652
 
653
  async function startAudioCall() {
654
  if (!selectedUser) {
655
- alert('Выберите пользователя из списка онлайн');
656
  toggleUserList();
657
  return;
658
  }
@@ -661,7 +711,7 @@ HTML_TEMPLATE = '''
661
 
662
  async function startVideoCall() {
663
  if (!selectedUser) {
664
- alert('Выберите пользователя из списка онлайн');
665
  toggleUserList();
666
  return;
667
  }
@@ -677,8 +727,7 @@ HTML_TEMPLATE = '''
677
  audio: true,
678
  video: isVideo ? {
679
  width: { ideal: 1280 },
680
- height: { ideal: 720 },
681
- frameRate: { ideal: 30 }
682
  } : false
683
  };
684
 
@@ -694,9 +743,11 @@ HTML_TEMPLATE = '''
694
 
695
  socket.emit('webrtc_offer', {
696
  offer: offer,
697
- to_user: targetUser
 
698
  });
699
 
 
700
  socket.emit('call_request', {
701
  call_id: Date.now().toString(),
702
  from_user: currentUser.username,
@@ -727,40 +778,26 @@ HTML_TEMPLATE = '''
727
  currentCall = null;
728
  }
729
 
730
- function toggleMute() {
731
- if (localStream) {
732
- const audioTrack = localStream.getAudioTracks()[0];
733
- if (audioTrack) {
734
- audioTrack.enabled = !audioTrack.enabled;
735
- }
736
- }
737
- }
738
-
739
- function toggleVideo() {
740
- if (localStream) {
741
- const videoTrack = localStream.getVideoTracks()[0];
742
- if (videoTrack) {
743
- videoTrack.enabled = !videoTrack.enabled;
744
- }
745
- }
746
- }
747
-
748
  // Touch events for voice recording
749
  let recordingTimer;
750
- document.querySelector('.action-btn[title="Голосовое сообщение"]').addEventListener('touchstart', function(e) {
751
- e.preventDefault();
752
- recordingTimer = setTimeout(() => {
753
- startRecording();
754
- }, 500);
755
- });
 
 
 
756
 
757
- document.querySelector('.action-btn[title="Голосовое сообщение"]').addEventListener('touchend', function(e) {
758
- e.preventDefault();
759
- clearTimeout(recordingTimer);
760
- if (isRecording) {
761
- stopRecording();
762
- }
763
- });
 
764
 
765
  // Click on recording overlay to stop
766
  document.getElementById('recordingOverlay').addEventListener('click', stopRecording);
@@ -778,12 +815,17 @@ HTML_TEMPLATE = '''
778
  }
779
  });
780
 
781
- // Prevent context menu on buttons
782
- document.addEventListener('contextmenu', (e) => {
783
- if (e.target.tagName === 'BUTTON') {
784
- e.preventDefault();
785
  }
786
  });
 
 
 
 
 
787
  </script>
788
  </body>
789
  </html>
@@ -796,6 +838,11 @@ def index():
796
  @socketio.on('connect')
797
  def handle_connect():
798
  print(f'Client connected: {request.sid}')
 
 
 
 
 
799
 
800
  @socketio.on('disconnect')
801
  def handle_disconnect():
@@ -803,7 +850,11 @@ def handle_disconnect():
803
  if user_data.get('sid') == request.sid:
804
  del users[user_id]
805
  break
806
- emit('user_list_update', {'count': len(users)}, broadcast=True)
 
 
 
 
807
 
808
  @socketio.on('register')
809
  def handle_register(username):
@@ -819,7 +870,10 @@ def handle_register(username):
819
  'username': username
820
  })
821
 
822
- emit('user_list_update', {'count': len(users)}, broadcast=True)
 
 
 
823
 
824
  @socketio.on('message')
825
  def handle_message(data):
@@ -883,7 +937,7 @@ def handle_call_answer(data):
883
  if target_sid:
884
  emit('call_answered', {
885
  'answer': data['answer'],
886
- 'from_user': data.get('from_user'),
887
  'isVideo': data.get('isVideo', False)
888
  }, room=target_sid)
889
 
 
113
  margin-top: 10px;
114
  border-radius: 15px;
115
  font-size: 14px;
116
+ cursor: pointer;
117
  }
118
 
119
  .messages-container {
 
300
  z-index: 100;
301
  max-height: 200px;
302
  overflow-y: auto;
303
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
304
  }
305
 
306
  .user-item {
307
+ padding: 12px 15px;
308
  border-bottom: 1px solid #eee;
309
  cursor: pointer;
310
+ color: #333;
311
  }
312
 
313
  .user-item:last-child {
 
317
  .user-item:active {
318
  background: #f0f0f0;
319
  }
320
+
321
+ .selected-user {
322
+ margin-top: 10px;
323
+ font-size: 14px;
324
+ background: rgba(255,255,255,0.3);
325
+ padding: 8px 12px;
326
+ border-radius: 15px;
327
+ }
328
+
329
+ .call-info {
330
+ margin-top: 5px;
331
+ font-size: 12px;
332
+ opacity: 0.9;
333
+ }
334
  </style>
335
  </head>
336
  <body>
 
353
  <h2>💬 Мессенджер</h2>
354
  <div class="online-users" onclick="toggleUserList()">
355
  Онлайн: <span id="onlineCount">0</span> пользователей
356
+ <div class="call-info">Нажмите для выбора</div>
357
+ </div>
358
+ <div id="selectedUserInfo" class="selected-user" style="display: none;">
359
+ Выбрано: <span id="selectedUserName">-</span>
360
  </div>
361
  <div id="userList" class="user-list"></div>
362
  </div>
 
383
  <div id="recordingOverlay" class="recording-overlay">
384
  <div class="recording-animation"></div>
385
  <h3>Запись голосового сообщения...</h3>
386
+ <p>Нажмите для остановки</p>
387
  </div>
388
 
389
  <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>
 
398
  let peerConnection = null;
399
  let currentCall = null;
400
  let selectedUser = null;
401
+ let onlineUsers = [];
402
 
403
  // WebRTC configuration
404
  const rtcConfig = {
 
417
  currentUser = data;
418
  document.getElementById('loginScreen').style.display = 'none';
419
  document.getElementById('chatScreen').style.display = 'flex';
 
420
  });
421
 
422
  socket.on('user_list_update', (data) => {
423
  document.getElementById('onlineCount').textContent = data.count;
424
+ onlineUsers = data.users || [];
425
  updateUserList();
426
  });
427
 
 
521
 
522
  container.appendChild(messageDiv);
523
  container.scrollTop = container.scrollHeight;
524
+
525
+ // Убираем placeholder если есть сообщения
526
+ const placeholder = container.querySelector('div[style*="text-align: center"]');
527
+ if (placeholder) {
528
+ placeholder.remove();
529
+ }
530
  }
531
 
532
  function displayVoiceMessage(data) {
 
554
  const userList = document.getElementById('userList');
555
  userList.innerHTML = '';
556
 
557
+ if (onlineUsers.length === 0) {
558
+ const emptyItem = document.createElement('div');
559
+ emptyItem.className = 'user-item';
560
+ emptyItem.textContent = 'Нет других пользователей онлайн';
561
+ emptyItem.style.color = '#999';
562
+ emptyItem.style.cursor = 'default';
563
+ userList.appendChild(emptyItem);
564
+ return;
565
+ }
566
+
567
+ onlineUsers.forEach(user => {
568
+ if (user !== currentUser.username) {
569
  const userItem = document.createElement('div');
570
  userItem.className = 'user-item';
571
+ userItem.textContent = user;
572
  userItem.onclick = () => {
573
+ selectedUser = user;
574
+ document.getElementById('selectedUserName').textContent = user;
575
+ document.getElementById('selectedUserInfo').style.display = 'block';
576
  userList.style.display = 'none';
577
  };
578
  userList.appendChild(userItem);
 
582
 
583
  function toggleUserList() {
584
  const userList = document.getElementById('userList');
585
+ if (onlineUsers.length <= 1) {
586
+ alert('Нет других пользователей онлайн');
587
+ return;
588
+ }
589
  userList.style.display = userList.style.display === 'block' ? 'none' : 'block';
590
  }
591
 
 
661
 
662
  function playVoiceMessage(filename) {
663
  const audio = new Audio(`/voice/${filename}`);
664
+ audio.play().catch(e => console.error('Error playing audio:', e));
665
  }
666
 
667
  // WebRTC Functions
668
  async function createPeerConnection(isCaller) {
669
+ try {
670
+ peerConnection = new RTCPeerConnection(rtcConfig);
 
 
 
 
 
 
671
 
672
+ // Add local stream if available
673
+ if (localStream) {
674
+ localStream.getTracks().forEach(track => {
675
+ peerConnection.addTrack(track, localStream);
 
 
 
 
 
 
 
 
676
  });
677
  }
 
678
 
679
+ // Handle incoming tracks
680
+ peerConnection.ontrack = (event) => {
681
+ remoteStream = event.streams[0];
682
+ // Можно добавить отображение удаленного видео
683
+ console.log('Remote track received');
684
+ };
685
+
686
+ // Handle ICE candidates
687
+ peerConnection.onicecandidate = (event) => {
688
+ if (event.candidate && selectedUser) {
689
+ socket.emit('webrtc_ice_candidate', {
690
+ candidate: event.candidate,
691
+ to_user: selectedUser
692
+ });
693
+ }
694
+ };
695
+
696
+ return peerConnection;
697
+ } catch (error) {
698
+ console.error('Error creating peer connection:', error);
699
+ throw error;
700
+ }
701
  }
702
 
703
  async function startAudioCall() {
704
  if (!selectedUser) {
705
+ alert('Сначала выберите пользователя из списка онлайн (нажмите на "Онлайн: X пользователей")');
706
  toggleUserList();
707
  return;
708
  }
 
711
 
712
  async function startVideoCall() {
713
  if (!selectedUser) {
714
+ alert('Сначала выберите пользователя из списка онлайн (нажмите на "Онлайн: X пользователей")');
715
  toggleUserList();
716
  return;
717
  }
 
727
  audio: true,
728
  video: isVideo ? {
729
  width: { ideal: 1280 },
730
+ height: { ideal: 720 }
 
731
  } : false
732
  };
733
 
 
743
 
744
  socket.emit('webrtc_offer', {
745
  offer: offer,
746
+ to_user: targetUser,
747
+ isVideo: isVideo
748
  });
749
 
750
+ // Send call request
751
  socket.emit('call_request', {
752
  call_id: Date.now().toString(),
753
  from_user: currentUser.username,
 
778
  currentCall = null;
779
  }
780
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
781
  // Touch events for voice recording
782
  let recordingTimer;
783
+ const voiceBtn = document.querySelector('.action-btn[title="Голосовое сообщение"]');
784
+
785
+ if (voiceBtn) {
786
+ voiceBtn.addEventListener('touchstart', function(e) {
787
+ e.preventDefault();
788
+ recordingTimer = setTimeout(() => {
789
+ startRecording();
790
+ }, 500);
791
+ });
792
 
793
+ voiceBtn.addEventListener('touchend', function(e) {
794
+ e.preventDefault();
795
+ clearTimeout(recordingTimer);
796
+ if (isRecording) {
797
+ stopRecording();
798
+ }
799
+ });
800
+ }
801
 
802
  // Click on recording overlay to stop
803
  document.getElementById('recordingOverlay').addEventListener('click', stopRecording);
 
815
  }
816
  });
817
 
818
+ // Close user list when clicking outside
819
+ document.addEventListener('click', (e) => {
820
+ if (!e.target.closest('.online-users') && !e.target.closest('.user-list')) {
821
+ document.getElementById('userList').style.display = 'none';
822
  }
823
  });
824
+
825
+ // Initialize
826
+ window.onload = function() {
827
+ onlineUsers = [];
828
+ };
829
  </script>
830
  </body>
831
  </html>
 
838
  @socketio.on('connect')
839
  def handle_connect():
840
  print(f'Client connected: {request.sid}')
841
+ # Send current user list to the newly connected client
842
+ emit('user_list_update', {
843
+ 'count': len(users),
844
+ 'users': [user_data['username'] for user_data in users.values()]
845
+ })
846
 
847
  @socketio.on('disconnect')
848
  def handle_disconnect():
 
850
  if user_data.get('sid') == request.sid:
851
  del users[user_id]
852
  break
853
+
854
+ emit('user_list_update', {
855
+ 'count': len(users),
856
+ 'users': [user_data['username'] for user_data in users.values()]
857
+ }, broadcast=True)
858
 
859
  @socketio.on('register')
860
  def handle_register(username):
 
870
  'username': username
871
  })
872
 
873
+ emit('user_list_update', {
874
+ 'count': len(users),
875
+ 'users': [user_data['username'] for user_data in users.values()]
876
+ }, broadcast=True)
877
 
878
  @socketio.on('message')
879
  def handle_message(data):
 
937
  if target_sid:
938
  emit('call_answered', {
939
  'answer': data['answer'],
940
+ 'from_user': data.get('from_user', current_user),
941
  'isVideo': data.get('isVideo', False)
942
  }, room=target_sid)
943