Spaces:
Running
Running
| <html lang="vi"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Messenger Chat</title> | |
| <script src="https://www.gstatic.com/firebasejs/10.12.2/firebase-app-compat.js"></script> | |
| <script src="https://www.gstatic.com/firebasejs/10.12.2/firebase-database-compat.js"></script> | |
| <style> | |
| * { box-sizing: border-box; } | |
| body { | |
| font-family: Arial, sans-serif; | |
| background: #f0f2f5; | |
| margin: 0; | |
| padding: 0; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| height: 100vh; | |
| } | |
| #chat-container { | |
| background: #fff; | |
| width: 100%; | |
| max-width: 500px; | |
| height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| border-radius: 10px; | |
| overflow: hidden; | |
| box-shadow: 0 2px 8px rgba(0,0,0,0.15); | |
| } | |
| #header { | |
| background: #0084ff; | |
| color: white; | |
| padding: 15px; | |
| text-align: center; | |
| font-weight: bold; | |
| font-size: 18px; | |
| } | |
| #output { | |
| flex: 1; | |
| padding: 15px; | |
| overflow-y: auto; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 8px; | |
| background: #e5ddd5; | |
| } | |
| .message { | |
| max-width: 75%; | |
| padding: 10px 14px; | |
| border-radius: 18px; | |
| font-size: 15px; | |
| word-wrap: break-word; | |
| position: relative; | |
| } | |
| .my-message { | |
| align-self: flex-end; | |
| background: #0084ff; | |
| color: white; | |
| border-bottom-right-radius: 4px; | |
| } | |
| .other-message { | |
| align-self: flex-start; | |
| background: #e4e6eb; | |
| color: black; | |
| border-bottom-left-radius: 4px; | |
| } | |
| .message img { | |
| max-width: 200px; | |
| border-radius: 12px; | |
| display: block; | |
| margin-top: 6px; | |
| } | |
| #input-area { | |
| display: flex; | |
| align-items: center; | |
| border-top: 1px solid #ccc; | |
| padding: 10px; | |
| background: white; | |
| gap: 10px; | |
| } | |
| #chat { | |
| flex: 1; | |
| padding: 10px 14px; | |
| font-size: 16px; | |
| border: 1px solid #ccc; | |
| border-radius: 20px; | |
| outline: none; | |
| } | |
| .icon-btn { | |
| background: none; | |
| border: none; | |
| cursor: pointer; | |
| font-size: 22px; | |
| color: #0084ff; | |
| } | |
| .icon-btn:hover { | |
| color: #005bb5; | |
| } | |
| #fileInput { | |
| display: none; | |
| } | |
| /* Preview trạng thái gửi */ | |
| .sending { | |
| opacity: 0.6; | |
| position: relative; | |
| } | |
| .sending::after { | |
| content: "Đang gửi..."; | |
| font-size: 12px; | |
| color: gray; | |
| display: block; | |
| margin-top: 4px; | |
| text-align: right; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="chat-container"> | |
| <div id="header">Messenger Chat</div> | |
| <div id="output"></div> | |
| <div id="input-area"> | |
| <button class="icon-btn" onclick="document.getElementById('fileInput').click()">📷</button> | |
| <input type="file" id="fileInput" accept="image/*"> | |
| <input type="text" id="chat" placeholder="Aa"> | |
| <button class="icon-btn" onclick="sendText()">➤</button> | |
| </div> | |
| </div> | |
| <script> | |
| // Firebase config | |
| const firebaseConfig = { | |
| apiKey: "AIzaSyCERsSDmnicIJ2HFGfSDSWR4dF89JsVt0g", | |
| authDomain: "minh-project-44548.firebaseapp.com", | |
| databaseURL: "https://minh-project-44548-default-rtdb.asia-southeast1.firebasedatabase.app", | |
| projectId: "minh-project-44548", | |
| storageBucket: "minh-project-44548.firebasestorage.app", | |
| messagingSenderId: "717104512164", | |
| appId: "1:717104512164:web:d43a26cb292ae153e57a31" | |
| }; | |
| firebase.initializeApp(firebaseConfig); | |
| const database = firebase.database(); | |
| let currentUser = ""; | |
| while (!currentUser) { | |
| currentUser = prompt("Nhập tên của bạn:"); | |
| if (currentUser) currentUser = currentUser.trim(); | |
| } | |
| const output = document.getElementById("output"); | |
| // ✅ Gửi text | |
| function sendText() { | |
| const chat = document.getElementById("chat").value.trim(); | |
| if (chat === "") return; | |
| // Hiển thị tạm trước | |
| const previewMsg = document.createElement("div"); | |
| previewMsg.classList.add("message", "my-message", "sending"); | |
| previewMsg.textContent = chat; | |
| output.appendChild(previewMsg); | |
| output.scrollTop = output.scrollHeight; | |
| const messageId = database.ref("messages").push().key; | |
| database.ref("messages/" + messageId).set({ | |
| name: currentUser, | |
| text: chat, | |
| image: "", | |
| timestamp: Date.now() | |
| }).then(() => { | |
| // Xóa preview khi đã lưu Firebase | |
| output.removeChild(previewMsg); | |
| }); | |
| document.getElementById("chat").value = ""; | |
| } | |
| // ✅ Gửi hình ảnh với preview | |
| document.getElementById("fileInput").addEventListener("change", async function () { | |
| const file = this.files[0]; | |
| if (!file) return; | |
| // Hiển thị preview ngay | |
| const previewMsg = document.createElement("div"); | |
| previewMsg.classList.add("message", "my-message", "sending"); | |
| const imgPreview = document.createElement("img"); | |
| imgPreview.src = URL.createObjectURL(file); | |
| previewMsg.appendChild(imgPreview); | |
| output.appendChild(previewMsg); | |
| output.scrollTop = output.scrollHeight; | |
| const formData = new FormData(); | |
| formData.append("image", file); | |
| try { | |
| const response = await fetch('https://api.imgbb.com/1/upload?expiration=600&key=eb64cc8f94a115e3a412694f2a0f10b3', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const result = await response.json(); | |
| if (result.success) { | |
| const imageUrl = result.data.url; | |
| const messageId = database.ref("messages").push().key; | |
| database.ref("messages/" + messageId).set({ | |
| name: currentUser, | |
| text: "", | |
| image: imageUrl, | |
| timestamp: Date.now() | |
| }); | |
| output.removeChild(previewMsg); | |
| } else { | |
| previewMsg.textContent = "Lỗi upload!"; | |
| } | |
| } catch (error) { | |
| console.error("Lỗi upload ảnh:", error); | |
| previewMsg.textContent = "Upload thất bại!"; | |
| } | |
| this.value = ""; // reset input | |
| }); | |
| // ✅ Hiển thị tin nhắn từ Firebase | |
| database.ref('messages').orderByChild("timestamp").on('value', (snapshot) => { | |
| const data = snapshot.val(); | |
| output.innerHTML = ""; | |
| for (const key in data) { | |
| if (data.hasOwnProperty(key)) { | |
| const msg = document.createElement("div"); | |
| msg.classList.add("message"); | |
| msg.classList.add(data[key].name === currentUser ? "my-message" : "other-message"); | |
| if (data[key].text) { | |
| const chatLine = document.createElement("div"); | |
| chatLine.textContent = data[key].text; | |
| msg.appendChild(chatLine); | |
| } | |
| if (data[key].image) { | |
| const img = document.createElement("img"); | |
| img.src = data[key].image; | |
| msg.appendChild(img); | |
| } | |
| output.appendChild(msg); | |
| } | |
| } | |
| output.scrollTop = output.scrollHeight; | |
| }); | |
| // Gửi bằng Enter | |
| document.getElementById("chat").addEventListener("keypress", function (e) { | |
| if (e.key === "Enter") sendText(); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |