Timon2414 commited on
Commit
3c009cb
·
verified ·
1 Parent(s): c4e4848

Почему опять нельзя писать другу???? Почему опять ненастоящие чаты??? Мне нужен мессенджер, чтобы реально переписываться с другим пользователем мессенджера, который зарегестрируется в нем, я с ним хочу общаться. Ники сделай, реальный глобальный поиск - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +656 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Messenger
3
- emoji: 🐢
4
- colorFrom: yellow
5
- colorTo: red
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: messenger
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: purple
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,656 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ru">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Real Messenger - Настоящий мессенджер</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
10
+ <style>
11
+ /* Кастомные стили */
12
+ .message-animation {
13
+ animation: fadeIn 0.3s ease-in-out;
14
+ }
15
+ @keyframes fadeIn {
16
+ from { opacity: 0; transform: translateY(10px); }
17
+ to { opacity: 1; transform: translateY(0); }
18
+ }
19
+ .typing-indicator:after {
20
+ content: '...';
21
+ animation: typing 1.5s infinite;
22
+ }
23
+ @keyframes typing {
24
+ 0% { content: '.'; }
25
+ 33% { content: '..'; }
26
+ 66% { content: '...'; }
27
+ }
28
+ .gradient-bg {
29
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
30
+ }
31
+ .scrollbar-hide::-webkit-scrollbar {
32
+ display: none;
33
+ }
34
+ </style>
35
+ </head>
36
+ <body class="bg-gray-100 font-sans">
37
+ <!-- Модальное окно авторизации -->
38
+ <div id="auth-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
39
+ <div class="bg-white rounded-lg w-full max-w-md mx-4">
40
+ <div class="p-4 border-b">
41
+ <h3 class="font-bold text-lg">Вход / Регистрация</h3>
42
+ </div>
43
+ <div class="p-4">
44
+ <div class="mb-4">
45
+ <label class="block text-sm font-medium mb-1">Логин</label>
46
+ <input type="text" id="auth-username" class="w-full px-4 py-2 border rounded">
47
+ </div>
48
+ <div class="mb-4">
49
+ <label class="block text-sm font-medium mb-1">Пароль</label>
50
+ <input type="password" id="auth-password" class="w-full px-4 py-2 border rounded">
51
+ </div>
52
+ <div class="mb-4 hidden" id="auth-name-field">
53
+ <label class="block text-sm font-medium mb-1">Ваше имя</label>
54
+ <input type="text" id="auth-name" class="w-full px-4 py-2 border rounded">
55
+ </div>
56
+ <div class="text-red-500 text-sm mb-4 hidden" id="auth-error"></div>
57
+ </div>
58
+ <div class="p-4 border-t flex justify-between">
59
+ <button id="auth-toggle" class="text-purple-600 hover:underline">Создать аккаунт</button>
60
+ <div>
61
+ <button id="auth-cancel" class="px-4 py-2 bg-gray-200 rounded mr-2 hover:bg-gray-300">Отмена</button>
62
+ <button id="auth-submit" class="px-4 py-2 bg-purple-600 text-white rounded hover:bg-purple-700">Войти</button>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ </div>
67
+
68
+ <!-- Главный контейнер -->
69
+ <div class="flex h-screen overflow-hidden">
70
+ <!-- Боковая панель -->
71
+ <div class="w-20 md:w-80 bg-white shadow-lg flex flex-col">
72
+ <!-- Заголовок -->
73
+ <div class="p-4 gradient-bg text-white flex items-center justify-between">
74
+ <div class="flex items-center">
75
+ <i class="fas fa-bolt text-yellow-300 text-2xl mr-2"></i>
76
+ <span class="text-xl font-bold hidden md:block">Quantum</span>
77
+ </div>
78
+ <button id="new-chat-btn" class="p-2 rounded-full hover:bg-white hover:bg-opacity-20 transition">
79
+ <i class="fas fa-plus"></i>
80
+ </button>
81
+ </div>
82
+
83
+ <!-- Поиск пользователей -->
84
+ <div class="p-3 border-b">
85
+ <div class="relative">
86
+ <input type="text" id="user-search" placeholder="Найти пользователя..."
87
+ class="w-full pl-10 pr-4 py-2 rounded-full bg-gray-100 focus:outline-none focus:ring-2 focus:ring-purple-500 text-sm">
88
+ <i class="fas fa-search absolute left-3 top-3 text-gray-400"></i>
89
+ </div>
90
+ <div id="search-results" class="absolute z-10 mt-1 w-full md:w-80 bg-white shadow-lg rounded-md hidden">
91
+ <!-- Результаты поиска будут здесь -->
92
+ </div>
93
+ </div>
94
+
95
+ <!-- Список чатов -->
96
+ <div class="flex-1 overflow-y-auto scrollbar-hide" id="chat-list">
97
+ <!-- Чат будет добавляться динамически -->
98
+ </div>
99
+
100
+ <!-- Профиль пользователя -->
101
+ <div class="p-3 border-t flex items-center justify-between bg-gray-50">
102
+ <div class="flex items-center">
103
+ <div class="w-10 h-10 rounded-full bg-purple-500 flex items-center justify-center text-white font-bold">
104
+ U
105
+ </div>
106
+ <div class="ml-3 hidden md:block">
107
+ <div class="font-medium">Пользователь</div>
108
+ <div class="text-xs text-gray-500">Онлайн</div>
109
+ </div>
110
+ </div>
111
+ <div class="hidden md:flex space-x-2">
112
+ <button class="p-1 text-gray-500 hover:text-purple-600">
113
+ <i class="fas fa-cog"></i>
114
+ </button>
115
+ <button class="p-1 text-gray-500 hover:text-purple-600">
116
+ <i class="fas fa-sign-out-alt"></i>
117
+ </button>
118
+ </div>
119
+ </div>
120
+ </div>
121
+
122
+ <!-- Основное содержимое -->
123
+ <div class="flex-1 flex flex-col">
124
+ <!-- Заголовок чата -->
125
+ <div class="p-4 border-b flex items-center justify-between bg-white">
126
+ <div class="flex items-center">
127
+ <div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold">
128
+ М
129
+ </div>
130
+ <div class="ml-3">
131
+ <div class="font-medium">Максим</div>
132
+ <div class="text-xs text-gray-500" id="typing-status">Онлайн</div>
133
+ </div>
134
+ </div>
135
+ <div class="flex space-x-4">
136
+ <button class="p-2 text-gray-500 hover:text-purple-600">
137
+ <i class="fas fa-phone"></i>
138
+ </button>
139
+ <button class="p-2 text-gray-500 hover:text-purple-600">
140
+ <i class="fas fa-video"></i>
141
+ </button>
142
+ <button class="p-2 text-gray-500 hover:text-purple-600">
143
+ <i class="fas fa-info-circle"></i>
144
+ </button>
145
+ </div>
146
+ </div>
147
+
148
+ <!-- Область сообщений -->
149
+ <div class="flex-1 overflow-y-auto p-4 bg-gray-50" id="message-area">
150
+ <!-- Сообщения будут добавляться динамически -->
151
+ <div class="text-center text-gray-500 text-sm py-10">
152
+ Начните новый чат или выберите существующий
153
+ </div>
154
+ </div>
155
+
156
+ <!-- Панель ввода сообщения -->
157
+ <div class="p-3 border-t bg-white">
158
+ <!-- Инструменты -->
159
+ <div class="flex items-center justify-between mb-2">
160
+ <div class="flex space-x-3">
161
+ <button class="p-2 text-gray-500 hover:text-purple-600">
162
+ <i class="fas fa-paperclip"></i>
163
+ </button>
164
+ <button class="p-2 text-gray-500 hover:text-purple-600">
165
+ <i class="fas fa-image"></i>
166
+ </button>
167
+ <button class="p-2 text-gray-500 hover:text-purple-600">
168
+ <i class="fas fa-microphone"></i>
169
+ </button>
170
+ <button class="p-2 text-gray-500 hover:text-purple-600">
171
+ <i class="fas fa-gift"></i>
172
+ </button>
173
+ </div>
174
+ <div>
175
+ <button class="p-2 text-gray-500 hover:text-purple-600">
176
+ <i class="fas fa-magic"></i>
177
+ </button>
178
+ </div>
179
+ </div>
180
+
181
+ <!-- Поле ввода -->
182
+ <div class="relative">
183
+ <textarea id="message-input" rows="1" placeholder="Напишите сообщение..."
184
+ class="w-full pl-4 pr-12 py-3 rounded-full bg-gray-100 focus:outline-none focus:ring-2 focus:ring-purple-500 resize-none max-h-32"></textarea>
185
+ <button id="send-btn" class="absolute right-3 bottom-3 p-2 bg-purple-600 text-white rounded-full hover:bg-purple-700 transition">
186
+ <i class="fas fa-paper-plane"></i>
187
+ </button>
188
+ </div>
189
+
190
+ <!-- Дополнительные функции -->
191
+ <div class="mt-2 flex justify-between items-center text-xs text-gray-500">
192
+ <div>
193
+ <button class="hover:text-purple-600 mr-3">
194
+ <i class="fas fa-smile"></i> Эмодзи
195
+ </button>
196
+ <button class="hover:text-purple-600">
197
+ <i class="fas fa-keyboard"></i> Голосовой ввод
198
+ </button>
199
+ </div>
200
+ <div>
201
+ <span class="mr-2">Шифрование E2E</span>
202
+ <i class="fas fa-lock text-green-500"></i>
203
+ </div>
204
+ </div>
205
+ </div>
206
+ </div>
207
+
208
+ <!-- Правая панель (скрыта на мобильных) -->
209
+ <div class="hidden lg:block w-80 bg-white border-l">
210
+ <!-- Заголовок -->
211
+ <div class="p-4 border-b">
212
+ <h3 class="font-bold text-lg">Информация о чате</h3>
213
+ </div>
214
+
215
+ <!-- Информация о пользователе -->
216
+ <div class="p-4 border-b">
217
+ <div class="flex flex-col items-center">
218
+ <div class="w-20 h-20 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-3xl mb-3">
219
+ М
220
+ </div>
221
+ <h4 class="font-bold text-lg">Максим</h4>
222
+ <p class="text-sm text-gray-500 mb-3">Онлайн</p>
223
+ <button class="px-4 py-2 bg-purple-600 text-white rounded-full hover:bg-purple-700 transition text-sm">
224
+ Профиль
225
+ </button>
226
+ </div>
227
+ </div>
228
+
229
+ <!-- Медиафайлы -->
230
+ <div class="p-4 border-b">
231
+ <h4 class="font-bold mb-3">Медиафайлы</h4>
232
+ <div class="grid grid-cols-3 gap-2">
233
+ <div class="aspect-square bg-gray-200 rounded"></div>
234
+ <div class="aspect-square bg-gray-200 rounded"></div>
235
+ <div class="aspect-square bg-gray-200 rounded"></div>
236
+ <div class="aspect-square bg-gray-200 rounded"></div>
237
+ <div class="aspect-square bg-gray-200 rounded"></div>
238
+ <div class="aspect-square bg-gray-200 rounded"></div>
239
+ </div>
240
+ <button class="mt-3 text-sm text-purple-600 hover:underline">Показать все</button>
241
+ </div>
242
+
243
+ <!-- Дополнительные функции -->
244
+ <div class="p-4">
245
+ <h4 class="font-bold mb-3">Функции</h4>
246
+ <div class="space-y-2">
247
+ <button class="w-full flex items-center p-2 hover:bg-gray-100 rounded transition">
248
+ <i class="fas fa-users mr-3 text-purple-600"></i>
249
+ <span>Создать группу</span>
250
+ </button>
251
+ <button class="w-full flex items-center p-2 hover:bg-gray-100 rounded transition">
252
+ <i class="fas fa-star mr-3 text-purple-600"></i>
253
+ <span>Избранные сообщения</span>
254
+ </button>
255
+ <button class="w-full flex items-center p-2 hover:bg-gray-100 rounded transition">
256
+ <i class="fas fa-moon mr-3 text-purple-600"></i>
257
+ <span>Темный режим</span>
258
+ </button>
259
+ <button class="w-full flex items-center p-2 hover:bg-gray-100 rounded transition">
260
+ <i class="fas fa-bell-slash mr-3 text-purple-600"></i>
261
+ <span>Отключить уведомления</span>
262
+ </button>
263
+ </div>
264
+ </div>
265
+ </div>
266
+ </div>
267
+
268
+ <!-- Модальное окно нового чата -->
269
+ <div id="new-chat-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
270
+ <div class="bg-white rounded-lg w-full max-w-md mx-4">
271
+ <div class="p-4 border-b flex justify-between items-center">
272
+ <h3 class="font-bold text-lg">Новый чат</h3>
273
+ <button id="close-modal" class="p-2 text-gray-500 hover:text-gray-700">
274
+ <i class="fas fa-times"></i>
275
+ </button>
276
+ </div>
277
+ <div class="p-4">
278
+ <input type="text" placeholder="Поиск контактов..."
279
+ class="w-full px-4 py-2 rounded-full bg-gray-100 focus:outline-none focus:ring-2 focus:ring-purple-500 mb-4">
280
+ <div class="max-h-96 overflow-y-auto">
281
+ <!-- Контакты будут добавляться динамически -->
282
+ <div class="p-3 hover:bg-gray-100 rounded cursor-pointer flex items-center">
283
+ <div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold mr-3">
284
+ А
285
+ </div>
286
+ <div>
287
+ <div class="font-medium">Алексей</div>
288
+ <div class="text-xs text-gray-500">Онлайн</div>
289
+ </div>
290
+ </div>
291
+ <div class="p-3 hover:bg-gray-100 rounded cursor-pointer flex items-center">
292
+ <div class="w-10 h-10 rounded-full bg-red-500 flex items-center justify-center text-white font-bold mr-3">
293
+ М
294
+ </div>
295
+ <div>
296
+ <div class="font-medium">Мария</div>
297
+ <div class="text-xs text-gray-500">Был(а) 5 мин назад</div>
298
+ </div>
299
+ </div>
300
+ </div>
301
+ </div>
302
+ <div class="p-4 border-t flex justify-end">
303
+ <button class="px-4 py-2 bg-gray-200 rounded mr-2 hover:bg-gray-300">Отмена</button>
304
+ <button class="px-4 py-2 bg-purple-600 text-white rounded hover:bg-purple-700">Создать</button>
305
+ </div>
306
+ </div>
307
+ </div>
308
+
309
+ <script>
310
+ // Глобальные переменные
311
+ let currentUser = null;
312
+ let currentChat = null;
313
+ let users = {};
314
+ let socket = null;
315
+
316
+ // Инициализация приложения
317
+ document.addEventListener('DOMContentLoaded', function() {
318
+ // Показать модальное окно авторизации
319
+ document.getElementById('auth-modal').classList.remove('hidden');
320
+
321
+ // Обработчики авторизации
322
+ document.getElementById('auth-toggle').addEventListener('click', function() {
323
+ const nameField = document.getElementById('auth-name-field');
324
+ const isRegister = nameField.classList.contains('hidden');
325
+ nameField.classList.toggle('hidden', !isRegister);
326
+ this.textContent = isRegister ? 'Уже есть аккаунт' : 'Создать аккаунт';
327
+ document.getElementById('auth-submit').textContent = isRegister ? 'Зарегистрироваться' : 'Войти';
328
+ });
329
+
330
+ document.getElementById('auth-submit').addEventListener('click', authSubmit);
331
+ document.getElementById('auth-cancel').addEventListener('click', function() {
332
+ document.getElementById('auth-modal').classList.add('hidden');
333
+ });
334
+
335
+ // Поиск пользователей
336
+ document.getElementById('user-search').addEventListener('input', function() {
337
+ const query = this.value.trim();
338
+ if (query.length > 1) {
339
+ searchUsers(query);
340
+ } else {
341
+ document.getElementById('search-results').classList.add('hidden');
342
+ }
343
+ });
344
+ // Элементы интерфейса
345
+ const messageInput = document.getElementById('message-input');
346
+ const sendBtn = document.getElementById('send-btn');
347
+ const messageArea = document.getElementById('message-area');
348
+ const chatList = document.getElementById('chat-list');
349
+ const newChatBtn = document.getElementById('new-chat-btn');
350
+ const newChatModal = document.getElementById('new-chat-modal');
351
+ const closeModal = document.getElementById('close-modal');
352
+ const typingStatus = document.getElementById('typing-status');
353
+
354
+ // Авторазмер текстового поля
355
+ messageInput.addEventListener('input', function() {
356
+ this.style.height = 'auto';
357
+ this.style.height = (this.scrollHeight) + 'px';
358
+ });
359
+
360
+ // Отправка сообщения
361
+ function sendMessage() {
362
+ const text = messageInput.value.trim();
363
+ if (text) {
364
+ // Добавление сообщения в чат
365
+ addMessage('outgoing', text);
366
+ messageInput.value = '';
367
+ messageInput.style.height = 'auto';
368
+
369
+ // Уведомление о доставке
370
+ setTimeout(() => {
371
+ const messageDivs = messageArea.querySelectorAll('.flex.justify-end');
372
+ const lastMessage = messageDivs[messageDivs.length - 1];
373
+ const checkIcon = lastMessage.querySelector('.fa-check');
374
+ if (checkIcon) {
375
+ checkIcon.classList.add('fa-check-double');
376
+ checkIcon.classList.add('text-blue-300');
377
+ }
378
+ }, 1500);
379
+ }
380
+ }
381
+
382
+ // Добавление сообщения в чат
383
+ function addMessage(type, text) {
384
+ const messageDiv = document.createElement('div');
385
+ messageDiv.className = `flex mb-4 message-animation ${type === 'outgoing' ? 'justify-end' : 'justify-start'}`;
386
+
387
+ messageDiv.innerHTML = `
388
+ <div class="max-w-xs md:max-w-md lg:max-w-lg rounded-lg px-4 py-2 ${type === 'outgoing' ? 'bg-purple-600 text-white' : 'bg-white border'}">
389
+ <div class="text-sm">${text}</div>
390
+ <div class="text-right mt-1">
391
+ <span class="text-xs ${type === 'outgoing' ? 'text-purple-200' : 'text-gray-500'}">${formatTime()}</span>
392
+ ${type === 'outgoing' ? '<i class="fas fa-check ml-1 text-xs text-purple-200"></i>' : ''}
393
+ </div>
394
+ </div>
395
+ `;
396
+
397
+ messageArea.appendChild(messageDiv);
398
+ messageArea.scrollTop = messageArea.scrollHeight;
399
+ }
400
+
401
+ // Форматирование времени
402
+ function formatTime() {
403
+ const now = new Date();
404
+ return now.getHours().toString().padStart(2, '0') + ':' +
405
+ now.getMinutes().toString().padStart(2, '0');
406
+ }
407
+
408
+ // Добавление чата в список
409
+ function addChat(name, lastMessage, time, unread) {
410
+ const chatDiv = document.createElement('div');
411
+ chatDiv.className = 'p-3 border-b hover:bg-gray-50 cursor-pointer flex items-center';
412
+
413
+ chatDiv.innerHTML = `
414
+ <div class="w-10 h-10 rounded-full bg-${getRandomColor()}-500 flex items-center justify-center text-white font-bold mr-3">
415
+ ${name.charAt(0)}
416
+ </div>
417
+ <div class="flex-1 min-w-0">
418
+ <div class="font-medium truncate">${name}</div>
419
+ <div class="text-xs text-gray-500 truncate">${lastMessage}</div>
420
+ </div>
421
+ <div class="ml-2 flex flex-col items-end">
422
+ <span class="text-xs text-gray-500">${time}</span>
423
+ ${unread ? '<span class="mt-1 w-5 h-5 bg-purple-600 text-white text-xs rounded-full flex items-center justify-center">'+unread+'</span>' : ''}
424
+ </div>
425
+ `;
426
+
427
+ chatList.appendChild(chatDiv);
428
+ }
429
+
430
+ // Генерация случайного цвета
431
+ function getRandomColor() {
432
+ const colors = ['purple', 'blue', 'green', 'red', 'yellow', 'indigo', 'pink'];
433
+ return colors[Math.floor(Math.random() * colors.length)];
434
+ }
435
+
436
+ // Начальный чат с другом
437
+ addChat('Максим', 'Начните общение', 'только что', 0);
438
+
439
+ // Обработчики событий
440
+ sendBtn.addEventListener('click', sendMessage);
441
+
442
+ messageInput.addEventListener('keypress', function(e) {
443
+ if (e.key === 'Enter' && !e.shiftKey) {
444
+ e.preventDefault();
445
+ sendMessage();
446
+ }
447
+ });
448
+
449
+ newChatBtn.addEventListener('click', function() {
450
+ newChatModal.classList.remove('hidden');
451
+ });
452
+
453
+ closeModal.addEventListener('click', function() {
454
+ newChatModal.classList.add('hidden');
455
+ });
456
+
457
+ // Клик по пустому месту закрывает модальное окно
458
+ newChatModal.addEventListener('click', function(e) {
459
+ if (e.target === newChatModal) {
460
+ newChatModal.classList.add('hidden');
461
+ }
462
+ });
463
+
464
+ // Демонстрация функций
465
+ setTimeout(() => {
466
+ // Добавляем демонстрационное сообщение
467
+ addMessage('incoming', 'Привет! Добро пожаловать в Quantum Messenger - самый современный мессенджер!');
468
+
469
+ // Показываем статус "печатает"
470
+ setTimeout(() => {
471
+ typingStatus.textContent = 'Дмитрий печатает...';
472
+ typingStatus.classList.add('typing-indicator');
473
+
474
+ setTimeout(() => {
475
+ typingStatus.textContent = 'Онлайн';
476
+ typingStatus.classList.remove('typing-indicator');
477
+ addMessage('incoming', 'Здесь ты можешь отправлять текстовые сообщения, фото, видео, голосовые и многое другое!');
478
+ }, 2000);
479
+ }, 1500);
480
+ }, 1000);
481
+ // Подключение к WebSocket
482
+ function connectWebSocket() {
483
+ socket = new WebSocket('wss://your-server.com/ws');
484
+
485
+ socket.onopen = function() {
486
+ console.log('WebSocket connected');
487
+ // Отправляем данные аутентификации
488
+ socket.send(JSON.stringify({
489
+ type: 'auth',
490
+ token: localStorage.getItem('messenger_token')
491
+ }));
492
+ };
493
+
494
+ socket.onmessage = function(event) {
495
+ const message = JSON.parse(event.data);
496
+ handleSocketMessage(message);
497
+ };
498
+
499
+ socket.onclose = function() {
500
+ console.log('WebSocket disconnected');
501
+ setTimeout(connectWebSocket, 5000); // Переподключение через 5 сек
502
+ };
503
+ }
504
+
505
+ // Обработка сообщений WebSocket
506
+ function handleSocketMessage(message) {
507
+ switch(message.type) {
508
+ case 'message':
509
+ if (message.chatId === currentChat?.id) {
510
+ addMessage('incoming', message.text, message.sender);
511
+ }
512
+ break;
513
+ case 'user_status':
514
+ updateUserStatus(message.userId, message.status);
515
+ break;
516
+ case 'typing':
517
+ if (message.chatId === currentChat?.id) {
518
+ showTypingIndicator(message.userId);
519
+ }
520
+ break;
521
+ }
522
+ }
523
+
524
+ // Авторизация/регистрация
525
+ async function authSubmit() {
526
+ const username = document.getElementById('auth-username').value;
527
+ const password = document.getElementById('auth-password').value;
528
+ const isRegister = !document.getElementById('auth-name-field').classList.contains('hidden');
529
+ const name = isRegister ? document.getElementById('auth-name').value : '';
530
+
531
+ try {
532
+ const response = await axios.post(isRegister ? '/api/register' : '/api/login', {
533
+ username,
534
+ password,
535
+ name
536
+ });
537
+
538
+ localStorage.setItem('messenger_token', response.data.token);
539
+ currentUser = response.data.user;
540
+ document.getElementById('auth-modal').classList.add('hidden');
541
+ connectWebSocket();
542
+ loadUserData();
543
+ } catch (error) {
544
+ document.getElementById('auth-error').textContent = error.response?.data?.message || 'Ошибка';
545
+ document.getElementById('auth-error').classList.remove('hidden');
546
+ }
547
+ }
548
+
549
+ // Поиск пользователей
550
+ async function searchUsers(query) {
551
+ try {
552
+ const response = await axios.get(`/api/users/search?q=${query}`);
553
+ const results = document.getElementById('search-results');
554
+ results.innerHTML = '';
555
+
556
+ if (response.data.length > 0) {
557
+ response.data.forEach(user => {
558
+ const userDiv = document.createElement('div');
559
+ userDiv.className = 'p-3 hover:bg-gray-100 cursor-pointer flex items-center';
560
+ userDiv.innerHTML = `
561
+ <div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold mr-3">
562
+ ${user.name.charAt(0)}
563
+ </div>
564
+ <div>
565
+ <div class="font-medium">${user.name}</div>
566
+ <div class="text-xs text-gray-500">@${user.username}</div>
567
+ </div>
568
+ `;
569
+ userDiv.addEventListener('click', () => startChat(user));
570
+ results.appendChild(userDiv);
571
+ });
572
+ results.classList.remove('hidden');
573
+ } else {
574
+ results.innerHTML = '<div class="p-3 text-gray-500">Ничего не найдено</div>';
575
+ results.classList.remove('hidden');
576
+ }
577
+ } catch (error) {
578
+ console.error('Search error:', error);
579
+ }
580
+ }
581
+
582
+ // Начать новый чат
583
+ function startChat(user) {
584
+ currentChat = {
585
+ id: generateChatId(currentUser.id, user.id),
586
+ user: user
587
+ };
588
+ document.getElementById('search-results').classList.add('hidden');
589
+ document.getElementById('user-search').value = '';
590
+ loadChatMessages();
591
+ }
592
+
593
+ // Генерация ID чата
594
+ function generateChatId(userId1, userId2) {
595
+ return [userId1, userId2].sort().join('_');
596
+ }
597
+
598
+ // Загрузка сообщений чата
599
+ async function loadChatMessages() {
600
+ try {
601
+ const response = await axios.get(`/api/messages?chatId=${currentChat.id}`);
602
+ const messageArea = document.getElementById('message-area');
603
+ messageArea.innerHTML = '';
604
+
605
+ response.data.forEach(msg => {
606
+ const type = msg.senderId === currentUser.id ? 'outgoing' : 'incoming';
607
+ addMessage(type, msg.text, msg.sender);
608
+ });
609
+ } catch (error) {
610
+ console.error('Error loading messages:', error);
611
+ }
612
+ }
613
+
614
+ // Отправка сообщения
615
+ async function sendMessage() {
616
+ const text = document.getElementById('message-input').value.trim();
617
+ if (text && currentChat) {
618
+ try {
619
+ await axios.post('/api/messages', {
620
+ chatId: currentChat.id,
621
+ text: text,
622
+ recipientId: currentChat.user.id
623
+ });
624
+
625
+ // Отправка через WebSocket
626
+ if (socket) {
627
+ socket.send(JSON.stringify({
628
+ type: 'message',
629
+ chatId: currentChat.id,
630
+ text: text,
631
+ recipientId: currentChat.user.id
632
+ }));
633
+ }
634
+
635
+ addMessage('outgoing', text, currentUser);
636
+ document.getElementById('message-input').value = '';
637
+ } catch (error) {
638
+ console.error('Error sending message:', error);
639
+ }
640
+ }
641
+ }
642
+
643
+ // Загрузка данных пользователя
644
+ async function loadUserData() {
645
+ try {
646
+ const response = await axios.get('/api/user');
647
+ currentUser = response.data;
648
+ // Обновление UI с данными пользователя
649
+ } catch (error) {
650
+ console.error('Error loading user data:', error);
651
+ }
652
+ }
653
+ });
654
+ </script>
655
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Timon2414/messenger" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
656
+ </html>