Spaces:
Running
Running
| <html lang="fa" dir="rtl"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>چت روم مینیمال</title> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --primary-color: #6366f1; | |
| --secondary-color: #8b5cf6; | |
| --background-color: #0f172a; | |
| --surface-color: rgba(255, 255, 255, 0.1); | |
| --glass-bg: rgba(255, 255, 255, 0.05); | |
| --glass-border: rgba(255, 255, 255, 0.1); | |
| --text-primary: #f1f5f9; | |
| --text-secondary: #94a3b8; | |
| --accent-color: #f59e0b; | |
| --success-color: #10b981; | |
| --danger-color: #ef4444; | |
| --warning-color: #f59e0b; | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Vazirmatn', sans-serif; | |
| background: linear-gradient(135deg, var(--background-color) 0%, #1e293b 100%); | |
| color: var(--text-primary); | |
| min-height: 100vh; | |
| overflow-x: hidden; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| } | |
| /* Header */ | |
| .header { | |
| text-align: center; | |
| padding: 20px 0; | |
| position: relative; | |
| } | |
| .header h1 { | |
| font-size: 2.5rem; | |
| background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| margin-bottom: 10px; | |
| } | |
| .built-with { | |
| position: absolute; | |
| top: 20px; | |
| left: 20px; | |
| font-size: 0.9rem; | |
| color: var(--text-secondary); | |
| } | |
| .built-with a { | |
| color: var(--primary-color); | |
| text-decoration: none; | |
| transition: color 0.3s; | |
| } | |
| .built-with a:hover { | |
| color: var(--secondary-color); | |
| } | |
| /* Auth Section */ | |
| .auth-section { | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| min-height: 80vh; | |
| } | |
| .auth-card { | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 20px; | |
| padding: 40px; | |
| width: 100%; | |
| max-width: 400px; | |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); | |
| animation: slideIn 0.5s ease-out; | |
| } | |
| @keyframes slideIn { | |
| from { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .auth-card h2 { | |
| text-align: center; | |
| margin-bottom: 30px; | |
| font-size: 1.8rem; | |
| } | |
| .form-group { | |
| margin-bottom: 20px; | |
| } | |
| .form-group label { | |
| display: block; | |
| margin-bottom: 8px; | |
| color: var(--text-secondary); | |
| } | |
| .form-group input { | |
| width: 100%; | |
| padding: 12px 20px; | |
| background: rgba(255, 255, 255, 0.05); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 10px; | |
| color: var(--text-primary); | |
| font-size: 1rem; | |
| transition: all 0.3s; | |
| } | |
| .form-group input:focus { | |
| outline: none; | |
| border-color: var(--primary-color); | |
| background: rgba(255, 255, 255, 0.08); | |
| } | |
| .btn { | |
| width: 100%; | |
| padding: 12px 20px; | |
| background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); | |
| border: none; | |
| border-radius: 10px; | |
| color: white; | |
| font-size: 1rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| margin-top: 10px; | |
| } | |
| .btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 5px 15px rgba(99, 102, 241, 0.4); | |
| } | |
| /* Main Chat Interface */ | |
| .chat-interface { | |
| display: none; | |
| min-height: 100vh; | |
| } | |
| .chat-container { | |
| display: grid; | |
| grid-template-columns: 280px 1fr; | |
| gap: 20px; | |
| height: calc(100vh - 120px); | |
| } | |
| /* Sidebar */ | |
| .sidebar { | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 20px; | |
| padding: 20px; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .sidebar-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| .sidebar-header h3 { | |
| font-size: 1.2rem; | |
| } | |
| .add-room-btn { | |
| background: var(--primary-color); | |
| border: none; | |
| border-radius: 50%; | |
| width: 40px; | |
| height: 40px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| } | |
| .add-room-btn:hover { | |
| background: var(--secondary-color); | |
| transform: rotate(90deg); | |
| } | |
| .rooms-list { | |
| flex: 1; | |
| overflow-y: auto; | |
| } | |
| .room-item { | |
| background: rgba(255, 255, 255, 0.05); | |
| border-radius: 12px; | |
| padding: 15px; | |
| margin-bottom: 10px; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .room-item:hover { | |
| background: rgba(255, 255, 255, 0.1); | |
| transform: translateX(5px); | |
| } | |
| .room-item.active { | |
| background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); | |
| } | |
| .room-info { | |
| flex: 1; | |
| } | |
| .room-name { | |
| font-weight: 600; | |
| margin-bottom: 5px; | |
| } | |
| .room-members { | |
| font-size: 0.85rem; | |
| color: var(--text-secondary); | |
| } | |
| .room-actions { | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .room-actions button { | |
| background: transparent; | |
| border: none; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| padding: 5px; | |
| border-radius: 5px; | |
| transition: all 0.3s; | |
| } | |
| .room-actions button:hover { | |
| background: rgba(255, 255, 255, 0.1); | |
| color: var(--text-primary); | |
| } | |
| /* Chat Area */ | |
| .chat-area { | |
| display: flex; | |
| flex-direction: column; | |
| background: var(--background-color); | |
| border-radius: 20px; | |
| overflow: hidden; | |
| } | |
| .chat-header { | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(10px); | |
| border-bottom: 1px solid var(--glass-border); | |
| padding: 15px 20px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .chat-header-info { | |
| display: flex; | |
| align-items: center; | |
| gap: 15px; | |
| } | |
| .chat-header-info h3 { | |
| font-size: 1.2rem; | |
| } | |
| .chat-actions { | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .chat-actions button { | |
| background: transparent; | |
| border: none; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| padding: 8px; | |
| border-radius: 8px; | |
| transition: all 0.3s; | |
| } | |
| .chat-actions button:hover { | |
| background: rgba(255, 255, 255, 0.1); | |
| color: var(--text-primary); | |
| } | |
| .messages-container { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 20px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 15px; | |
| } | |
| .message { | |
| max-width: 70%; | |
| padding: 12px 16px; | |
| border-radius: 18px; | |
| animation: fadeIn 0.3s ease-out; | |
| position: relative; | |
| } | |
| @keyframes fadeIn { | |
| from { | |
| opacity: 0; | |
| transform: translateY(10px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .message.received { | |
| align-self: flex-start; | |
| background: var(--glass-bg); | |
| border: 1px solid var(--glass-border); | |
| } | |
| .message.sent { | |
| align-self: flex-end; | |
| background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); | |
| } | |
| .message-header { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-bottom: 8px; | |
| font-size: 0.85rem; | |
| color: var(--text-secondary); | |
| } | |
| .message-content { | |
| word-wrap: break-word; | |
| } | |
| .message-reactions { | |
| display: flex; | |
| gap: 5px; | |
| margin-top: 8px; | |
| } | |
| .reaction { | |
| background: rgba(255, 255, 255, 0.1); | |
| border-radius: 50%; | |
| width: 24px; | |
| height: 24px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 0.85rem; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| } | |
| .reaction:hover { | |
| transform: scale(1.2); | |
| } | |
| .message-actions { | |
| position: absolute; | |
| top: -10px; | |
| right: -10px; | |
| display: flex; | |
| gap: 5px; | |
| opacity: 0; | |
| transition: opacity 0.3s; | |
| } | |
| .message:hover .message-actions { | |
| opacity: 1; | |
| } | |
| .message-actions button { | |
| background: rgba(255, 255, 255, 0.1); | |
| border: none; | |
| border-radius: 50%; | |
| width: 28px; | |
| height: 28px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| } | |
| .message-actions button:hover { | |
| background: rgba(255, 255, 255, 0.2); | |
| } | |
| /* Input Area */ | |
| .input-area { | |
| padding: 20px; | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(10px); | |
| border-top: 1px solid var(--glass-border); | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .input-wrapper { | |
| flex: 1; | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .input-wrapper input { | |
| flex: 1; | |
| padding: 12px 20px; | |
| background: rgba(255, 255, 255, 0.05); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 25px; | |
| color: var(--text-primary); | |
| font-size: 1rem; | |
| } | |
| .input-wrapper input:focus { | |
| outline: none; | |
| border-color: var(--primary-color); | |
| } | |
| .input-actions { | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .input-actions button { | |
| background: transparent; | |
| border: none; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| padding: 10px; | |
| border-radius: 50%; | |
| transition: all 0.3s; | |
| } | |
| .input-actions button:hover { | |
| background: rgba(255, 255, 255, 0.1); | |
| color: var(--text-primary); | |
| } | |
| /* Modal */ | |
| .modal { | |
| display: none; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: rgba(0, 0, 0, 0.5); | |
| backdrop-filter: blur(5px); | |
| z-index: 1000; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .modal.active { | |
| display: flex; | |
| } | |
| .modal-content { | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 20px; | |
| padding: 30px; | |
| width: 90%; | |
| max-width: 500px; | |
| animation: modalSlideIn 0.3s ease-out; | |
| } | |
| @keyframes modalSlideIn { | |
| from { | |
| opacity: 0; | |
| transform: scale(0.9); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: scale(1); | |
| } | |
| } | |
| .modal-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| .modal-header h2 { | |
| font-size: 1.5rem; | |
| } | |
| .modal-close { | |
| background: transparent; | |
| border: none; | |
| color: var(--text-secondary); | |
| font-size: 1.5rem; | |
| cursor: pointer; | |
| } | |
| /* Reactions Panel */ | |
| .reactions-panel { | |
| display: none; | |
| position: absolute; | |
| bottom: 100%; | |
| right: 0; | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 12px; | |
| padding: 10px; | |
| gap: 10px; | |
| z-index: 100; | |
| } | |
| .reactions-panel.active { | |
| display: flex; | |
| } | |
| .reaction-btn { | |
| width: 36px; | |
| height: 36px; | |
| background: rgba(255, 255, 255, 0.1); | |
| border: none; | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| } | |
| .reaction-btn:hover { | |
| background: rgba(255, 255, 255, 0.2); | |
| transform: scale(1.1); | |
| } | |
| /* Responsive Design */ | |
| @media (max-width: 768px) { | |
| .chat-container { | |
| grid-template-columns: 1fr; | |
| } | |
| .sidebar { | |
| display: none; | |
| } | |
| .auth-card { | |
| padding: 30px; | |
| } | |
| .header h1 { | |
| font-size: 2rem; | |
| } | |
| } | |
| /* Loading Spinner */ | |
| .spinner { | |
| width: 40px; | |
| height: 40px; | |
| border: 4px solid rgba(255, 255, 255, 0.1); | |
| border-top: 4px solid var(--primary-color); | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| margin: 20px auto; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| /* Toast Notification */ | |
| .toast { | |
| position: fixed; | |
| bottom: 20px; | |
| right: 20px; | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 10px; | |
| padding: 15px 20px; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| transform: translateX(400px); | |
| transition: transform 0.3s ease-out; | |
| z-index: 1000; | |
| } | |
| .toast.show { | |
| transform: translateX(0); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="built-with">Built with anycoder</a> | |
| <h1>چت روم مینیمال</h1> | |
| </div> | |
| <!-- Authentication Section --> | |
| <div class="auth-section" id="authSection"> | |
| <div class="auth-card"> | |
| <h2>ورود به چت روم</h2> | |
| <div class="form-group"> | |
| <label for="phoneNumber">شماره موبایل</label> | |
| <input type="tel" id="phoneNumber" placeholder="09xxxxxxxxx" maxlength="11"> | |
| </div> | |
| <button class="btn" onclick="authenticate()">تایید و ورود</button> | |
| </div> | |
| </div> | |
| <!-- Main Chat Interface --> | |
| <div class="chat-interface" id="chatInterface"> | |
| <div class="chat-container"> | |
| <!-- Sidebar --> | |
| <div class="sidebar"> | |
| <div class="sidebar-header"> | |
| <h3>اتاقهای چت</h3> | |
| <button class="add-room-btn" onclick="showCreateRoomModal()"> | |
| <i class="fas fa-plus"></i> | |
| </button> | |
| </div> | |
| <div class="rooms-list" id="roomsList"> | |
| <!-- Rooms will be dynamically added here --> | |
| </div> | |
| </div> | |
| <!-- Chat Area --> | |
| <div class="chat-area"> | |
| <div class="chat-header"> | |
| <div class="chat-header-info"> | |
| <div class="room-info"> | |
| <h3 id="currentRoomName">انتخاب یک اتاق</h3> | |
| <span id="currentRoomMembers" class="room-members">0 عضو</span> | |
| </div> | |
| </div> | |
| <div class="chat-actions"> | |
| <button onclick="copyRoomLink()"> | |
| <i class="fas fa-link"></i> | |
| </button> | |
| <button onclick="showRoomInfo()"> | |
| <i class="fas fa-info-circle"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="messages-container" id="messagesContainer"> | |
| <!-- Messages will be dynamically added here --> | |
| </div> | |
| <div class="input-area"> | |
| <div class="input-wrapper"> | |
| <input type="text" id="messageInput" placeholder="پیام خود را بنویسید..." onkeypress="handleKeyPress(event)"> | |
| <div class="input-actions"> | |
| <button onclick="attachFile()"> | |
| <i class="fas fa-paperclip"></i> | |
| </button> | |
| <button onclick="showReactions()"> | |
| <i class="fas fa-smile"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <button class="btn" onclick="sendMessage()">ارسال</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Create Room Modal --> | |
| <div class="modal" id="createRoomModal"> | |
| <div class="modal-content"> | |
| <div class="modal-header"> | |
| <h2>ساخت اتاق جدید</h2> | |
| <button class="modal-close" onclick="closeCreateRoomModal()">×</button> | |
| </div> | |
| <div class="form-group"> | |
| <label for="roomName">نام اتاق</label> | |
| <input type="text" id="roomName" placeholder="نام اتاق را وارد کنید"> | |
| </div> | |
| <button class="btn" onclick="createRoom()">ایجاد اتاق</button> | |
| </div> | |
| </div> | |
| <!-- Reactions Panel --> | |
| <div class="reactions-panel" id="reactionsPanel"> | |
| <button class="reaction-btn" onclick="addReaction('😀')">😀</button> | |
| <button class="reaction-btn" onclick="addReaction('❤️')">❤️</button> | |
| <button class="reaction-btn" onclick="addReaction('👍')">👍</button> | |
| <button class="reaction-btn" onclick="addReaction('😂')">😂</button> | |
| <button class="reaction-btn" onclick="addReaction('🎉')">🎉</button> | |
| <button class="reaction-btn" onclick="addReaction('🔥')">🔥</button> | |
| </div> | |
| <!-- Toast Notification --> | |
| <div class="toast" id="toast"> | |
| <i class="fas fa-check-circle"></i> | |
| <span id="toastMessage">پیام موفقیتآمیز</span> | |
| </div> | |
| <script> | |
| // Global Variables | |
| let currentUser = null; | |
| let currentRoom = null; | |
| let rooms = []; | |
| let messages = {}; | |
| let reactions = {}; | |
| // Authentication | |
| function authenticate() { | |
| const phoneNumber = document.getElementById('phoneNumber').value; | |
| if (phoneNumber && phoneNumber.length === 11 && phoneNumber.startsWith('09')) { | |
| currentUser = { | |
| id: Date.now(), | |
| phone: phoneNumber, | |
| name: `کاربر ${phoneNumber.slice(-4)}` | |
| }; | |
| showToast('ورود موفقیتآمیز'); | |
| showChatInterface(); | |
| } else { | |
| showToast('لطفاً شماره موبایل معتبر وارد کنید', 'error'); | |
| } | |
| } | |
| function showChatInterface() { | |
| document.getElementById('authSection').style.display = 'none'; | |
| document.getElementById('chatInterface').style.display = 'block'; | |
| loadRooms(); | |
| } | |
| // Room Management | |
| function loadRooms() { | |
| // Simulate loading rooms | |
| rooms = [ | |
| { id: 1, name: 'اتاق عمومی', members: 3 }, | |
| { id: 2, name: 'گروه دوستان', members: 5 }, | |
| { id: 3, name: 'تیم کاری', members: 8 } | |
| ]; | |
| renderRooms(); | |
| } | |
| function renderRooms() { | |
| const roomsList = document.getElementById('roomsList'); | |
| roomsList.innerHTML = ''; | |
| rooms.forEach(room => { | |
| const roomElement = document.createElement('div'); | |
| roomElement.className = 'room-item'; | |
| roomElement.innerHTML = ` | |
| <div class="room-info"> | |
| <div class="room-name">${room.name}</div> | |
| <div class="room-members">${room.members} عضو</div> | |
| </div> | |
| <div class="room-actions"> | |
| <button onclick="joinRoom(${room.id})"><i class="fas fa-sign-in-alt"></i></button> | |
| <button onclick="deleteRoom(${room.id})"><i class="fas fa-trash"></i></button> | |
| </div> | |
| `; | |
| roomElement.onclick = () => selectRoom(room); | |
| roomsList.appendChild(roomElement); | |
| }); | |
| } | |
| function selectRoom(room) { | |
| currentRoom = room; | |
| document.getElementById('currentRoomName').textContent = room.name; | |
| document.getElementById('currentRoomMembers').textContent = `${room.members} عضو`; | |
| // Update active room | |
| document.querySelectorAll('.room-item').forEach(item => { | |
| item.classList.remove('active'); | |
| }); | |
| event.currentTarget.classList.add('active'); | |
| loadMessages(room.id); | |
| } | |
| function joinRoom(roomId) { | |
| const room = rooms.find(r => r.id === roomId); | |
| selectRoom(room); | |
| } | |
| function deleteRoom(roomId) { | |
| rooms = rooms.filter(r => r.id !== roomId); | |
| renderRooms(); | |
| showToast('اتاق حذف شد'); | |
| } | |
| function showCreateRoomModal() { | |
| document.getElementById('createRoomModal').classList.add('active'); | |
| } | |
| function closeCreateRoomModal() { | |
| document.getElementById('createRoomModal').classList.remove('active'); | |
| document.getElementById('roomName').value = ''; | |
| } | |
| function createRoom() { | |
| const roomName = document.getElementById('roomName').value; | |
| if (roomName && rooms.length < 3) { | |
| const newRoom = { | |
| id: Date.now(), | |
| name: roomName, | |
| members: 1 | |
| }; | |
| rooms.push(newRoom); | |
| renderRooms(); | |
| closeCreateRoomModal(); | |
| showToast('اتاق با موفقیت ایجاد شد'); | |
| } else if (rooms.length >= 3) { | |
| showToast('حداکثر ۳ اتاق میتوانید ایجاد کنید', 'warning'); | |
| } else { | |
| showToast('لطفاً نام اتاق را وارد کنید', 'error'); | |
| } | |
| } | |
| // Message System | |
| function loadMessages(roomId) { | |
| // Simulate loading messages | |
| if (!messages[roomId]) { | |
| messages[roomId] = [ | |
| { id: 1, sender: 'کاربر 1234', content: 'سلام! خوش آمدید به اتاق', time: '10:30', type: 'received' }, | |
| { id: 2, sender: currentUser.name, content: 'سلام! ممنون', time: '10:32', type: 'sent' }, | |
| { id: 3, sender: 'کاربر 5678', content: 'خوشحال شدم که اینجا هستید', time: '10:35', type: 'received' } | |
| ]; | |
| } | |
| renderMessages(roomId); | |
| } | |
| function renderMessages(roomId) { | |
| const messagesContainer = document.getElementById('messagesContainer'); | |
| messagesContainer.innerHTML = ''; | |
| messages[roomId].forEach(message => { | |
| const messageElement = createMessageElement(message); | |
| messagesContainer.appendChild(messageElement); | |
| }); | |
| messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
| } | |
| function createMessageElement(message) { | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = `message ${message.type}`; | |
| messageDiv.innerHTML = ` | |
| <div class="message-header"> | |
| <span>${message.sender}</span> | |
| <span>${message.time}</span> | |
| </div> | |
| <div class="message-content">${message.content}</div> | |
| <div class="message-reactions"> | |
| ${message.reactions ? message.reactions.map(r => | |
| `<div class="reaction">${r}</div>` | |
| ).join('') : ''} | |
| </div> | |
| <div class="message-actions"> | |
| <button onclick="replyToMessage(${message.id})"><i class="fas fa-reply"></i></button> | |
| <button onclick="deleteMessage(${message.id})"><i class="fas fa-trash"></i></button> | |
| </div> | |
| `; | |
| return messageDiv; | |
| } | |
| function sendMessage() { | |
| const input = document.getElementById('messageInput'); | |
| const content = input.value.trim(); | |
| if (content && currentRoom) { | |
| const newMessage = { | |
| id: Date.now(), | |
| sender: currentUser.name, | |
| content: content, | |
| time: new Date().toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }), | |
| type: 'sent' | |
| }; | |
| if (!messages[currentRoom.id]) { | |
| messages[currentRoom.id] = []; | |
| } | |
| messages[currentRoom.id].push(newMessage); | |
| renderMessages(currentRoom.id); | |
| input.value = ''; | |
| showToast('پیام ارسال شد'); | |
| } | |
| } | |
| function handleKeyPress(event) { | |
| if (event.key === 'Enter') { | |
| sendMessage(); | |
| } | |
| } | |
| function replyToMessage(messageId) { | |
| const input = document.getElementById('messageInput'); | |
| input.value = `@${messageId} `; | |
| input.focus(); | |
| showToast('در حال پاسخ به پیام...'); | |
| } | |
| function deleteMessage(messageId) { | |
| if (currentRoom) { | |
| messages[currentRoom.id] = messages[currentRoom.id].filter(m => m.id !== messageId); | |
| renderMessages(currentRoom.id); | |
| showToast('پیام حذف شد'); | |
| } | |
| } | |
| // Reactions System | |
| function showReactions() { | |
| const panel = document.getElementById('reactionsPanel'); | |
| panel.classList.toggle('active'); | |
| } | |
| function addReaction(emoji) { | |
| if (currentRoom) { | |
| const lastMessage = messages[currentRoom.id][messages[currentRoom.id].length - 1]; | |
| if (lastMessage) { | |
| if (!lastMessage.reactions) { | |
| lastMessage.reactions = []; | |
| } | |
| lastMessage.reactions.push(emoji); | |
| renderMessages(currentRoom.id); | |
| showToast('واکنش اضافه شد'); | |
| } | |
| } | |
| document.getElementById('reactionsPanel').classList.remove('active'); | |
| } | |
| // UI Functions | |
| function copyRoomLink() { | |
| if (currentRoom) { | |
| const link = `https://chatroom.com/room/${currentRoom.id}`; | |
| navigator.clipboard.writeText(link).then(() => { | |
| showToast('لینک اتاق کپی شد'); | |
| }); | |
| } | |
| } | |
| function showRoomInfo() { | |
| if (currentRoom) { | |
| showToast(`اطلاعات اتاق: ${currentRoom.name} - ${currentRoom.members} عضو`); | |
| } | |
| } | |
| function attachFile() { | |
| showToast('فایل پیوست شده است'); | |
| } | |
| // Toast Notification | |
| function showToast(message, type = 'success') { | |
| const toast = document.getElementById('toast'); | |
| const toastMessage = document.getElementById('toastMessage'); | |
| const icon = toast.querySelector('i'); | |
| toastMessage.textContent = message; | |
| // Set icon based on type | |
| icon.className = type === 'error' ? 'fas fa-exclamation-circle' : | |
| type === 'warning' ? 'fas fa-exclamation-triangle' : | |
| 'fas fa-check-circle'; | |
| toast.classList.add('show'); | |
| setTimeout(() => { | |
| toast.classList.remove('show'); | |
| }, 3000); | |
| } | |
| // Touch Gestures (simulated) | |
| let touchStartX = 0; | |
| let touchEndX = 0; | |
| document.addEventListener('touchstart', e => { | |
| touchStartX = e.changedTouches[0].screenX; | |
| }); | |
| document.addEventListener('touchend', e => { | |
| touchEndX = e.changedTouches[0].screenX; | |
| handleSwipe(); | |
| }); | |
| function handleSwipe() { | |
| if (touchEndX < touchStartX - 50) { | |
| // Swipe left - show sidebar on mobile | |
| if (window.innerWidth <= 768) { | |
| document.querySelector('.sidebar').style.display = 'flex'; | |
| } | |
| } | |
| if (touchEndX > touchStartX + 50) { | |
| // Swipe right - hide sidebar on mobile | |
| if (window.innerWidth <= 768) { | |
| document.querySelector('.sidebar').style.display = 'none'; | |
| } | |
| } | |
| } | |
| // Long press simulation | |
| let pressTimer; | |
| document.addEventListener('mousedown', e => { | |
| pressTimer = setTimeout(() => { | |
| // Long press action | |
| if (e.target.closest('.message')) { | |
| e.target.closest('.message').querySelector('.message-actions').style.opacity = '1'; | |
| } | |
| }, 500); | |
| }); | |
| document.addEventListener('mouseup', () => { | |
| clearTimeout(pressTimer); | |
| }); | |
| // Initialize | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Add some initial messages to make it look populated | |
| if (!messages[1]) { | |
| messages[1] = [ | |
| { id: 1, sender: 'کاربر 1234', content: 'سلام! خوش آمدید به اتاق', time: '10:30', type: 'received' }, | |
| { id: 2, sender: 'کاربر 5678', content: 'خوشحال شدم که اینجا هستید', time: '10:35', type: 'received' } | |
| ]; | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |