Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Modern Chat Interface</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
/* Custom scrollbar */ | |
.custom-scrollbar::-webkit-scrollbar { | |
width: 6px; | |
} | |
.custom-scrollbar::-webkit-scrollbar-track { | |
background: #f1f1f1; | |
border-radius: 10px; | |
} | |
.custom-scrollbar::-webkit-scrollbar-thumb { | |
background: #888; | |
border-radius: 10px; | |
} | |
.custom-scrollbar::-webkit-scrollbar-thumb:hover { | |
background: #555; | |
} | |
/* Animation for new messages */ | |
@keyframes fadeIn { | |
from { opacity: 0; transform: translateY(10px); } | |
to { opacity: 1; transform: translateY(0); } | |
} | |
.message-animation { | |
animation: fadeIn 0.3s ease-out; | |
} | |
/* Pulse animation for active users */ | |
@keyframes pulse { | |
0%, 100% { opacity: 1; } | |
50% { opacity: 0.5; } | |
} | |
.pulse-active { | |
animation: pulse 2s infinite; | |
} | |
/* Tab styling */ | |
.tab { | |
position: relative; | |
padding: 0.5rem 1rem; | |
cursor: pointer; | |
border-radius: 0.5rem 0.5rem 0 0; | |
transition: all 0.2s; | |
} | |
.tab.active { | |
background-color: white; | |
color: #4f46e5; | |
font-weight: 600; | |
} | |
.tab.active::after { | |
content: ''; | |
position: absolute; | |
bottom: -1px; | |
left: 0; | |
right: 0; | |
height: 2px; | |
background-color: #4f46e5; | |
} | |
.tab-badge { | |
position: absolute; | |
top: -0.5rem; | |
right: -0.5rem; | |
background-color: #ef4444; | |
color: white; | |
border-radius: 50%; | |
width: 1.25rem; | |
height: 1.25rem; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
font-size: 0.75rem; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-100 font-sans"> | |
<!-- Main Container --> | |
<div class="container mx-auto px-4 py-8 max-w-6xl"> | |
<!-- Login Section (shown by default) --> | |
<div id="login-section" class="bg-white rounded-xl shadow-lg p-8 max-w-md mx-auto mb-8 transition-all duration-300"> | |
<div class="text-center mb-6"> | |
<h1 class="text-3xl font-bold text-indigo-600">Welcome to ChatApp</h1> | |
<p class="text-gray-500 mt-2">Connect with people around the world</p> | |
</div> | |
<div class="space-y-4"> | |
<div> | |
<label for="username" class="block text-sm font-medium text-gray-700 mb-1">Username</label> | |
<input type="text" id="username" placeholder="Enter your username" | |
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition"> | |
</div> | |
<button id="login-btn" | |
class="w-full bg-indigo-600 text-white py-2 px-4 rounded-lg hover:bg-indigo-700 transition flex items-center justify-center"> | |
<i class="fas fa-sign-in-alt mr-2"></i> Login | |
</button> | |
</div> | |
</div> | |
<!-- Main Chat Interface (hidden by default) --> | |
<div id="chat-interface" class="hidden"> | |
<!-- Header with user info --> | |
<div class="flex justify-between items-center mb-6"> | |
<div class="flex items-center"> | |
<div class="w-10 h-10 rounded-full bg-indigo-500 flex items-center justify-center text-white font-bold text-xl mr-3" id="user-avatar"> | |
U | |
</div> | |
<div> | |
<h2 class="font-bold text-lg" id="username-display">Username</h2> | |
<p class="text-sm text-gray-500">Online</p> | |
</div> | |
</div> | |
<button id="logout-btn" class="text-gray-500 hover:text-gray-700 transition"> | |
<i class="fas fa-sign-out-alt text-xl"></i> | |
</button> | |
</div> | |
<!-- Chat tabs --> | |
<div class="flex mb-4 bg-gray-200 rounded-t-lg overflow-hidden"> | |
<div id="room-tab" class="tab active relative" data-type="room"> | |
<i class="fas fa-hashtag mr-2"></i>Rooms | |
<span id="room-notification" class="tab-badge hidden"></span> | |
</div> | |
<div id="private-tab" class="tab" data-type="private"> | |
<i class="fas fa-user-friends mr-2"></i>Private | |
<span id="private-notification" class="tab-badge hidden"></span> | |
</div> | |
</div> | |
<!-- Dual List Layout --> | |
<div id="room-section" class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6"> | |
<!-- Rooms User is In --> | |
<div class="bg-white rounded-xl shadow p-4"> | |
<div class="flex justify-between items-center mb-3"> | |
<h3 class="font-semibold text-indigo-600 flex items-center"> | |
<i class="fas fa-door-open mr-2"></i> Your Rooms | |
</h3> | |
<span class="bg-indigo-100 text-indigo-800 text-xs px-2 py-1 rounded-full" id="room-count">0</span> | |
</div> | |
<div id="user-rooms" class="space-y-2 max-h-40 overflow-y-auto custom-scrollbar"> | |
<p class="text-gray-500 text-sm italic">You haven't joined any rooms yet</p> | |
</div> | |
</div> | |
<!-- Online Users --> | |
<div class="bg-white rounded-xl shadow p-4"> | |
<div class="flex justify-between items-center mb-3"> | |
<h3 class="font-semibold text-green-600 flex items-center"> | |
<i class="fas fa-users mr-2"></i> Online Users | |
</h3> | |
<span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full" id="user-count">0</span> | |
</div> | |
<div id="online-users" class="space-y-2 max-h-40 overflow-y-auto custom-scrollbar"> | |
<p class="text-gray-500 text-sm italic">Loading users...</p> | |
</div> | |
</div> | |
</div> | |
<!-- Private chat section (hidden by default) --> | |
<div id="private-section" class="hidden mb-6"> | |
<div class="bg-white rounded-xl shadow p-4"> | |
<div class="flex justify-between items-center mb-3"> | |
<h3 class="font-semibold text-purple-600 flex items-center"> | |
<i class="fas fa-comments mr-2"></i> Private Conversations | |
</h3> | |
<span class="bg-purple-100 text-purple-800 text-xs px-2 py-1 rounded-full" id="private-count">0</span> | |
</div> | |
<div id="private-chats" class="space-y-2 max-h-40 overflow-y-auto custom-scrollbar"> | |
<p class="text-gray-500 text-sm italic">No private conversations yet</p> | |
</div> | |
</div> | |
</div> | |
<!-- Chat Area --> | |
<div class="bg-white rounded-xl shadow-lg overflow-hidden mb-6"> | |
<!-- Chat header --> | |
<div id="chat-header" class="p-4 border-b border-gray-200 bg-gray-50 flex items-center"> | |
<div id="chat-type-icon" class="text-indigo-600 mr-2"> | |
<i class="fas fa-hashtag"></i> | |
</div> | |
<h3 id="chat-title" class="font-semibold">Select a chat</h3> | |
</div> | |
<!-- Messages Display --> | |
<div id="messages-container" class="p-4 h-64 overflow-y-auto custom-scrollbar bg-gray-50"> | |
<div class="text-center text-gray-500 py-10"> | |
<i class="fas fa-comments text-4xl mb-2 text-gray-300"></i> | |
<p>No messages yet. Start the conversation!</p> | |
</div> | |
</div> | |
<!-- Message Input --> | |
<div class="p-4 border-t border-gray-200 bg-white"> | |
<div class="flex space-x-2"> | |
<input type="text" id="message-input" placeholder="Type your message here..." | |
class="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition"> | |
<button id="send-btn" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition"> | |
<i class="fas fa-paper-plane"></i> | |
</button> | |
</div> | |
</div> | |
</div> | |
<!-- Rooms Section --> | |
<div id="room-management-section" class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
<!-- Available Rooms --> | |
<div class="bg-white rounded-xl shadow p-4"> | |
<div class="flex justify-between items-center mb-3"> | |
<h3 class="font-semibold text-blue-600 flex items-center"> | |
<i class="fas fa-hashtag mr-2"></i> Available Rooms | |
</h3> | |
<span class="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full" id="available-room-count">0</span> | |
</div> | |
<div id="available-rooms" class="space-y-2 max-h-40 overflow-y-auto custom-scrollbar"> | |
<p class="text-gray-500 text-sm italic">Loading rooms...</p> | |
</div> | |
</div> | |
<!-- Add Room Section --> | |
<div class="bg-white rounded-xl shadow p-4"> | |
<h3 class="font-semibold text-purple-600 flex items-center mb-3"> | |
<i class="fas fa-plus-circle mr-2"></i> Create New Room | |
</h3> | |
<div class="flex space-x-2"> | |
<input type="text" id="new-room-input" placeholder="Enter room name" | |
class="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition"> | |
<button id="add-room-btn" class="bg-purple-600 text-white px-4 py-2 rounded-lg hover:bg-purple-700 transition"> | |
<i class="fas fa-check"></i> | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Join Room Modal --> | |
<div id="join-room-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden"> | |
<div class="bg-white rounded-xl shadow-xl p-6 max-w-sm w-full mx-4 transform transition-all duration-300 scale-95 opacity-0"> | |
<div class="flex justify-between items-center mb-4"> | |
<h3 class="font-bold text-lg">Join Room</h3> | |
<button id="close-modal-btn" class="text-gray-500 hover:text-gray-700"> | |
<i class="fas fa-times"></i> | |
</button> | |
</div> | |
<p class="mb-4">Do you want to join <span id="room-name-display" class="font-semibold">General</span>?</p> | |
<div class="flex justify-end space-x-3"> | |
<button id="cancel-join-btn" class="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-100 transition"> | |
Cancel | |
</button> | |
<button id="confirm-join-btn" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition"> | |
Join | |
</button> | |
</div> | |
</div> | |
</div> | |
<script> | |
// DOM Elements | |
const loginSection = document.getElementById('login-section'); | |
const chatInterface = document.getElementById('chat-interface'); | |
const loginBtn = document.getElementById('login-btn'); | |
const logoutBtn = document.getElementById('logout-btn'); | |
const usernameInput = document.getElementById('username'); | |
const usernameDisplay = document.getElementById('username-display'); | |
const userAvatar = document.getElementById('user-avatar'); | |
const messageInput = document.getElementById('message-input'); | |
const sendBtn = document.getElementById('send-btn'); | |
const messagesContainer = document.getElementById('messages-container'); | |
const userRooms = document.getElementById('user-rooms'); | |
const onlineUsers = document.getElementById('online-users'); | |
const availableRooms = document.getElementById('available-rooms'); | |
const newRoomInput = document.getElementById('new-room-input'); | |
const addRoomBtn = document.getElementById('add-room-btn'); | |
const joinRoomModal = document.getElementById('join-room-modal'); | |
const closeModalBtn = document.getElementById('close-modal-btn'); | |
const cancelJoinBtn = document.getElementById('cancel-join-btn'); | |
const confirmJoinBtn = document.getElementById('confirm-join-btn'); | |
const roomNameDisplay = document.getElementById('room-name-display'); | |
const roomCount = document.getElementById('room-count'); | |
const userCount = document.getElementById('user-count'); | |
const availableRoomCount = document.getElementById('available-room-count'); | |
const roomTab = document.getElementById('room-tab'); | |
const privateTab = document.getElementById('private-tab'); | |
const roomSection = document.getElementById('room-section'); | |
const privateSection = document.getElementById('private-section'); | |
const privateChats = document.getElementById('private-chats'); | |
const chatHeader = document.getElementById('chat-header'); | |
const chatTitle = document.getElementById('chat-title'); | |
const chatTypeIcon = document.getElementById('chat-type-icon'); | |
const roomManagementSection = document.getElementById('room-management-section'); | |
const roomNotification = document.getElementById('room-notification'); | |
const privateNotification = document.getElementById('private-notification'); | |
const privateCount = document.getElementById('private-count'); | |
// State | |
let currentUser = ''; | |
let currentRooms = []; | |
let allUsers = []; | |
let allRooms = ['General', 'Random', 'Help']; | |
let selectedChat = null; | |
let chatType = 'room'; // 'room' or 'private' | |
let messages = {}; | |
let privateMessages = {}; | |
let unreadCounts = { rooms: {}, private: {} }; | |
// Initialize with some sample data | |
function initializeSampleData() { | |
// Sample users | |
allUsers = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve']; | |
// Sample messages for rooms | |
messages = { | |
'General': [ | |
{ user: 'Alice', text: 'Hello everyone!', time: '10:30 AM' }, | |
{ user: 'Bob', text: 'Hi Alice! How are you?', time: '10:32 AM' } | |
], | |
'Random': [ | |
{ user: 'Charlie', text: 'Did you see that movie?', time: '9:15 AM' }, | |
{ user: 'Diana', text: 'Yes, it was amazing!', time: '9:20 AM' } | |
], | |
'Help': [ | |
{ user: 'Eve', text: 'Can someone help me with this?', time: '11:05 AM' } | |
] | |
}; | |
// Initialize private messages | |
privateMessages = {}; | |
allUsers.forEach(user => { | |
if (user !== currentUser) { | |
privateMessages[user] = []; | |
} | |
}); | |
// Initialize unread counts | |
unreadCounts = { | |
rooms: {}, | |
private: {} | |
}; | |
} | |
// Login function | |
function login() { | |
const username = usernameInput.value.trim(); | |
if (username) { | |
currentUser = username; | |
usernameDisplay.textContent = username; | |
userAvatar.textContent = username.charAt(0).toUpperCase(); | |
// Generate a random color for the avatar | |
const colors = ['bg-indigo-500', 'bg-blue-500', 'bg-green-500', 'bg-purple-500', 'bg-pink-500', 'bg-red-500', 'bg-yellow-500']; | |
const randomColor = colors[Math.floor(Math.random() * colors.length)]; | |
userAvatar.className = `w-10 h-10 rounded-full ${randomColor} flex items-center justify-center text-white font-bold text-xl mr-3`; | |
// Show chat interface and hide login | |
loginSection.classList.add('hidden'); | |
chatInterface.classList.remove('hidden'); | |
// Initialize data and UI | |
initializeSampleData(); | |
updateUI(); | |
// Add user to online users if not already there | |
if (!allUsers.includes(username)) { | |
allUsers.push(username); | |
} | |
// Focus on message input | |
messageInput.focus(); | |
} else { | |
alert('Please enter a username'); | |
} | |
} | |
// Logout function | |
function logout() { | |
currentUser = ''; | |
chatInterface.classList.add('hidden'); | |
loginSection.classList.remove('hidden'); | |
usernameInput.value = ''; | |
} | |
// Switch between room and private chat tabs | |
function switchTab(type) { | |
if (type === chatType) return; | |
chatType = type; | |
// Update tab styling | |
if (type === 'room') { | |
roomTab.classList.add('active'); | |
privateTab.classList.remove('active'); | |
roomSection.classList.remove('hidden'); | |
privateSection.classList.add('hidden'); | |
roomManagementSection.classList.remove('hidden'); | |
} else { | |
roomTab.classList.remove('active'); | |
privateTab.classList.add('active'); | |
roomSection.classList.add('hidden'); | |
privateSection.classList.remove('hidden'); | |
roomManagementSection.classList.add('hidden'); | |
} | |
// Clear selected chat when switching tabs | |
selectedChat = null; | |
updateMessages(); | |
updateChatHeader(); | |
} | |
// Update all UI elements | |
function updateUI() { | |
updateUserRooms(); | |
updateOnlineUsers(); | |
updateAvailableRooms(); | |
updatePrivateChats(); | |
updateMessages(); | |
updateChatHeader(); | |
updateNotifications(); | |
} | |
// Update the user's rooms list | |
function updateUserRooms() { | |
userRooms.innerHTML = ''; | |
if (currentRooms.length === 0) { | |
userRooms.innerHTML = '<p class="text-gray-500 text-sm italic">You haven\'t joined any rooms yet</p>'; | |
roomCount.textContent = '0'; | |
return; | |
} | |
roomCount.textContent = currentRooms.length; | |
currentRooms.forEach(room => { | |
const roomElement = document.createElement('div'); | |
roomElement.className = 'flex items-center justify-between p-2 hover:bg-gray-100 rounded-lg cursor-pointer transition'; | |
roomElement.innerHTML = ` | |
<div class="flex items-center"> | |
<i class="fas fa-hashtag text-gray-400 mr-2"></i> | |
<span>${room}</span> | |
</div> | |
<span class="text-xs text-gray-500">${messages[room] ? messages[room].length : 0} messages</span> | |
`; | |
roomElement.addEventListener('click', () => { | |
chatType = 'room'; | |
selectedChat = room; | |
switchTab('room'); | |
updateMessages(); | |
// Mark as read | |
if (unreadCounts.rooms[room]) { | |
unreadCounts.rooms[room] = 0; | |
updateNotifications(); | |
} | |
}); | |
userRooms.appendChild(roomElement); | |
}); | |
} | |
// Update online users list | |
function updateOnlineUsers() { | |
onlineUsers.innerHTML = ''; | |
userCount.textContent = allUsers.length; | |
if (allUsers.length === 0) { | |
onlineUsers.innerHTML = '<p class="text-gray-500 text-sm italic">No users online</p>'; | |
return; | |
} | |
allUsers.forEach(user => { | |
if (user === currentUser) return; | |
const userElement = document.createElement('div'); | |
userElement.className = 'flex items-center justify-between p-2 hover:bg-gray-100 rounded-lg cursor-pointer transition'; | |
userElement.innerHTML = ` | |
<div class="flex items-center"> | |
<div class="w-6 h-6 rounded-full bg-green-500 flex items-center justify-center text-white text-xs mr-2"> | |
${user.charAt(0).toUpperCase()} | |
</div> | |
<span>${user}</span> | |
</div> | |
<span class="text-xs text-gray-500">Online</span> | |
`; | |
userElement.addEventListener('click', () => { | |
// Start private chat with this user | |
chatType = 'private'; | |
selectedChat = user; | |
switchTab('private'); | |
updateMessages(); | |
// Mark as read | |
if (unreadCounts.private[user]) { | |
unreadCounts.private[user] = 0; | |
updateNotifications(); | |
} | |
}); | |
onlineUsers.appendChild(userElement); | |
}); | |
} | |
// Update available rooms list | |
function updateAvailableRooms() { | |
availableRooms.innerHTML = ''; | |
availableRoomCount.textContent = allRooms.length; | |
if (allRooms.length === 0) { | |
availableRooms.innerHTML = '<p class="text-gray-500 text-sm italic">No rooms available</p>'; | |
return; | |
} | |
allRooms.forEach(room => { | |
// Skip rooms the user is already in | |
if (currentRooms.includes(room)) return; | |
const roomElement = document.createElement('div'); | |
roomElement.className = 'flex items-center justify-between p-2 hover:bg-gray-100 rounded-lg cursor-pointer transition'; | |
roomElement.innerHTML = ` | |
<div class="flex items-center"> | |
<i class="fas fa-hashtag text-gray-400 mr-2"></i> | |
<span>${room}</span> | |
</div> | |
<span class="text-xs text-gray-500">${messages[room] ? messages[room].length : 0} messages</span> | |
`; | |
roomElement.addEventListener('click', () => { | |
showJoinRoomModal(room); | |
}); | |
availableRooms.appendChild(roomElement); | |
}); | |
} | |
// Update private chats list | |
function updatePrivateChats() { | |
privateChats.innerHTML = ''; | |
const privateChatUsers = Object.keys(privateMessages).filter(user => | |
user !== currentUser && (privateMessages[user].length > 0 || allUsers.includes(user)) | |
); | |
privateCount.textContent = privateChatUsers.length; | |
if (privateChatUsers.length === 0) { | |
privateChats.innerHTML = '<p class="text-gray-500 text-sm italic">No private conversations yet</p>'; | |
return; | |
} | |
privateChatUsers.forEach(user => { | |
const chatElement = document.createElement('div'); | |
chatElement.className = 'flex items-center justify-between p-2 hover:bg-gray-100 rounded-lg cursor-pointer transition'; | |
const lastMessage = privateMessages[user].length > 0 | |
? privateMessages[user][privateMessages[user].length - 1].text | |
: 'No messages yet'; | |
chatElement.innerHTML = ` | |
<div class="flex items-center"> | |
<div class="w-6 h-6 rounded-full bg-purple-500 flex items-center justify-center text-white text-xs mr-2"> | |
${user.charAt(0).toUpperCase()} | |
</div> | |
<div> | |
<div class="font-medium">${user}</div> | |
<div class="text-xs text-gray-500 truncate max-w-xs">${lastMessage}</div> | |
</div> | |
</div> | |
${unreadCounts.private[user] > 0 ? | |
`<span class="bg-red-500 text-white text-xs px-1.5 py-0.5 rounded-full">${unreadCounts.private[user]}</span>` : | |
''} | |
`; | |
chatElement.addEventListener('click', () => { | |
chatType = 'private'; | |
selectedChat = user; | |
switchTab('private'); | |
updateMessages(); | |
// Mark as read | |
if (unreadCounts.private[user]) { | |
unreadCounts.private[user] = 0; | |
updateNotifications(); | |
} | |
}); | |
privateChats.appendChild(chatElement); | |
}); | |
} | |
// Update messages display | |
function updateMessages() { | |
messagesContainer.innerHTML = ''; | |
if (!selectedChat) { | |
messagesContainer.innerHTML = ` | |
<div class="text-center text-gray-500 py-10"> | |
<i class="fas fa-comments text-4xl mb-2 text-gray-300"></i> | |
<p>Select a chat to start messaging</p> | |
</div> | |
`; | |
return; | |
} | |
let messageList = []; | |
if (chatType === 'room') { | |
messageList = messages[selectedChat] || []; | |
} else { | |
messageList = privateMessages[selectedChat] || []; | |
} | |
if (messageList.length === 0) { | |
messagesContainer.innerHTML = ` | |
<div class="text-center text-gray-500 py-10"> | |
<i class="fas fa-comments text-4xl mb-2 text-gray-300"></i> | |
<p>No messages in this chat yet</p> | |
</div> | |
`; | |
return; | |
} | |
messageList.forEach((msg, index) => { | |
const isCurrentUser = msg.user === currentUser; | |
const messageElement = document.createElement('div'); | |
messageElement.className = `mb-4 message-animation ${isCurrentUser ? 'pl-8' : 'pr-8'}`; | |
messageElement.innerHTML = ` | |
<div class="flex ${isCurrentUser ? 'justify-end' : ''}"> | |
<div class="max-w-xs md:max-w-md lg:max-w-lg ${isCurrentUser ? 'bg-indigo-100' : 'bg-white'} p-3 rounded-lg shadow-sm border border-gray-200"> | |
${!isCurrentUser ? `<div class="font-medium text-sm mb-1">${msg.user}</div>` : ''} | |
<div class="text-gray-800">${msg.text}</div> | |
<div class="text-xs text-gray-500 mt-1 text-right">${msg.time}</div> | |
</div> | |
</div> | |
`; | |
messagesContainer.appendChild(messageElement); | |
}); | |
// Scroll to bottom | |
messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
} | |
// Update chat header | |
function updateChatHeader() { | |
if (!selectedChat) { | |
chatTitle.textContent = 'Select a chat'; | |
chatTypeIcon.innerHTML = '<i class="fas fa-comments"></i>'; | |
return; | |
} | |
if (chatType === 'room') { | |
chatTitle.textContent = selectedChat; | |
chatTypeIcon.innerHTML = '<i class="fas fa-hashtag"></i>'; | |
} else { | |
chatTitle.textContent = selectedChat; | |
chatTypeIcon.innerHTML = '<i class="fas fa-user-friends"></i>'; | |
} | |
} | |
// Update notification badges | |
function updateNotifications() { | |
// Room notifications | |
let totalRoomUnread = 0; | |
Object.keys(unreadCounts.rooms).forEach(room => { | |
totalRoomUnread += unreadCounts.rooms[room]; | |
}); | |
if (totalRoomUnread > 0) { | |
roomNotification.textContent = totalRoomUnread; | |
roomNotification.classList.remove('hidden'); | |
} else { | |
roomNotification.classList.add('hidden'); | |
} | |
// Private notifications | |
let totalPrivateUnread = 0; | |
Object.keys(unreadCounts.private).forEach(user => { | |
totalPrivateUnread += unreadCounts.private[user]; | |
}); | |
if (totalPrivateUnread > 0) { | |
privateNotification.textContent = totalPrivateUnread; | |
privateNotification.classList.remove('hidden'); | |
} else { | |
privateNotification.classList.add('hidden'); | |
} | |
} | |
// Send message | |
function sendMessage() { | |
const messageText = messageInput.value.trim(); | |
if (!messageText || !selectedChat) return; | |
// Create new message | |
const now = new Date(); | |
const timeString = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); | |
const newMessage = { | |
user: currentUser, | |
text: messageText, | |
time: timeString | |
}; | |
// Add to messages | |
if (chatType === 'room') { | |
if (!messages[selectedChat]) { | |
messages[selectedChat] = []; | |
} | |
messages[selectedChat].push(newMessage); | |
// Update unread count for other users in the room | |
// (In a real app, this would be handled by the server) | |
} else { | |
if (!privateMessages[selectedChat]) { | |
privateMessages[selectedChat] = []; | |
} | |
privateMessages[selectedChat].push(newMessage); | |
// Update unread count for the recipient | |
if (chatType !== 'private' || selectedChat !== currentUser) { | |
if (!unreadCounts.private[selectedChat]) { | |
unreadCounts.private[selectedChat] = 0; | |
} | |
unreadCounts.private[selectedChat]++; | |
updateNotifications(); | |
} | |
} | |
// Clear input | |
messageInput.value = ''; | |
// Update UI | |
updateMessages(); | |
if (chatType === 'private') { | |
updatePrivateChats(); | |
} | |
} | |
// Show join room modal | |
function showJoinRoomModal(roomName) { | |
roomNameDisplay.textContent = roomName; | |
selectedChat = roomName; | |
chatType = 'room'; | |
// Show modal with animation | |
joinRoomModal.classList.remove('hidden'); | |
setTimeout(() => { | |
const modalContent = joinRoomModal.querySelector('div > div'); | |
modalContent.classList.remove('scale-95', 'opacity-0'); | |
modalContent.classList.add('scale-100', 'opacity-100'); | |
}, 10); | |
} | |
// Hide join room modal | |
function hideJoinRoomModal() { | |
const modalContent = joinRoomModal.querySelector('div > div'); | |
modalContent.classList.remove('scale-100', 'opacity-100'); | |
modalContent.classList.add('scale-95', 'opacity-0'); | |
setTimeout(() => { | |
joinRoomModal.classList.add('hidden'); | |
}, 300); | |
} | |
// Join room | |
function joinRoom() { | |
if (!selectedChat || currentRooms.includes(selectedChat)) { | |
hideJoinRoomModal(); | |
return; | |
} | |
currentRooms.push(selectedChat); | |
updateUI(); | |
hideJoinRoomModal(); | |
} | |
// Add new room | |
function addRoom() { | |
const roomName = newRoomInput.value.trim(); | |
if (!roomName) return; | |
// Check if room already exists | |
if (allRooms.includes(roomName)) { | |
alert('Room already exists!'); | |
return; | |
} | |
// Add new room | |
allRooms.push(roomName); | |
newRoomInput.value = ''; | |
// Update UI | |
updateAvailableRooms(); | |
// Show join modal for the new room | |
showJoinRoomModal(roomName); | |
} | |
// Event Listeners | |
loginBtn.addEventListener('click', login); | |
logoutBtn.addEventListener('click', logout); | |
// Allow login with Enter key | |
usernameInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') login(); | |
}); | |
sendBtn.addEventListener('click', sendMessage); | |
// Allow sending with Enter key | |
messageInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') sendMessage(); | |
}); | |
addRoomBtn.addEventListener('click', addRoom); | |
// Allow adding room with Enter key | |
newRoomInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') addRoom(); | |
}); | |
closeModalBtn.addEventListener('click', hideJoinRoomModal); | |
cancelJoinBtn.addEventListener('click', hideJoinRoomModal); | |
confirmJoinBtn.addEventListener('click', joinRoom); | |
// Close modal when clicking outside | |
joinRoomModal.addEventListener('click', (e) => { | |
if (e.target === joinRoomModal) { | |
hideJoinRoomModal(); | |
} | |
}); | |
// Tab switching | |
roomTab.addEventListener('click', () => switchTab('room')); | |
privateTab.addEventListener('click', () => switchTab('private')); | |
</script> | |
<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=swordmeister-zoro/modern-chat-interface" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |