school44s commited on
Commit
6c5dab0
·
verified ·
1 Parent(s): 5d2184d

Update script.js

Browse files
Files changed (1) hide show
  1. script.js +589 -589
script.js CHANGED
@@ -1,589 +1,589 @@
1
- // Firebase configuration
2
- const firebaseConfig = {
3
- apiKey: "AIzaSyDN6tU7Ln3JgeFP7jTprAjSgXDfzunDGQI",
4
- authDomain: "gay-db7b1.firebaseapp.com",
5
- databaseURL: "https://gay-db7b1-default-rtdb.firebaseio.com",
6
- projectId: "gay-db7b1",
7
- storageBucket: "gay-db7b1.appspot.com",
8
- messagingSenderId: "959507085021",
9
- appId: "1:959507085021:web:755901093c2c81d0fb4d34",
10
- measurementId: "G-1900F4D48J"
11
- };
12
-
13
- // Initialize Firebase
14
- firebase.initializeApp(firebaseConfig);
15
- const auth = firebase.auth();
16
- const db = firebase.database();
17
-
18
- // Global variables
19
- let currentRoomId = "general";
20
- let currentUser = null;
21
-
22
- // DOM elements
23
- const loginForm = document.getElementById("login-form");
24
- const registerForm = document.getElementById("register-form");
25
- const toggleAuth = document.getElementById("toggle-auth");
26
- const authTitle = document.getElementById("auth-title");
27
-
28
- // Toggle between login and register forms
29
- toggleAuth.addEventListener("click", () => {
30
- loginForm.classList.toggle("hidden");
31
- registerForm.classList.toggle("hidden");
32
- authTitle.textContent = loginForm.classList.contains("hidden") ? "Đăng ký" : "Đăng nhập";
33
- toggleAuth.textContent = loginForm.classList.contains("hidden") ? "Đã có tài khoản? Đăng nhập" : "Chưa có tài khoản? Đăng ký";
34
- });
35
-
36
- // Register form handler
37
- registerForm.addEventListener("submit", (e) => {
38
- e.preventDefault();
39
- const username = document.getElementById("register-username").value;
40
- const email = document.getElementById("register-email").value;
41
- const password = document.getElementById("register-password").value;
42
-
43
- auth.createUserWithEmailAndPassword(email, password).then(userCredential => {
44
- return userCredential.user.updateProfile({ displayName: username });
45
- }).then(() => {
46
- document.getElementById("display-name").textContent = auth.currentUser.displayName;
47
- showChat();
48
- }).catch(error => alert(error.message));
49
- });
50
-
51
- // Login form handler
52
- loginForm.addEventListener("submit", (e) => {
53
- e.preventDefault();
54
- const email = document.getElementById("login-email").value;
55
- const password = document.getElementById("login-password").value;
56
-
57
- auth.signInWithEmailAndPassword(email, password).then(() => {
58
- document.getElementById("display-name").textContent = auth.currentUser.displayName || auth.currentUser.email;
59
- showChat();
60
- }).catch(error => alert(error.message));
61
- });
62
-
63
- // Google login handler
64
- document.getElementById("google-login").addEventListener("click", () => {
65
- const provider = new firebase.auth.GoogleAuthProvider();
66
- auth.signInWithPopup(provider).then(() => {
67
- document.getElementById("display-name").textContent = auth.currentUser.displayName;
68
- showChat();
69
- }).catch(error => alert(error.message));
70
- });
71
-
72
- // Show chat section
73
- function showChat() {
74
- document.getElementById("auth-section").classList.add("hidden");
75
- document.getElementById("chat-section").classList.remove("hidden");
76
- currentUser = auth.currentUser;
77
-
78
- // Initialize room functionality
79
- initializeRooms();
80
- loadUserRooms();
81
- setupRoomListeners();
82
- }
83
-
84
- // Send message function
85
- function sendMessage() {
86
- const input = document.getElementById("chat-input");
87
- const imageInput = document.getElementById("imageInput");
88
- const videoInput = document.getElementById("videoInput");
89
- const text = input.value.trim();
90
- const images = imageInput.files;
91
- const videos = videoInput.files;
92
-
93
- if (!text && images.length === 0 && videos.length === 0) return;
94
-
95
- // Send text message if exists
96
- if (text) {
97
- db.ref(`rooms/${currentRoomId}/messages`).push({
98
- name: auth.currentUser.displayName || auth.currentUser.email,
99
- text: text,
100
- uid: auth.currentUser.uid,
101
- timestamp: Date.now()
102
- });
103
-
104
- // Update room last message
105
- updateRoomLastMessage(currentRoomId, text);
106
- }
107
-
108
- // Send images
109
- if (images.length > 0) {
110
- sendImages(images);
111
- }
112
-
113
- // Send videos
114
- if (videos.length > 0) {
115
- sendVideos(videos);
116
- }
117
-
118
- // Clear inputs
119
- input.value = "";
120
- imageInput.value = "";
121
- videoInput.value = "";
122
- document.getElementById("mediaPreview").innerHTML = "";
123
- }
124
-
125
- // Send images function
126
- async function sendImages(files) {
127
- for (const file of files) {
128
- try {
129
- const base64 = await toBase64(file);
130
- const imageUrl = await uploadToImgbb(base64);
131
- if (imageUrl) {
132
- db.ref(`rooms/${currentRoomId}/messages`).push({
133
- name: auth.currentUser.displayName || auth.currentUser.email,
134
- text: "",
135
- image: imageUrl,
136
- uid: auth.currentUser.uid,
137
- timestamp: Date.now()
138
- });
139
-
140
- // Update room last message
141
- updateRoomLastMessage(currentRoomId, "📷 Hình ảnh");
142
- }
143
- } catch (error) {
144
- console.error("Error uploading image:", error);
145
- alert("Lỗi upload ảnh!");
146
- }
147
- }
148
- }
149
-
150
- // Send videos function
151
- async function sendVideos(files) {
152
- for (const file of files) {
153
- try {
154
- showUploadProgress("Đang upload video...");
155
- const videoUrl = await uploadVideo(file);
156
- hideUploadProgress();
157
- if (videoUrl) {
158
- db.ref(`rooms/${currentRoomId}/messages`).push({
159
- name: auth.currentUser.displayName || auth.currentUser.email,
160
- text: "",
161
- video: videoUrl,
162
- uid: auth.currentUser.uid,
163
- timestamp: Date.now()
164
- });
165
-
166
- // Update room last message
167
- updateRoomLastMessage(currentRoomId, "🎥 Video");
168
- }
169
- } catch (error) {
170
- hideUploadProgress();
171
- console.error("Error uploading video:", error);
172
- alert("Lỗi upload video!");
173
- }
174
- }
175
- }
176
-
177
- // Convert file to base64
178
- function toBase64(file) {
179
- return new Promise((resolve, reject) => {
180
- const reader = new FileReader();
181
- reader.onloadend = () => resolve(reader.result.split(',')[1]);
182
- reader.onerror = reject;
183
- reader.readAsDataURL(file);
184
- });
185
- }
186
-
187
- // Upload image to imgbb
188
- async function uploadToImgbb(base64) {
189
- const apiKey = "eb64cc8f94a115e3a412694f2a0f10b3";
190
- const formData = new FormData();
191
- formData.append("key", apiKey);
192
- formData.append("image", base64);
193
-
194
- try {
195
- const response = await fetch("https://api.imgbb.com/1/upload", {
196
- method: "POST",
197
- body: formData
198
- });
199
- const result = await response.json();
200
- return result.data.url;
201
- } catch (error) {
202
- console.error("Error uploading to imgbb:", error);
203
- return null;
204
- }
205
- }
206
-
207
- // Upload video to server
208
- async function uploadVideo(file) {
209
- const formData = new FormData();
210
- formData.append("file", file);
211
-
212
- try {
213
- const response = await fetch("http://192.168.1.6:5000/upload", {
214
- method: "POST",
215
- body: formData,
216
- });
217
-
218
- const result = await response.json();
219
-
220
- // Check if upload was successful
221
- if (result.status === "success" && result.data && result.data.url) {
222
- return result.data.url;
223
- } else {
224
- console.error("Upload failed:", result);
225
- return null;
226
- }
227
- } catch (error) {
228
- console.error("Error uploading video:", error);
229
- return null;
230
- }
231
- }
232
-
233
- // Show upload progress
234
- function showUploadProgress(message) {
235
- const preview = document.getElementById("mediaPreview");
236
- preview.innerHTML = `
237
- <div class="upload-progress">
238
- <div class="upload-progress-bar" style="width: 100%">${message}</div>
239
- </div>
240
- `;
241
- }
242
-
243
- // Hide upload progress
244
- function hideUploadProgress() {
245
- document.getElementById("mediaPreview").innerHTML = "";
246
- }
247
-
248
- // Preview selected images
249
- document.getElementById("imageInput").addEventListener("change", function() {
250
- const files = this.files;
251
- const preview = document.getElementById("mediaPreview");
252
- preview.innerHTML = "";
253
-
254
- for (const file of files) {
255
- const reader = new FileReader();
256
- reader.onload = () => {
257
- const img = document.createElement("img");
258
- img.src = reader.result;
259
- img.title = file.name;
260
- preview.appendChild(img);
261
- };
262
- reader.readAsDataURL(file);
263
- }
264
- });
265
-
266
- // Preview selected videos
267
- document.getElementById("videoInput").addEventListener("change", function() {
268
- const files = this.files;
269
- const preview = document.getElementById("mediaPreview");
270
- preview.innerHTML = "";
271
-
272
- for (const file of files) {
273
- const reader = new FileReader();
274
- reader.onload = () => {
275
- const video = document.createElement("video");
276
- video.src = reader.result;
277
- video.title = file.name;
278
- video.controls = true;
279
- video.muted = true;
280
- preview.appendChild(video);
281
- };
282
- reader.readAsDataURL(file);
283
- }
284
- });
285
-
286
- // Allow Enter key to send message
287
- document.getElementById("chat-input").addEventListener("keydown", function(event) {
288
- if (event.key === "Enter") {
289
- event.preventDefault();
290
- sendMessage();
291
- }
292
- });
293
-
294
- // Listen for new messages
295
- const chatBox = document.getElementById("chat-box");
296
- let messagesListener = null;
297
-
298
- function listenToMessages() {
299
- // Remove previous listener
300
- if (messagesListener) {
301
- messagesListener.off();
302
- }
303
-
304
- // Clear chat box
305
- chatBox.innerHTML = "";
306
-
307
- // Listen to current room messages
308
- messagesListener = db.ref(`rooms/${currentRoomId}/messages`);
309
- messagesListener.on("child_added", snapshot => {
310
- const msg = snapshot.val();
311
- const div = document.createElement("div");
312
- div.className = "message " + (msg.uid === auth.currentUser?.uid ? "mine" : "other");
313
-
314
- let content = `<strong>${msg.name}:</strong><br>`;
315
-
316
- // Add text if exists
317
- if (msg.text) {
318
- content += `<span>${msg.text}</span>`;
319
- }
320
-
321
- // Add image if exists
322
- if (msg.image) {
323
- content += `<br><a href="${msg.image}" target="_blank">
324
- <img src="${msg.image}" alt="Image" />
325
- </a>`;
326
- }
327
-
328
- // Add video if exists
329
- if (msg.video) {
330
- content += `<br><video controls>
331
- <source src="${msg.video}" type="video/mp4">
332
- <source src="${msg.video}" type="video/webm">
333
- Your browser does not support the video tag.
334
- </video>`;
335
- }
336
-
337
- div.innerHTML = content;
338
- chatBox.appendChild(div);
339
- chatBox.scrollTop = chatBox.scrollHeight;
340
- });
341
- }
342
-
343
- // Room management functions
344
- function initializeRooms() {
345
- // Create general room if not exists
346
- db.ref('rooms/general').once('value', snapshot => {
347
- if (!snapshot.exists()) {
348
- db.ref('rooms/general').set({
349
- name: "Room chung",
350
- description: "Phòng chat chung cho tất cả mọi người",
351
- createdBy: auth.currentUser.uid,
352
- createdAt: Date.now(),
353
- members: {
354
- [auth.currentUser.uid]: {
355
- name: auth.currentUser.displayName || auth.currentUser.email,
356
- joinedAt: Date.now()
357
- }
358
- }
359
- });
360
- } else {
361
- // Add current user to general room if not already member
362
- db.ref(`rooms/general/members/${auth.currentUser.uid}`).set({
363
- name: auth.currentUser.displayName || auth.currentUser.email,
364
- joinedAt: Date.now()
365
- });
366
- }
367
- });
368
-
369
- // Switch to general room
370
- switchToRoom("general", "Room chung");
371
- }
372
-
373
- function loadUserRooms() {
374
- const roomList = document.getElementById("room-list");
375
-
376
- // Listen for rooms where user is a member
377
- db.ref('rooms').on('value', snapshot => {
378
- roomList.innerHTML = "";
379
- const rooms = snapshot.val();
380
-
381
- if (rooms) {
382
- Object.keys(rooms).forEach(roomId => {
383
- const room = rooms[roomId];
384
- if (room.members && room.members[auth.currentUser.uid]) {
385
- createRoomListItem(roomId, room);
386
- }
387
- });
388
- }
389
- });
390
- }
391
-
392
- function createRoomListItem(roomId, room) {
393
- const roomList = document.getElementById("room-list");
394
- const roomItem = document.createElement("div");
395
- roomItem.className = `room-item ${roomId === currentRoomId ? 'active' : ''}`;
396
- roomItem.dataset.roomId = roomId;
397
- roomItem.onclick = () => switchToRoom(roomId, room.name);
398
-
399
- roomItem.innerHTML = `
400
- <div class="room-info">
401
- <div class="room-name">${room.name}</div>
402
- <div class="room-last-message">${room.lastMessage || "Chưa có tin nhắn"}</div>
403
- </div>
404
- `;
405
-
406
- roomList.appendChild(roomItem);
407
- }
408
-
409
- function switchToRoom(roomId, roomName) {
410
- currentRoomId = roomId;
411
- document.getElementById("current-room-name").textContent = roomName;
412
-
413
- // Update active room in UI
414
- document.querySelectorAll(".room-item").forEach(item => {
415
- item.classList.remove("active");
416
- });
417
-
418
- // Find and activate current room by checking data attribute
419
- document.querySelectorAll(".room-item").forEach(item => {
420
- if (item.dataset.roomId === roomId) {
421
- item.classList.add("active");
422
- }
423
- });
424
-
425
- // Load messages for this room
426
- listenToMessages();
427
- }
428
-
429
- function updateRoomLastMessage(roomId, message) {
430
- db.ref(`rooms/${roomId}/lastMessage`).set(message);
431
- db.ref(`rooms/${roomId}/lastMessageTime`).set(Date.now());
432
- }
433
-
434
- function createRoom() {
435
- const roomName = prompt("Nhập tên phòng chat:");
436
- if (!roomName || !roomName.trim()) return;
437
-
438
- const roomDescription = prompt("Nhập mô tả phòng (tùy chọn):") || `Phòng chat ${roomName.trim()}`;
439
-
440
- const roomId = 'room_' + Date.now();
441
- db.ref(`rooms/${roomId}`).set({
442
- name: roomName.trim(),
443
- description: roomDescription.trim(),
444
- createdBy: auth.currentUser.uid,
445
- createdAt: Date.now(),
446
- members: {
447
- [auth.currentUser.uid]: {
448
- name: auth.currentUser.displayName || auth.currentUser.email,
449
- joinedAt: Date.now()
450
- }
451
- }
452
- }).then(() => {
453
- switchToRoom(roomId, roomName.trim());
454
- alert(`Đã tạo phòng "${roomName.trim()}" thành công!`);
455
- });
456
- }
457
-
458
- function setupRoomListeners() {
459
- // Room list toggle
460
- document.getElementById("roomListToggle").addEventListener("click", () => {
461
- const sidebar = document.getElementById("room-sidebar");
462
- sidebar.classList.toggle("show");
463
- });
464
-
465
- // Create room button
466
- document.getElementById("createRoomBtn").addEventListener("click", createRoom);
467
-
468
- // Join room button
469
- document.getElementById("joinRoomBtn").addEventListener("click", showJoinRoomDialog);
470
-
471
- // Room search functionality
472
- const searchInput = document.getElementById("roomSearchInput");
473
- searchInput.addEventListener("input", handleRoomSearch);
474
- searchInput.addEventListener("focus", () => {
475
- if (searchInput.value.trim()) {
476
- document.getElementById("search-results").classList.remove("hidden");
477
- }
478
- });
479
-
480
- // Hide search results when clicking outside
481
- document.addEventListener("click", (event) => {
482
- const sidebar = document.getElementById("room-sidebar");
483
- const searchResults = document.getElementById("search-results");
484
-
485
- if (!sidebar.contains(event.target)) {
486
- searchResults.classList.add("hidden");
487
- }
488
- });
489
- }
490
-
491
- // Room search functionality
492
- function handleRoomSearch() {
493
- const searchTerm = document.getElementById("roomSearchInput").value.trim().toLowerCase();
494
- const searchResults = document.getElementById("search-results");
495
- const searchRoomList = document.getElementById("search-room-list");
496
-
497
- if (!searchTerm) {
498
- searchResults.classList.add("hidden");
499
- return;
500
- }
501
-
502
- searchResults.classList.remove("hidden");
503
- searchRoomList.innerHTML = "";
504
-
505
- // Search all rooms in database
506
- db.ref('rooms').once('value', snapshot => {
507
- const rooms = snapshot.val();
508
- let foundRooms = [];
509
-
510
- if (rooms) {
511
- Object.keys(rooms).forEach(roomId => {
512
- const room = rooms[roomId];
513
- if (room.name && room.name.toLowerCase().includes(searchTerm)) {
514
- foundRooms.push({ id: roomId, ...room });
515
- }
516
- });
517
- }
518
-
519
- if (foundRooms.length === 0) {
520
- searchRoomList.innerHTML = '<div class="no-results">Không tìm thấy phòng nào</div>';
521
- } else {
522
- foundRooms.forEach(room => {
523
- createSearchResultItem(room.id, room);
524
- });
525
- }
526
- });
527
- }
528
-
529
- function createSearchResultItem(roomId, room) {
530
- const searchRoomList = document.getElementById("search-room-list");
531
- const roomItem = document.createElement("div");
532
- const isMember = room.members && room.members[auth.currentUser.uid];
533
-
534
- roomItem.className = `room-item search-result`;
535
- roomItem.dataset.roomId = roomId;
536
-
537
- // Count members
538
- const memberCount = room.members ? Object.keys(room.members).length : 0;
539
-
540
- roomItem.innerHTML = `
541
- <div class="room-info">
542
- <div class="room-name">${room.name}</div>
543
- <div class="room-last-message">${room.description || "Không có mô tả"}</div>
544
- <div class="room-member-count">${memberCount} thành viên</div>
545
- </div>
546
- ${isMember ?
547
- `<button class="room-join-btn" onclick="switchToRoom('${roomId}', '${room.name}'); hideSearchResults();">Vào phòng</button>` :
548
- `<button class="room-join-btn" onclick="joinRoom('${roomId}', '${room.name}')">Tham gia</button>`
549
- }
550
- `;
551
-
552
- searchRoomList.appendChild(roomItem);
553
- }
554
-
555
- function joinRoom(roomId, roomName) {
556
- // Add user to room members
557
- db.ref(`rooms/${roomId}/members/${auth.currentUser.uid}`).set({
558
- name: auth.currentUser.displayName || auth.currentUser.email,
559
- joinedAt: Date.now()
560
- }).then(() => {
561
- // Switch to the joined room
562
- switchToRoom(roomId, roomName);
563
- hideSearchResults();
564
- alert(`Đã tham gia phòng "${roomName}" thành công!`);
565
- }).catch(error => {
566
- console.error("Error joining room:", error);
567
- alert("Lỗi khi tham gia phòng!");
568
- });
569
- }
570
-
571
- function hideSearchResults() {
572
- document.getElementById("search-results").classList.add("hidden");
573
- document.getElementById("roomSearchInput").value = "";
574
- }
575
-
576
- function showJoinRoomDialog() {
577
- const roomId = prompt("Nhập ID phòng muốn tham gia:");
578
- if (!roomId || !roomId.trim()) return;
579
-
580
- // Check if room exists
581
- db.ref(`rooms/${roomId}`).once('value', snapshot => {
582
- if (snapshot.exists()) {
583
- const room = snapshot.val();
584
- joinRoom(roomId, room.name);
585
- } else {
586
- alert("Không tìm thấy phòng với ID này!");
587
- }
588
- });
589
- }
 
