chatverse-retro / script.js
C50BARZ's picture
Build a retro chat app
69c6940 verified
// 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');