chatverse / index.html
ysn-rfd's picture
یک پیام رسان واقعی مانند discord بساز، به طور کاملا واقعی کار کنه، کاملا واقعی باشه، ثبت نام بدون نیاز به ایمیل، نیازی نیست GUI همانند discord باشه، فقط عملکرد همانند discord باشه
62b9efb verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ChatVerse - Connect & Chat</title>
<link rel="icon" type="image/x-icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🌌</text></svg>">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<style>
@keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-20px); }
}
.float-animation {
animation: float 6s ease-in-out infinite;
}
.message-bubble {
animation: slideIn 0.3s ease-out;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.typing-indicator span {
animation: typing 1.4s infinite ease-in-out;
}
.typing-indicator span:nth-child(2) {
animation-delay: 0.2s;
}
.typing-indicator span:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes typing {
0%, 60%, 100% {
transform: translateY(0);
}
30% {
transform: translateY(-10px);
}
}
</style>
</head>
<body class="bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900 min-h-screen">
<!-- Login Screen -->
<div id="loginScreen" class="min-h-screen flex items-center justify-center p-4">
<div class="bg-white/10 backdrop-blur-lg rounded-3xl p-8 max-w-md w-full shadow-2xl border border-white/20">
<div class="text-center mb-8">
<div class="float-animation">
<h1 class="text-5xl font-bold text-white mb-2">ChatVerse</h1>
<p class="text-purple-200">Connect with the universe 🌌</p>
</div>
</div>
<form id="loginForm" class="space-y-6">
<div>
<label class="block text-purple-200 mb-2">Choose your username</label>
<input type="text" id="username" required
class="w-full px-4 py-3 rounded-xl bg-white/20 backdrop-blur text-white placeholder-purple-200 border border-purple-300/30 focus:outline-none focus:border-purple-400 transition"
placeholder="Enter username">
</div>
<button type="submit"
class="w-full bg-gradient-to-r from-purple-500 to-pink-500 text-white py-3 rounded-xl font-semibold hover:from-purple-600 hover:to-pink-600 transform hover:scale-105 transition duration-300 shadow-lg">
Join ChatVerse
</button>
</form>
</div>
</div>
<!-- Chat Interface -->
<div id="chatInterface" class="hidden h-screen flex flex-col">
<!-- Header -->
<header class="bg-white/10 backdrop-blur-lg border-b border-white/20 p-4">
<div class="flex items-center justify-between max-w-7xl mx-auto">
<div class="flex items-center space-x-3">
<h1 class="text-2xl font-bold text-white">ChatVerse</h1>
<span class="bg-green-400 w-3 h-3 rounded-full animate-pulse"></span>
</div>
<div class="flex items-center space-x-4">
<span id="currentUser" class="text-purple-200"></span>
<button onclick="logout()" class="text-purple-200 hover:text-white transition">
<i data-feather="log-out"></i>
</button>
</div>
</div>
</header>
<div class="flex-1 flex overflow-hidden">
<!-- Sidebar - Online Users -->
<aside class="w-64 bg-white/5 backdrop-blur-lg border-r border-white/10 p-4 overflow-y-auto">
<h2 class="text-purple-200 font-semibold mb-4 flex items-center">
<i data-feather="users" class="w-4 h-4 mr-2"></i>
Online Users (<span id="onlineCount">0</span>)
</h2>
<div id="usersList" class="space-y-2">
<!-- Users will be populated here -->
</div>
</aside>
<!-- Main Chat Area -->
<main class="flex-1 flex flex-col">
<!-- Messages Container -->
<div id="messagesContainer" class="flex-1 overflow-y-auto p-6 space-y-4">
<!-- Messages will appear here -->
</div>
<!-- Typing Indicator -->
<div id="typingIndicator" class="px-6 py-2 hidden">
<div class="typing-indicator flex items-center space-x-1 text-purple-300">
<span class="w-2 h-2 bg-purple-300 rounded-full"></span>
<span class="w-2 h-2 bg-purple-300 rounded-full"></span>
<span class="w-2 h-2 bg-purple-300 rounded-full"></span>
<span class="text-sm ml-2" id="typingText"></span>
</div>
</div>
<!-- Message Input -->
<div class="bg-white/10 backdrop-blur-lg border-t border-white/20 p-4">
<form id="messageForm" class="flex space-x-3">
<input type="text" id="messageInput"
placeholder="Type your message..."
class="flex-1 px-4 py-3 rounded-xl bg-white/20 backdrop-blur text-white placeholder-purple-200 border border-purple-300/30 focus:outline-none focus:border-purple-400 transition"
autocomplete="off">
<button type="submit"
class="bg-gradient-to-r from-purple-500 to-pink-500 text-white px-6 py-3 rounded-xl hover:from-purple-600 hover:to-pink-600 transform hover:scale-105 transition duration-300 shadow-lg">
<i data-feather="send" class="w-5 h-5"></i>
</button>
</form>
</div>
</main>
</div>
</div>
<script>
// Simple WebSocket-like simulation using localStorage and BroadcastChannel
class ChatSystem {
constructor() {
this.currentUser = null;
this.users = new Set();
this.messages = [];
this.broadcastChannel = new BroadcastChannel('chatverse');
this.typingTimeout = null;
this.isTyping = false;
this.broadcastChannel.onmessage = (event) => {
const { type, data } = event.data;
this.handleMessage(type, data);
};
}
handleMessage(type, data) {
switch(type) {
case 'userJoined':
this.addUser(data.username);
break;
case 'userLeft':
this.removeUser(data.username);
break;
case 'message':
this.addMessage(data);
break;
case 'typing':
this.showTyping(data.username);
break;
case 'stopTyping':
this.hideTyping();
break;
}
}
broadcast(type, data) {
this.broadcastChannel.postMessage({ type, data });
}
login(username) {
this.currentUser = username;
localStorage.setItem('currentUser', username);
this.broadcast('userJoined', { username });
this.addUser(username);
this.loadMessages();
}
logout() {
if (this.currentUser) {
this.broadcast('userLeft', { username: this.currentUser });
localStorage.removeItem('currentUser');
this.removeUser(this.currentUser);
this.currentUser = null;
}
}
addUser(username) {
this.users.add(username);
this.updateUsersList();
}
removeUser(username) {
this.users.delete(username);
this.updateUsersList();
}
updateUsersList() {
const usersList = document.getElementById('usersList');
const onlineCount = document.getElementById('onlineCount');
usersList.innerHTML = '';
onlineCount.textContent = this.users.size;
this.users.forEach(username => {
const userDiv = document.createElement('div');
userDiv.className = 'flex items-center space-x-2 p-2 rounded-lg hover:bg-white/10 transition cursor-pointer';
userDiv.innerHTML = `
<div class="w-2 h-2 bg-green-400 rounded-full"></div>
<span class="text-purple-200">${username}</span>
${username === this.currentUser ? '<span class="text-xs text-purple-400">(You)</span>' : ''}
`;
usersList.appendChild(userDiv);
});
}
sendMessage(content) {
const message = {
id: Date.now(),
username: this.currentUser,
content: content,
timestamp: new Date().toISOString()
};
this.messages.push(message);
this.broadcast('message', message);
this.addMessage(message);
this.saveMessages();
}
addMessage(message) {
const messagesContainer = document.getElementById('messagesContainer');
const messageDiv = document.createElement('div');
messageDiv.className = `message-bubble flex ${message.username === this.currentUser ? 'justify-end' : 'justify-start'}`;
const time = new Date(message.timestamp).toLocaleTimeString('en-US', {
hour: '2-digit',
minute: '2-digit'
});
messageDiv.innerHTML = `
<div class="max-w-xs lg:max-w-md px-4 py-2 rounded-2xl ${
message.username === this.currentUser
? 'bg-gradient-to-r from-purple-500 to-pink-500 text-white'
: 'bg-white/20 backdrop-blur text-purple-100'
}">
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-sm">${message.username}</span>
<span class="text-xs opacity-70">${time}</span>
</div>
<p class="mt-1">${message.content}</p>
</div>
`;
messagesContainer.appendChild(messageDiv);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
showTyping(username) {
if (username === this.currentUser) return;
const typingIndicator = document.getElementById('typingIndicator');
const typingText = document.getElementById('typingText');
typingText.textContent = `${username} is typing...`;
typingIndicator.classList.remove('hidden');
}
hideTyping() {
document.getElementById('typingIndicator').classList.add('hidden');
}
handleTyping() {
if (!this.isTyping) {
this.isTyping = true;
this.broadcast('typing', { username: this.currentUser });
}
clearTimeout(this.typingTimeout);
this.typingTimeout = setTimeout(() => {
this.isTyping = false;
this.broadcast('stopTyping', {});
}, 1000);
}
saveMessages() {
localStorage.setItem('chatMessages', JSON.stringify(this.messages));
}
loadMessages() {
const saved = localStorage.getItem('chatMessages');
if (saved) {
this.messages = JSON.parse(saved);
this.messages.forEach(msg => this.addMessage(msg));
}
}
}
// Initialize chat system
const chatSystem = new ChatSystem();
// Check if user is already logged in
window.addEventListener('DOMContentLoaded', () => {
const savedUser = localStorage.getItem('currentUser');
if (savedUser) {
showChatInterface(savedUser);
}
});
// Login form handler
document.getElementById('loginForm').addEventListener('submit', (e) => {
e.preventDefault();
const username = document.getElementById('username').value.trim();
if (username) {
chatSystem.login(username);
showChatInterface(username);
}
});
// Message form handler
document.getElementById('messageForm').addEventListener('submit', (e) => {
e.preventDefault();
const input = document.getElementById('messageInput');
const message = input.value.trim();
if (message) {
chatSystem.sendMessage(message);
input.value = '';
chatSystem.hideTyping();
}
});
// Typing indicator
document.getElementById('messageInput').addEventListener('input', () => {
chatSystem.handleTyping();
});
// Show chat interface
function showChatInterface(username) {
document.getElementById('loginScreen').classList.add('hidden');
document.getElementById('chatInterface').classList.remove('hidden');
document.getElementById('currentUser').textContent = username;
feather.replace();
}
// Logout
function logout() {
chatSystem.logout();
document.getElementById('chatInterface').classList.add('hidden');
document.getElementById('loginScreen').classList.remove('hidden');
document.getElementById('messagesContainer').innerHTML = '';
document.getElementById('username').value = '';
}
// Replace feather icons
feather.replace();
</script>
</body>
</html>