1
+ // Firebase configuration
2
+ const firebaseConfig = {
3
+ apiKey: "AIzaSyDN6tU7Ln3JgeFP7jTprAjSgXDfzunDGQI",
4
+ authDomain: "gay-db7b1.firebaseapp.com",
5
+ databaseURL: "https://gay-db7b1-default-rtdb.firebaseio.com",
6
+ projectId: "gay-db7b1",
7
+ storageBucket: "gay-db7b1.appspot.com",
8
+ messagingSenderId: "959507085021",
9
+ appId: "1:959507085021:web:755901093c2c81d0fb4d34",
10
+ measurementId: "G-1900F4D48J"
11
+ };
12
+
13
+ // Initialize Firebase
14
+ firebase.initializeApp(firebaseConfig);
15
+ const auth = firebase.auth();
16
+ const db = firebase.database();
17
+
18
+ // Global variables
19
+ let currentRoomId = "general";
20
+ let currentUser = null;
21
+
22
+ // DOM elements
23
+ const loginForm = document.getElementById("login-form");
24
+ const registerForm = document.getElementById("register-form");
25
+ const toggleAuth = document.getElementById("toggle-auth");
26
+ const authTitle = document.getElementById("auth-title");
27
+
28
+ // Toggle between login and register forms
29
+ toggleAuth.addEventListener("click", () => {
30
+ loginForm.classList.toggle("hidden");
31
+ registerForm.classList.toggle("hidden");
32
+ authTitle.textContent = loginForm.classList.contains("hidden") ? "Đăng ký" : "Đăng nhập";
33
+ toggleAuth.textContent = loginForm.classList.contains("hidden") ? "Đã có tài khoản? Đăng nhập" : "Chưa có tài khoản? Đăng ký";
34
+ });
35
+
36
+ // Register form handler
37
+ registerForm.addEventListener("submit", (e) => {
38
+ e.preventDefault();
39
+ const username = document.getElementById("register-username").value;
40
+ const email = document.getElementById("register-email").value;
41
+ const password = document.getElementById("register-password").value;
42
+
43
+ auth.createUserWithEmailAndPassword(email, password).then(userCredential => {
44
+ return userCredential.user.updateProfile({ displayName: username });
45
+ }).then(() => {
46
+ document.getElementById("display-name").textContent = auth.currentUser.displayName;
47
+ showChat();
48
+ }).catch(error => alert(error.message));
49
+ });
50
+
51
+ // Login form handler
52
+ loginForm.addEventListener("submit", (e) => {
53
+ e.preventDefault();
54
+ const email = document.getElementById("login-email").value;
55
+ const password = document.getElementById("login-password").value;
56
+
57
+ auth.signInWithEmailAndPassword(email, password).then(() => {
58
+ document.getElementById("display-name").textContent = auth.currentUser.displayName || auth.currentUser.email;
59
+ showChat();
60
+ }).catch(error => alert(error.message));
61
+ });
62
+
63
+ // Google login handler
64
+ document.getElementById("google-login").addEventListener("click", () => {
65
+ const provider = new firebase.auth.GoogleAuthProvider();
66
+ auth.signInWithPopup(provider).then(() => {
67
+ document.getElementById("display-name").textContent = auth.currentUser.displayName;
68
+ showChat();
69
+ }).catch(error => alert(error.message));
70
+ });
71
+
72
+ // Show chat section
73
+ function showChat() {
74
+ document.getElementById("auth-section").classList.add("hidden");
75
+ document.getElementById("chat-section").classList.remove("hidden");
76
+ currentUser = auth.currentUser;
77
+
78
+ // Initialize room functionality
79
+ initializeRooms();
80
+ loadUserRooms();
81
+ setupRoomListeners();
82
+ }
83
+
84
+ // Send message function
85
+ function sendMessage() {
86
+ const input = document.getElementById("chat-input");
87
+ const imageInput = document.getElementById("imageInput");
88
+ const videoInput = document.getElementById("videoInput");
89
+ const text = input.value.trim();
90
+ const images = imageInput.files;
91
+ const videos = videoInput.files;
92
+
93
+ if (!text && images.length === 0 && videos.length === 0) return;
94
+
95
+ // Send text message if exists
96
+ if (text) {
97
+ db.ref(`rooms/${currentRoomId}/messages`).push({
98
+ name: auth.currentUser.displayName || auth.currentUser.email,
99
+ text: text,
100
+ uid: auth.currentUser.uid,
101
+ timestamp: Date.now()
102
+ });
103
+
104
+ // Update room last message
105
+ updateRoomLastMessage(currentRoomId, text);
106
+ }
107
+
108
+ // Send images
109
+ if (images.length > 0) {
110
+ sendImages(images);
111
+ }
112
+
113
+ // Send videos
114
+ if (videos.length > 0) {
115
+ sendVideos(videos);
116
+ }
117
+
118
+ // Clear inputs
119
+ input.value = "";
120
+ imageInput.value = "";
121
+ videoInput.value = "";
122
+ document.getElementById("mediaPreview").innerHTML = "";
123
+ }
124
+
125
+ // Send images function
126
+ async function sendImages(files) {
127
+ for (const file of files) {
128
+ try {
129
+ const base64 = await toBase64(file);
130
+ const imageUrl = await uploadToImgbb(base64);
131
+ if (imageUrl) {
132
+ db.ref(`rooms/${currentRoomId}/messages`).push({
133
+ name: auth.currentUser.displayName || auth.currentUser.email,
134
+ text: "",
135
+ image: imageUrl,
136
+ uid: auth.currentUser.uid,
137
+ timestamp: Date.now()
138
+ });
139
+
140
+ // Update room last message
141
+ updateRoomLastMessage(currentRoomId, "📷 Hình ảnh");
142
+ }
143
+ } catch (error) {
144
+ console.error("Error uploading image:", error);
145
+ alert("Lỗi upload ảnh!");
146
+ }
147
+ }
148
+ }
149
+
150
+ // Send videos function
151
+ async function sendVideos(files) {
152
+ for (const file of files) {
153
+ try {
154
+ showUploadProgress("Đang upload video...");
155
+ const videoUrl = await uploadVideo(file);
156
+ hideUploadProgress();
157
+ if (videoUrl) {
158
+ db.ref(`rooms/${currentRoomId}/messages`).push({
159
+ name: auth.currentUser.displayName || auth.currentUser.email,
160
+ text: "",
161
+ video: videoUrl,
162
+ uid: auth.currentUser.uid,
163
+ timestamp: Date.now()
164
+ });
165
+
166
+ // Update room last message
167
+ updateRoomLastMessage(currentRoomId, "🎥 Video");
168
+ }
169
+ } catch (error) {
170
+ hideUploadProgress();
171
+ console.error("Error uploading video:", error);
172
+ alert("Lỗi upload video!");
173
+ }
174
+ }
175
+ }
176
+
177
+ // Convert file to base64
178
+ function toBase64(file) {
179
+ return new Promise((resolve, reject) => {
180
+ const reader = new FileReader();
181
+ reader.onloadend = () => resolve(reader.result.split(',')[1]);
182
+ reader.onerror = reject;
183
+ reader.readAsDataURL(file);
184
+ });
185
+ }
186
+
187
+ // Upload image to imgbb
188
+ async function uploadToImgbb(base64) {
189
+ const apiKey = "eb64cc8f94a115e3a412694f2a0f10b3";
190
+ const formData = new FormData();
191
+ formData.append("key", apiKey);
192
+ formData.append("image", base64);
193
+
194
+ try {
195
+ const response = await fetch("https://api.imgbb.com/1/upload", {
196
+ method: "POST",
197
+ body: formData
198
+ });
199
+ const result = await response.json();
200
+ return result.data.url;
201
+ } catch (error) {
202
+ console.error("Error uploading to imgbb:", error);
203
+ return null;
204
+ }
205
+ }
206
+
207
+ // Upload video to server
208
+ async function uploadVideo(file) {
209
+ const formData = new FormData();
210
+ formData.append("file", file);
211
+
212
+ try {
213
+ const response = await fetch("http://192.168.2.47:5000/upload", {
214
+ method: "POST",
215
+ body: formData,
216
+ });
217
+
218
+ const result = await response.json();
219
+
220
+ // Check if upload was successful
221
+ if (result.status === "success" && result.data && result.data.url) {
222
+ return result.data.url;
223
+ } else {
224
+ console.error("Upload failed:", result);
225
+ return null;
226
+ }
227
+ } catch (error) {
228
+ console.error("Error uploading video:", error);
229
+ return null;
230
+ }
231
+ }
232
+
233
+ // Show upload progress
234
+ function showUploadProgress(message) {
235
+ const preview = document.getElementById("mediaPreview");
236
+ preview.innerHTML = `
237
+ <div class="upload-progress">
238
+ <div class="upload-progress-bar" style="width: 100%">${message}</div>
239
+ </div>
240
+ `;
241
+ }
242
+
243
+ // Hide upload progress
244
+ function hideUploadProgress() {
245
+ document.getElementById("mediaPreview").innerHTML = "";
246
+ }
247
+
248
+ // Preview selected images
249
+ document.getElementById("imageInput").addEventListener("change", function() {
250
+ const files = this.files;
251
+ const preview = document.getElementById("mediaPreview");
252
+ preview.innerHTML = "";
253
+
254
+ for (const file of files) {
255
+ const reader = new FileReader();
256
+ reader.onload = () => {
257
+ const img = document.createElement("img");
258
+ img.src = reader.result;
259
+ img.title = file.name;
260
+ preview.appendChild(img);
261
+ };
262
+ reader.readAsDataURL(file);
263
+ }
264
+ });
265
+
266
+ // Preview selected videos
267
+ document.getElementById("videoInput").addEventListener("change", function() {
268
+ const files = this.files;
269
+ const preview = document.getElementById("mediaPreview");
270
+ preview.innerHTML = "";
271
+
272
+ for (const file of files) {
273
+ const reader = new FileReader();
274
+ reader.onload = () => {
275
+ const video = document.createElement("video");
276
+ video.src = reader.result;
277
+ video.title = file.name;
278
+ video.controls = true;
279
+ video.muted = true;
280
+ preview.appendChild(video);
281
+ };
282
+ reader.readAsDataURL(file);
283
+ }
284
+ });
285
+
286
+ // Allow Enter key to send message
287
+ document.getElementById("chat-input").addEventListener("keydown", function(event) {
288
+ if (event.key === "Enter") {
289
+ event.preventDefault();
290
+ sendMessage();
291
+ }
292
+ });
293
+
294
+ // Listen for new messages
295
+ const chatBox = document.getElementById("chat-box");
296
+ let messagesListener = null;
297
+
298
+ function listenToMessages() {
299
+ // Remove previous listener
300
+ if (messagesListener) {
301
+ messagesListener.off();
302
+ }
303
+
304
+ // Clear chat box
305
+ chatBox.innerHTML = "";
306
+
307
+ // Listen to current room messages
308
+ messagesListener = db.ref(`rooms/${currentRoomId}/messages`);
309
+ messagesListener.on("child_added", snapshot => {
310
+ const msg = snapshot.val();
311
+ const div = document.createElement("div");
312
+ div.className = "message " + (msg.uid === auth.currentUser?.uid ? "mine" : "other");
313
+
314
+ let content = `<strong>${msg.name}:</strong><br>`;
315
+
316
+ // Add text if exists
317
+ if (msg.text) {
318
+ content += `<span>${msg.text}</span>`;
319
+ }
320
+
321
+ // Add image if exists
322
+ if (msg.image) {
323
+ content += `<br><a href="${msg.image}" target="_blank">
324
+ <img src="${msg.image}" alt="Image" />
325
+ </a>`;
326
+ }
327
+
328
+ // Add video if exists
329
+ if (msg.video) {
330
+ content += `<br><video controls>
331
+ <source src="${msg.video}" type="video/mp4">
332
+ <source src="${msg.video}" type="video/webm">
333
+ Your browser does not support the video tag.
334
+ </video>`;
335
+ }
336
+
337
+ div.innerHTML = content;
338
+ chatBox.appendChild(div);
339
+ chatBox.scrollTop = chatBox.scrollHeight;
340
+ });
341
+ }
342
+
343
+ // Room management functions
344
+ function initializeRooms() {
345
+ // Create general room if not exists
346
+ db.ref('rooms/general').once('value', snapshot => {
347
+ if (!snapshot.exists()) {
348
+ db.ref('rooms/general').set({
349
+ name: "Room chung",
350
+ description: "Phòng chat chung cho tất cả mọi người",
351
+ createdBy: auth.currentUser.uid,
352
+ createdAt: Date.now(),
353
+ members: {
354
+ [auth.currentUser.uid]: {
355
+ name: auth.currentUser.displayName || auth.currentUser.email,
356
+ joinedAt: Date.now()
357
+ }
358
+ }
359
+ });
360
+ } else {
361
+ // Add current user to general room if not already member
362
+ db.ref(`rooms/general/members/${auth.currentUser.uid}`).set({
363
+ name: auth.currentUser.displayName || auth.currentUser.email,
364
+ joinedAt: Date.now()
365
+ });
366
+ }
367
+ });
368
+
369
+ // Switch to general room
370
+ switchToRoom("general", "Room chung");
371
+ }
372
+
373
+ function loadUserRooms() {
374
+ const roomList = document.getElementById("room-list");
375
+
376
+ // Listen for rooms where user is a member
377
+ db.ref('rooms').on('value', snapshot => {
378
+ roomList.innerHTML = "";
379
+ const rooms = snapshot.val();
380
+
381
+ if (rooms) {
382
+ Object.keys(rooms).forEach(roomId => {
383
+ const room = rooms[roomId];
384
+ if (room.members && room.members[auth.currentUser.uid]) {
385
+ createRoomListItem(roomId, room);
386
+ }
387
+ });
388
+ }
389
+ });
390
+ }
391
+
392
+ function createRoomListItem(roomId, room) {
393
+ const roomList = document.getElementById("room-list");
394
+ const roomItem = document.createElement("div");
395
+ roomItem.className = `room-item ${roomId === currentRoomId ? 'active' : ''}`;
396
+ roomItem.dataset.roomId = roomId;
397
+ roomItem.onclick = () => switchToRoom(roomId, room.name);
398
+
399
+ roomItem.innerHTML = `
400
+ <div class="room-info">
401
+ <div class="room-name">${room.name}</div>
402
+ <div class="room-last-message">${room.lastMessage || "Chưa có tin nhắn"}</div>
403
+ </div>
404
+ `;
405
+
406
+ roomList.appendChild(roomItem);
407
+ }
408
+
409
+ function switchToRoom(roomId, roomName) {
410
+ currentRoomId = roomId;
411
+ document.getElementById("current-room-name").textContent = roomName;
412
+
413
+ // Update active room in UI
414
+ document.querySelectorAll(".room-item").forEach(item => {
415
+ item.classList.remove("active");
416
+ });
417
+
418
+ // Find and activate current room by checking data attribute
419
+ document.querySelectorAll(".room-item").forEach(item => {
420
+ if (item.dataset.roomId === roomId) {
421
+ item.classList.add("active");
422
+ }
423
+ });
424
+
425
+ // Load messages for this room
426
+ listenToMessages();
427
+ }
428
+
429
+ function updateRoomLastMessage(roomId, message) {
430
+ db.ref(`rooms/${roomId}/lastMessage`).set(message);
431
+ db.ref(`rooms/${roomId}/lastMessageTime`).set(Date.now());
432
+ }
433
+
434
+ function createRoom() {
435
+ const roomName = prompt("Nhập tên phòng chat:");
436
+ if (!roomName || !roomName.trim()) return;
437
+
438
+ const roomDescription = prompt("Nhập mô tả phòng (tùy chọn):") || `Phòng chat ${roomName.trim()}`;
439
+
440
+ const roomId = 'room_' + Date.now();
441
+ db.ref(`rooms/${roomId}`).set({
442
+ name: roomName.trim(),
443
+ description: roomDescription.trim(),
444
+ createdBy: auth.currentUser.uid,
445
+ createdAt: Date.now(),
446
+ members: {
447
+ [auth.currentUser.uid]: {
448
+ name: auth.currentUser.displayName || auth.currentUser.email,
449
+ joinedAt: Date.now()
450
+ }
451
+ }
452
+ }).then(() => {
453
+ switchToRoom(roomId, roomName.trim());
454
+ alert(`Đã tạo phòng "${roomName.trim()}" thành công!`);
455
+ });
456
+ }
457
+
458
+ function setupRoomListeners() {
459
+ // Room list toggle
460
+ document.getElementById("roomListToggle").addEventListener("click", () => {
461
+ const sidebar = document.getElementById("room-sidebar");
462
+ sidebar.classList.toggle("show");
463
+ });
464
+
465
+ // Create room button
466
+ document.getElementById("createRoomBtn").addEventListener("click", createRoom);
467
+
468
+ // Join room button
469
+ document.getElementById("joinRoomBtn").addEventListener("click", showJoinRoomDialog);
470
+
471
+ // Room search functionality
472
+ const searchInput = document.getElementById("roomSearchInput");
473
+ searchInput.addEventListener("input", handleRoomSearch);
474
+ searchInput.addEventListener("focus", () => {
475
+ if (searchInput.value.trim()) {
476
+ document.getElementById("search-results").classList.remove("hidden");
477
+ }
478
+ });
479
+
480
+ // Hide search results when clicking outside
481
+ document.addEventListener("click", (event) => {
482
+ const sidebar = document.getElementById("room-sidebar");
483
+ const searchResults = document.getElementById("search-results");
484
+
485
+ if (!sidebar.contains(event.target)) {
486
+ searchResults.classList.add("hidden");
487
+ }
488
+ });
489
+ }
490
+
491
+ // Room search functionality
492
+ function handleRoomSearch() {
493
+ const searchTerm = document.getElementById("roomSearchInput").value.trim().toLowerCase();
494
+ const searchResults = document.getElementById("search-results");
495
+ const searchRoomList = document.getElementById("search-room-list");
496
+
497
+ if (!searchTerm) {
498
+ searchResults.classList.add("hidden");
499
+ return;
500
+ }
501
+
502
+ searchResults.classList.remove("hidden");
503
+ searchRoomList.innerHTML = "";
504
+
505
+ // Search all rooms in database
506
+ db.ref('rooms').once('value', snapshot => {
507
+ const rooms = snapshot.val();
508
+ let foundRooms = [];
509
+
510
+ if (rooms) {
511
+ Object.keys(rooms).forEach(roomId => {
512
+ const room = rooms[roomId];
513
+ if (room.name && room.name.toLowerCase().includes(searchTerm)) {
514
+ foundRooms.push({ id: roomId, ...room });
515
+ }
516
+ });
517
+ }
518
+
519
+ if (foundRooms.length === 0) {
520
+ searchRoomList.innerHTML = '<div class="no-results">Không tìm thấy phòng nào</div>';
521
+ } else {
522
+ foundRooms.forEach(room => {
523
+ createSearchResultItem(room.id, room);
524
+ });
525
+ }
526
+ });
527
+ }
528
+
529
+ function createSearchResultItem(roomId, room) {
530
+ const searchRoomList = document.getElementById("search-room-list");
531
+ const roomItem = document.createElement("div");
532
+ const isMember = room.members && room.members[auth.currentUser.uid];
533
+
534
+ roomItem.className = `room-item search-result`;
535
+ roomItem.dataset.roomId = roomId;
536
+
537
+ // Count members
538
+ const memberCount = room.members ? Object.keys(room.members).length : 0;
539
+
540
+ roomItem.innerHTML = `
541
+ <div class="room-info">
542
+ <div class="room-name">${room.name}</div>
543
+ <div class="room-last-message">${room.description || "Không có mô tả"}</div>
544
+ <div class="room-member-count">${memberCount} thành viên</div>
545
+ </div>
546
+ ${isMember ?
547
+ `<button class="room-join-btn" onclick="switchToRoom('${roomId}', '${room.name}'); hideSearchResults();">Vào phòng</button>` :
548
+ `<button class="room-join-btn" onclick="joinRoom('${roomId}', '${room.name}')">Tham gia</button>`
549
+ }
550
+ `;
551
+
552
+ searchRoomList.appendChild(roomItem);
553
+ }
554
+
555
+ function joinRoom(roomId, roomName) {
556
+ // Add user to room members
557
+ db.ref(`rooms/${roomId}/members/${auth.currentUser.uid}`).set({
558
+ name: auth.currentUser.displayName || auth.currentUser.email,
559
+ joinedAt: Date.now()
560
+ }).then(() => {
561
+ // Switch to the joined room
562
+ switchToRoom(roomId, roomName);
563
+ hideSearchResults();
564
+ alert(`Đã tham gia phòng "${roomName}" thành công!`);
565
+ }).catch(error => {
566
+ console.error("Error joining room:", error);
567
+ alert("Lỗi khi tham gia phòng!");
568
+ });
569
+ }
570
+
571
+ function hideSearchResults() {
572
+ document.getElementById("search-results").classList.add("hidden");
573
+ document.getElementById("roomSearchInput").value = "";
574
+ }
575
+
576
+ function showJoinRoomDialog() {
577
+ const roomId = prompt("Nhập ID phòng muốn tham gia:");
578
+ if (!roomId || !roomId.trim()) return;
579
+
580
+ // Check if room exists
581
+ db.ref(`rooms/${roomId}`).once('value', snapshot => {
582
+ if (snapshot.exists()) {
583
+ const room = snapshot.val();
584
+ joinRoom(roomId, room.name);
585
+ } else {
586
+ alert("Không tìm thấy phòng với ID này!");
587
+ }
588
+ });
589
+ }