Spaces:
Running
Running
| // ChatVerse Retro - Main JavaScript | |
| class ChatApp { | |
| constructor() { | |
| this.currentUser = localStorage.getItem('currentUser') || 'Anonymous'; | |
| this.messages = JSON.parse(localStorage.getItem('messages')) || []; | |
| this.contacts = JSON.parse(localStorage.getItem('contacts')) || this.getDefaultContacts(); | |
| this.activeContact = this.contacts[0]; | |
| this.commands = { | |
| '/help': this.showHelp.bind(this), | |
| '/clear': this.clearChat.bind(this), | |
| '/nick': this.changeNick.bind(this), | |
| '/theme': this.toggleTheme.bind(this), | |
| '/time': this.showTime.bind(this), | |
| '/whoami': this.showCurrentUser.bind(this), | |
| }; | |
| this.init(); | |
| } | |
| init() { | |
| this.setupEventListeners(); | |
| this.loadMessages(); | |
| this.updateContacts(); | |
| this.setupTheme(); | |
| this.setupMobile(); | |
| } | |
| setupEventListeners() { | |
| const messageInput = document.getElementById('messageInput'); | |
| const sendButton = document.getElementById('sendButton'); | |
| if (messageInput) { | |
| messageInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') { | |
| this.sendMessage(); | |
| } | |
| }); | |
| } | |
| if (sendButton) { | |
| sendButton.addEventListener('click', () => this.sendMessage()); | |
| } | |
| // Auto-resize input | |
| if (messageInput) { | |
| messageInput.addEventListener('input', () => { | |
| messageInput.style.height = 'auto'; | |
| messageInput.style.height = Math.min(messageInput.scrollHeight, 120) + 'px'; | |
| }); | |
| } | |
| } | |
| setupTheme() { | |
| const savedTheme = localStorage.getItem('theme') || 'dark'; | |
| document.documentElement.setAttribute('data-theme', savedTheme); | |
| } | |
| setupMobile() { | |
| // Handle mobile menu toggle | |
| const menuToggle = document.getElementById('menuToggle'); | |
| const sidebar = document.querySelector('side-bar'); | |
| if (menuToggle && sidebar) { | |
| menuToggle.addEventListener('click', () => { | |
| sidebar.classList.toggle('sidebar-expanded'); | |
| sidebar.classList.toggle('sidebar-collapsed'); | |
| }); | |
| } | |
| // Close sidebar on outside click for mobile | |
| document.addEventListener('click', (e) => { | |
| if (window.innerWidth <= 768) { | |
| const sidebarElement = document.querySelector('side-bar'); | |
| const isClickInsideSidebar = sidebarElement.contains(e.target); | |
| const isMenuToggle = menuToggle && menuToggle.contains(e.target); | |
| if (!isClickInsideSidebar && !isMenuToggle) { | |
| sidebarElement.classList.add('sidebar-collapsed'); | |
| sidebarElement.classList.remove('sidebar-expanded'); | |
| } | |
| } | |
| }); | |
| } | |
| getDefaultContacts() { | |
| return [ | |
| { id: 1, name: 'System', status: 'online', avatar: '💻', lastMessage: 'Welcome to ChatVerse!' }, | |
| { id: 2, name: 'RetroBot', status: 'online', avatar: '🤖', lastMessage: 'Type /help for commands' }, | |
| { id: 3, name: 'CyberPunk', status: 'away', avatar: '🎮', lastMessage: 'Gaming...' }, | |
| { id: 4, name: 'NeonDream', status: 'offline', avatar: '🌟', lastMessage: 'See you later!' }, | |
| { id: 5, name: 'PixelMaster', status: 'online', avatar: '🎨', lastMessage: 'Check out my new pixel art!' }, | |
| ]; | |
| } | |
| sendMessage() { | |
| const input = document.getElementById('messageInput'); | |
| const content = input.value.trim(); | |
| if (!content) return; | |
| // Check for commands | |
| if (content.startsWith('/')) { | |
| this.executeCommand(content); | |
| input.value = ''; | |
| return; | |
| } | |
| const message = { | |
| id: Date.now(), | |
| content: content, | |
| sender: this.currentUser, | |
| timestamp: new Date(), | |
| type: 'user' | |
| }; | |
| this.messages.push(message); | |
| this.saveMessages(); | |
| this.displayMessage(message); | |
| // Simulate bot response | |
| this.simulateBotResponse(content); | |
| input.value = ''; | |
| input.style.height = 'auto'; | |
| } | |
| executeCommand(command) { | |
| const parts = command.split(' '); | |
| const cmd = parts[0].toLowerCase(); | |
| const args = parts.slice(1); | |
| if (this.commands[cmd]) { | |
| this.commands[cmd](args); | |
| } else { | |
| this.displaySystemMessage(`Unknown command: ${cmd}. Type /help for available commands.`); | |
| } | |
| } | |
| showHelp() { | |
| const helpText = ` | |
| Available Commands: | |
| /help - Show this help message | |
| /clear - Clear the chat history | |
| /nick [name] - Change your nickname | |
| /theme - Toggle light/dark theme | |
| /time - Show current server time | |
| /whoami - Show current user info | |
| `; | |
| this.displaySystemMessage(helpText); | |
| } | |
| clearChat() { | |
| this.messages = []; | |
| localStorage.removeItem('messages'); | |
| const container = document.getElementById('messagesContainer'); | |
| if (container) { | |
| container.innerHTML = ''; | |
| } | |
| this.displaySystemMessage('Chat history cleared.'); | |
| } | |
| changeNick(args) { | |
| const newNick = args.join(' '); | |
| if (newNick && newNick.length > 0) { | |
| const oldNick = this.currentUser; | |
| this.currentUser = newNick; | |
| localStorage.setItem('currentUser', newNick); | |
| this.displaySystemMessage(`Nickname changed from "${oldNick}" to "${newNick}"`); | |
| } else { | |
| this.displaySystemMessage('Usage: /nick [new nickname]'); | |
| } | |
| } | |
| toggleTheme() { | |
| const currentTheme = document.documentElement.getAttribute('data-theme'); | |
| const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; | |
| document.documentElement.setAttribute('data-theme', newTheme); | |
| localStorage.setItem('theme', newTheme); | |
| this.displaySystemMessage(`Theme switched to ${newTheme} mode`); | |
| } | |
| showTime() { | |
| const now = new Date(); | |
| this.displaySystemMessage(`Server Time: ${now.toLocaleString()}`); | |
| } | |
| showCurrentUser() { | |
| this.displaySystemMessage(`Current User: ${this.currentUser}\nTheme: ${document.documentElement.getAttribute('data-theme')} mode`); | |
| } | |
| simulateBotResponse(userMessage) { | |
| setTimeout(() => { | |
| const responses = [ | |
| `I see you said: "${userMessage}"`, | |
| `That's interesting! Tell me more.`, | |
| `🤖 Processing... Processing...`, | |
| `Beep boop! Message received.`, | |
| `You sound like a real retro gamer!`, | |
| `404: Witty response not found 😄`, | |
| `I'm just a bot, but I appreciate the message!`, | |
| `System: Message delivered successfully.` | |
| ]; | |
| const randomResponse = responses[Math.floor(Math.random() * responses.length)]; | |
| const botMessage = { | |
| id: Date.now() + 1, | |
| content: randomResponse, | |
| sender: 'RetroBot', | |
| timestamp: new Date(), | |
| type: 'bot' | |
| }; | |
| this.messages.push(botMessage); | |
| this.saveMessages(); | |
| this.displayMessage(botMessage); | |
| }, Math.random() * 2000 + 1000); | |
| } | |
| displayMessage(message) { | |
| const container = document.getElementById('messagesContainer'); | |
| if (!container) return; | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = 'message-group'; | |
| const timestamp = this.formatTime(message.timestamp); | |
| const senderClass = message.type === 'user' ? 'text-emerald-400' : 'text-cyan-400'; | |
| const senderGlow = message.type === 'user' ? 'shadow-[0_0_10px_#00ff00]' : 'shadow-[0_0_10px_#00ffff]'; | |
| messageDiv.innerHTML = ` | |
| <div class="message-header flex items-center gap-2 mb-2"> | |
| <div class="w-3 h-3 ${senderClass} ${senderGlow}"></div> | |
| <span class="font-['Press_Start_2P'] text-xs ${senderClass}">${message.sender}</span> | |
| <span class="text-slate-500 text-xs" data-timestamp="${timestamp}">[${timestamp}]</span> | |
| </div> | |
| <div class="message-content font-mono text-slate-300 text-sm leading-relaxed"> | |
| > ${this.escapeHtml(message.content)} | |
| </div> | |
| `; | |
| container.appendChild(messageDiv); | |
| this.scrollToBottom(); | |
| } | |
| displaySystemMessage(content) { | |
| const message = { | |
| id: Date.now(), | |
| content: content, | |
| sender: 'SYSTEM', | |
| timestamp: new Date(), | |
| type: 'system' | |
| }; | |
| this.displayMessage(message); | |
| } | |
| loadMessages() { | |
| const container = document.getElementById('messagesContainer'); | |
| if (!container) return; | |
| // Clear existing messages except system welcome | |
| container.innerHTML = ''; | |
| // Add welcome message | |
| const welcomeMessage = { | |
| id: 0, | |
| content: `Welcome to ChatVerse Retro v1.0\n> Type /help for available commands\n> Connection established: ONLINE`, | |
| sender: 'SYSTEM', | |
| timestamp: new Date(), | |
| type: 'system' | |
| }; | |
| this.displayMessage(welcomeMessage); | |
| // Load and display stored messages | |
| this.messages.forEach(message => { | |
| this.displayMessage(message); | |
| }); | |
| } | |
| saveMessages() { | |
| // Keep only last 50 messages | |
| this.messages = this.messages.slice(-50); | |
| localStorage.setItem('messages', JSON.stringify(this.messages)); | |
| } | |
| updateContacts() { | |
| // This would be called by the sidebar component | |
| const event = new CustomEvent('contactsUpdated', { detail: this.contacts }); | |
| document.dispatchEvent(event); | |
| } | |
| formatTime(date) { | |
| const now = new Date(); | |
| const diff = now - date; | |
| const minutes = Math.floor(diff / 60000); | |
| if (minutes < 1) return 'NOW'; | |
| if (minutes < 60) return `${minutes}M`; | |
| const hours = Math.floor(minutes / 60); | |
| if (hours < 24) return `${hours}H`; | |
| return date.toLocaleDateString(); | |
| } | |
| scrollToBottom() { | |
| const container = document.getElementById('messagesContainer'); | |
| if (container) { | |
| container.scrollTop = container.scrollHeight; | |
| } | |
| } | |
| escapeHtml(text) { | |
| const div = document.createElement('div'); | |
| div.textContent = text; | |
| return div.innerHTML; | |
| } | |
| } | |
| // Initialize app when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', () => { | |
| window.chatApp = new ChatApp(); | |
| }); | |
| // Handle page visibility for retro effect | |
| document.addEventListener('visibilitychange', () => { | |
| if (document.hidden) { | |
| document.body.style.filter = 'brightness(0.5)'; | |
| } else { | |
| document.body.style.filter = 'brightness(1)'; | |
| } | |
| }); | |
| // Add some retro console messages | |
| console.log('%c ChatVerse Retro v1.0 Loaded ', 'background: #00ff00; color: #000; font-size: 20px; font-family: "Press Start 2P"'); | |
| console.log('%c Type chatApp.showHelp() in console for debug commands', 'color: #00ff00; font-family: monospace'); |