Spaces:
Running
Running
proč se mi odesílají zprávy které napíšu i tak že to ukáže jako druhý náhodný živatel - Follow Up Deployment
f168725 verified | <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Gomegle - Chat s náhodnými ľuďmi</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> | |
| .typing-indicator::after { | |
| content: "..."; | |
| animation: typing 1.5s infinite; | |
| display: inline-block; | |
| width: 0; | |
| } | |
| @keyframes typing { | |
| 0% { content: "."; } | |
| 33% { content: ".."; } | |
| 66% { content: "..."; } | |
| } | |
| .chat-messages { | |
| scrollbar-width: thin; | |
| scrollbar-color: #4B5563 #1F2937; | |
| } | |
| .chat-messages::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| .chat-messages::-webkit-scrollbar-track { | |
| background: #1F2937; | |
| } | |
| .chat-messages::-webkit-scrollbar-thumb { | |
| background-color: #4B5563; | |
| border-radius: 3px; | |
| } | |
| .pulse-animation { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 0.6; } | |
| 50% { opacity: 1; } | |
| 100% { opacity: 0.6; } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col"> | |
| <!-- Header --> | |
| <header class="bg-gray-800 py-4 px-6 shadow-lg"> | |
| <div class="container mx-auto flex justify-between items-center"> | |
| <div class="flex items-center space-x-2"> | |
| <i class="fas fa-comments text-[#ae00eb] text-2xl"></i> | |
| <h1 class="text-xl font-bold">Gomegle</h1> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <button id="theme-toggle" class="text-gray-300 hover:text-white"> | |
| <i class="fas fa-moon"></i> | |
| </button> | |
| <button id="info-btn" class="text-gray-300 hover:text-white"> | |
| <i class="fas fa-info-circle"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <main class="flex-grow container mx-auto px-4 py-8 flex flex-col"> | |
| <!-- Connection Status --> | |
| <div id="status-container" class="mb-6 text-center"> | |
| <div id="disconnected-view" class="bg-gray-800 rounded-lg p-6 shadow-lg"> | |
| <div class="flex flex-col items-center"> | |
| <i class="fas fa-user-friends text-5xl text-blue-400 mb-4"></i> | |
| <h2 class="text-2xl font-bold mb-2">Chcete chatovať?</h2> | |
| <p class="text-gray-400 mb-6">Kliknite na tlačidlo nižšie pre spojenie s náhodným človekom</p> | |
| <button id="connect-btn" class="bg-[#ae00eb] hover:bg-[#9a00d1] text-white font-bold py-3 px-8 rounded-full transition-all transform hover:scale-105 flex items-center"> | |
| <i class="fas fa-random mr-2"></i> Nájsť partnera | |
| </button> | |
| </div> | |
| </div> | |
| <div id="connecting-view" class="hidden bg-gray-800 rounded-lg p-6 shadow-lg"> | |
| <div class="flex flex-col items-center"> | |
| <div class="relative mb-4"> | |
| <div class="w-16 h-16 rounded-full bg-blue-900 opacity-60 pulse-animation"></div> | |
| <div class="w-16 h-16 rounded-full bg-blue-700 opacity-80 pulse-animation absolute top-0 left-0" style="animation-delay: 0.5s;"></div> | |
| <div class="w-16 h-16 rounded-full bg-blue-500 pulse-animation absolute top-0 left-0" style="animation-delay: 1s;"></div> | |
| <i class="fas fa-search absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white text-xl"></i> | |
| </div> | |
| <h2 class="text-2xl font-bold mb-2">Hľadáme niekoho...</h2> | |
| <p class="text-gray-400 mb-4">Čakajte kým vás spojíme s náhodným partnerom</p> | |
| <button id="cancel-connect-btn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-6 rounded-full transition-all"> | |
| Zrušiť | |
| </button> | |
| </div> | |
| </div> | |
| <div id="connected-view" class="hidden bg-gray-800 rounded-lg p-6 shadow-lg"> | |
| <div class="flex flex-col items-center"> | |
| <div class="relative mb-4"> | |
| <div class="w-16 h-16 rounded-full bg-green-900 opacity-60"></div> | |
| <div class="w-16 h-16 rounded-full bg-green-700 opacity-80 absolute top-0 left-0"></div> | |
| <div class="w-16 h-16 rounded-full bg-green-500 absolute top-0 left-0"></div> | |
| <i class="fas fa-check absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white text-xl"></i> | |
| </div> | |
| <h2 class="text-2xl font-bold mb-2">Pripojené!</h2> | |
| <p class="text-gray-400 mb-4">Teraz chatujete s náhodným človekom</p> | |
| <div class="flex space-x-4"> | |
| <button id="disconnect-btn" class="bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-6 rounded-full transition-all"> | |
| <i class="fas fa-times mr-2"></i> Odpojiť | |
| </button> | |
| <button id="new-partner-btn" class="bg-[#ae00eb] hover:bg-[#9a00d1] text-white font-bold py-2 px-6 rounded-full transition-all"> | |
| <i class="fas fa-sync-alt mr-2"></i> Nový partner | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Chat Container --> | |
| <div id="chat-container" class="hidden flex-grow flex flex-col bg-gray-800 rounded-lg shadow-lg overflow-hidden"> | |
| <!-- Messages --> | |
| <div id="chat-messages" class="flex-grow p-4 overflow-y-auto chat-messages max-h-96"> | |
| <!-- Messages will be inserted here by JavaScript --> | |
| <div id="welcome-message" class="text-center py-8 text-gray-400"> | |
| <i class="fas fa-comment-dots text-4xl mb-4"></i> | |
| <p class="text-lg">Pozdravte svojho nového chatovacieho partnera!</p> | |
| <p class="text-sm mt-2">Správy sú end-to-end šifrované</p> | |
| </div> | |
| </div> | |
| <!-- Typing Indicator --> | |
| <div id="typing-indicator" class="hidden bg-gray-700 px-4 py-2 text-sm text-gray-400"> | |
| <span class="typing-indicator">Partner píše...</span> | |
| </div> | |
| <!-- Message Input --> | |
| <div class="bg-gray-700 p-4"> | |
| <div class="flex items-center"> | |
| <input type="text" id="message-input" placeholder="Napíšte svoju správu..." class="flex-grow bg-gray-600 text-white rounded-l-full py-3 px-4 focus:outline-none focus:ring-2 focus:ring-[#ae00eb]"> | |
| <button id="send-btn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-r-full transition-all"> | |
| <i class="fas fa-paper-plane"></i> | |
| </button> | |
| </div> | |
| <div class="flex justify-between mt-2 text-xs text-gray-400"> | |
| <div> | |
| <button id="emoji-btn" class="hover:text-blue-400 mr-3"> | |
| <i class="far fa-smile"></i> Emoji | |
| </button> | |
| <button id="attachment-btn" class="hover:text-[#ae00eb]"> | |
| <i class="fas fa-paperclip"></i> Attach | |
| </button> | |
| </div> | |
| <div> | |
| <span id="char-count">0/500</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Interests Selection (Hidden by default) --> | |
| <div id="interests-container" class="hidden mt-6 bg-gray-800 rounded-lg p-6 shadow-lg"> | |
| <h3 class="text-xl font-bold mb-4">Select your interests to find better matches</h3> | |
| <div class="flex flex-wrap gap-2 mb-6"> | |
| <button class="interest-tag bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-full transition-all"> | |
| Music | |
| </button> | |
| <button class="interest-tag bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-full transition-all"> | |
| Gaming | |
| </button> | |
| <button class="interest-tag bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-full transition-all"> | |
| Movies | |
| </button> | |
| <button class="interest-tag bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-full transition-all"> | |
| Sports | |
| </button> | |
| <button class="interest-tag bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-full transition-all"> | |
| Technology | |
| </button> | |
| <button class="interest-tag bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-full transition-all"> | |
| Travel | |
| </button> | |
| <button class="interest-tag bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-full transition-all"> | |
| Food | |
| </button> | |
| <button class="interest-tag bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-full transition-all"> | |
| Art | |
| </button> | |
| </div> | |
| <div class="flex justify-end"> | |
| <button id="save-interests-btn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded-full transition-all"> | |
| Save Interests | |
| </button> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Footer --> | |
| <footer class="bg-gray-800 py-4 px-6"> | |
| <div class="container mx-auto text-center text-gray-400 text-sm"> | |
| <p>Gomegle © 2023 | <a href="#" class="hover:text-[#ae00eb]">Podmienky</a> | <a href="#" class="hover:text-[#ae00eb]">Ochrana súkromia</a> | <a href="#" class="hover:text-[#ae00eb]">Bezpečnosť</a></p> | |
| <p class="mt-2">Spojte sa s náhodnými ľuďmi po celom svete</p> | |
| </div> | |
| </footer> | |
| <!-- Info Modal --> | |
| <div id="info-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> | |
| <div class="bg-gray-800 rounded-lg p-6 max-w-md w-full mx-4 shadow-xl"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-bold">O Gomegle</h3> | |
| <button id="close-info-modal" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="space-y-4"> | |
| <p>Gomegle vás spája s náhodnými ľuďmi pre anonymné konverzácie.</p> | |
| <p><strong>Ako to funguje:</strong></p> | |
| <ol class="list-decimal list-inside space-y-2"> | |
| <li>Kliknite na "Nájsť partnera" pre začatie vyhľadávania</li> | |
| <li>Spojíme vás s náhodným používateľom</li> | |
| <li>Chatujte anonymne (žiadne osobné údaje sa nezdieľajú)</li> | |
| <li>Kliknite na "Odpojiť" pre ukončenie chatu</li> | |
| </ol> | |
| <div class="bg-gray-700 p-3 rounded-lg"> | |
| <p class="text-sm"><i class="fas fa-exclamation-triangle text-yellow-400 mr-2"></i> Pamätajte byť zdvorilí a dodržiavať pravidlá komunity.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // DOM Elements | |
| const connectBtn = document.getElementById('connect-btn'); | |
| const cancelConnectBtn = document.getElementById('cancel-connect-btn'); | |
| const disconnectBtn = document.getElementById('disconnect-btn'); | |
| const newPartnerBtn = document.getElementById('new-partner-btn'); | |
| const messageInput = document.getElementById('message-input'); | |
| const sendBtn = document.getElementById('send-btn'); | |
| const chatMessages = document.getElementById('chat-messages'); | |
| const typingIndicator = document.getElementById('typing-indicator'); | |
| const charCount = document.getElementById('char-count'); | |
| const emojiBtn = document.getElementById('emoji-btn'); | |
| const attachmentBtn = document.getElementById('attachment-btn'); | |
| const infoBtn = document.getElementById('info-btn'); | |
| const closeInfoModal = document.getElementById('close-info-modal'); | |
| const infoModal = document.getElementById('info-modal'); | |
| const themeToggle = document.getElementById('theme-toggle'); | |
| const interestsContainer = document.getElementById('interests-container'); | |
| const saveInterestsBtn = document.getElementById('save-interests-btn'); | |
| // Status views | |
| const disconnectedView = document.getElementById('disconnected-view'); | |
| const connectingView = document.getElementById('connecting-view'); | |
| const connectedView = document.getElementById('connected-view'); | |
| const chatContainer = document.getElementById('chat-container'); | |
| const welcomeMessage = document.getElementById('welcome-message'); | |
| // State | |
| let isConnected = false; | |
| let isTyping = false; | |
| let typingTimeout; | |
| let partnerTyping = false; | |
| let partnerTypingInterval; | |
| // WebSocket connection | |
| let socket; | |
| let userId = Math.random().toString(36).substring(2, 15); | |
| let partnerId = null; | |
| // Initialize | |
| function init() { | |
| // Set up event listeners | |
| connectBtn.addEventListener('click', startConnection); | |
| cancelConnectBtn.addEventListener('click', cancelConnection); | |
| disconnectBtn.addEventListener('click', disconnect); | |
| newPartnerBtn.addEventListener('click', findNewPartner); | |
| messageInput.addEventListener('input', handleTyping); | |
| messageInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter' && messageInput.value.trim() !== '') { | |
| sendMessage(); | |
| } | |
| }); | |
| sendBtn.addEventListener('click', sendMessage); | |
| infoBtn.addEventListener('click', () => infoModal.classList.remove('hidden')); | |
| closeInfoModal.addEventListener('click', () => infoModal.classList.add('hidden')); | |
| themeToggle.addEventListener('click', toggleTheme); | |
| saveInterestsBtn.addEventListener('click', saveInterests); | |
| // Set up character count | |
| messageInput.addEventListener('input', updateCharCount); | |
| updateCharCount(); | |
| // Set up interest tags | |
| document.querySelectorAll('.interest-tag').forEach(tag => { | |
| tag.addEventListener('click', () => { | |
| tag.classList.toggle('bg-gray-700'); | |
| tag.classList.toggle('bg-blue-600'); | |
| }); | |
| }); | |
| // Check for saved theme preference | |
| if (localStorage.getItem('theme') === 'dark' || | |
| (!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) { | |
| document.documentElement.classList.add('dark'); | |
| themeToggle.innerHTML = '<i class="fas fa-sun"></i>'; | |
| } else { | |
| document.documentElement.classList.remove('dark'); | |
| themeToggle.innerHTML = '<i class="fas fa-moon"></i>'; | |
| } | |
| } | |
| // Theme toggle | |
| function toggleTheme() { | |
| if (document.documentElement.classList.contains('dark')) { | |
| document.documentElement.classList.remove('dark'); | |
| localStorage.setItem('theme', 'light'); | |
| themeToggle.innerHTML = '<i class="fas fa-moon"></i>'; | |
| } else { | |
| document.documentElement.classList.add('dark'); | |
| localStorage.setItem('theme', 'dark'); | |
| themeToggle.innerHTML = '<i class="fas fa-sun"></i>'; | |
| } | |
| } | |
| // Start connection | |
| function startConnection() { | |
| disconnectedView.classList.add('hidden'); | |
| connectingView.classList.remove('hidden'); | |
| // Connect to public demo WebSocket server | |
| socket = new WebSocket('wss://ws.ifelse.io'); | |
| socket.onopen = function(e) { | |
| console.log("Connected to WebSocket server"); | |
| connectingView.classList.add('hidden'); | |
| connectedView.classList.remove('hidden'); | |
| chatContainer.classList.remove('hidden'); | |
| isConnected = true; | |
| // Send connection request | |
| socket.send(JSON.stringify({ | |
| type: 'connect', | |
| userId: userId | |
| })); | |
| }; | |
| socket.onmessage = function(event) { | |
| // This demo server just echoes messages back | |
| // In a real app you'd parse JSON and handle different message types | |
| if (event.data.startsWith('{')) { | |
| const message = JSON.parse(event.data); | |
| // Handle JSON messages | |
| } else { | |
| // Show echoed messages as from "Partner" | |
| addMessage("Partner", event.data, false); | |
| } | |
| }; | |
| socket.onclose = function(event) { | |
| if (event.wasClean) { | |
| addSystemMessage(`Connection closed cleanly, code=${event.code} reason=${event.reason}`); | |
| } else { | |
| addSystemMessage('Connection died'); | |
| } | |
| disconnect(); | |
| }; | |
| socket.onerror = function(error) { | |
| addSystemMessage(`WebSocket error: ${error.message}`); | |
| disconnect(); | |
| }; | |
| } | |
| // Cancel connection | |
| function cancelConnection() { | |
| connectingView.classList.add('hidden'); | |
| disconnectedView.classList.remove('hidden'); | |
| } | |
| // Disconnect | |
| function disconnect() { | |
| isConnected = false; | |
| // Notify server about disconnection | |
| if (socket) { | |
| socket.send(JSON.stringify({ | |
| type: 'disconnect', | |
| partnerId: partnerId | |
| })); | |
| socket.close(); | |
| } | |
| connectedView.classList.add('hidden'); | |
| chatContainer.classList.add('hidden'); | |
| disconnectedView.classList.remove('hidden'); | |
| // Clear chat messages | |
| while (chatMessages.firstChild) { | |
| chatMessages.removeChild(chatMessages.firstChild); | |
| } | |
| // Reset welcome message | |
| welcomeMessage.classList.remove('hidden'); | |
| // Clear typing indicators | |
| clearTimeout(typingTimeout); | |
| typingIndicator.classList.add('hidden'); | |
| // Reset partner ID | |
| partnerId = null; | |
| } | |
| // Find new partner | |
| function findNewPartner() { | |
| disconnect(); | |
| startConnection(); | |
| } | |
| // Handle typing | |
| function handleTyping() { | |
| if (!isTyping && isConnected && socket) { | |
| isTyping = true; | |
| socket.send(JSON.stringify({ | |
| type: 'typing', | |
| isTyping: true, | |
| to: partnerId | |
| })); | |
| } | |
| // Reset the typing indicator after 3 seconds of inactivity | |
| clearTimeout(typingTimeout); | |
| typingTimeout = setTimeout(() => { | |
| if (isTyping) { | |
| isTyping = false; | |
| socket.send(JSON.stringify({ | |
| type: 'typing', | |
| isTyping: false, | |
| to: partnerId | |
| })); | |
| } | |
| }, 3000); | |
| } | |
| // Simulate partner typing (for demo purposes) | |
| function simulatePartnerTyping() { | |
| partnerTypingInterval = setInterval(() => { | |
| if (Math.random() > 0.7) { // 30% chance partner starts typing | |
| partnerTyping = true; | |
| typingIndicator.classList.remove('hidden'); | |
| setTimeout(() => { | |
| if (partnerTyping) { | |
| partnerTyping = false; | |
| typingIndicator.classList.add('hidden'); | |
| // Add a random message from the partner | |
| const messages = [ | |
| "Hi there! How are you?", | |
| "What brings you to RandomChat today?", | |
| "Nice to meet you!", | |
| "Do you come here often? 😄", | |
| "What are your interests?", | |
| "The weather is nice today, isn't it?", | |
| "Have you tried the new chat features?" | |
| ]; | |
| addMessage(mockUsers[Math.floor(Math.random() * mockUsers.length)].name, messages[Math.floor(Math.random() * messages.length)], false); | |
| } | |
| }, 1000 + Math.random() * 3000); | |
| } | |
| }, 8000); // Check every 8 seconds | |
| } | |
| // Send message | |
| function sendMessage() { | |
| const message = messageInput.value.trim(); | |
| if (message === '' || !isConnected || !socket) return; | |
| // Add message to chat | |
| addMessage("You", message, true); | |
| // Send message via WebSocket | |
| socket.send(JSON.stringify({ | |
| type: 'message', | |
| text: message, | |
| to: partnerId | |
| })); | |
| // Clear input | |
| messageInput.value = ''; | |
| updateCharCount(); | |
| } | |
| // Add message to chat | |
| function addMessage(sender, text, isUser) { | |
| // Hide welcome message if it's the first message | |
| if (welcomeMessage && !welcomeMessage.classList.contains('hidden')) { | |
| welcomeMessage.classList.add('hidden'); | |
| } | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = `mb-4 flex ${isUser ? 'justify-end' : 'justify-start'}`; | |
| const messageContent = document.createElement('div'); | |
| messageContent.className = `max-w-xs lg:max-w-md px-4 py-2 rounded-lg ${isUser ? 'bg-blue-600 rounded-tr-none' : 'bg-gray-700 rounded-tl-none'}`; | |
| if (!isUser) { | |
| const senderName = document.createElement('div'); | |
| senderName.className = 'text-xs font-semibold text-blue-300 mb-1'; | |
| senderName.textContent = sender; | |
| messageContent.appendChild(senderName); | |
| } | |
| const messageText = document.createElement('div'); | |
| messageText.className = 'text-white'; | |
| messageText.textContent = text; | |
| messageContent.appendChild(messageText); | |
| const time = document.createElement('div'); | |
| time.className = `text-xs mt-1 text-right ${isUser ? 'text-blue-200' : 'text-gray-400'}`; | |
| const now = new Date(); | |
| time.textContent = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); | |
| messageContent.appendChild(time); | |
| messageDiv.appendChild(messageContent); | |
| chatMessages.appendChild(messageDiv); | |
| // Scroll to bottom | |
| chatMessages.scrollTop = chatMessages.scrollHeight; | |
| } | |
| // Update character count | |
| function updateCharCount() { | |
| const count = messageInput.value.length; | |
| charCount.textContent = `${count}/500`; | |
| if (count > 450) { | |
| charCount.classList.add('text-yellow-400'); | |
| charCount.classList.remove('text-gray-400'); | |
| } else if (count > 490) { | |
| charCount.classList.add('text-red-400'); | |
| charCount.classList.remove('text-yellow-400'); | |
| } else { | |
| charCount.classList.add('text-gray-400'); | |
| charCount.classList.remove('text-yellow-400', 'text-red-400'); | |
| } | |
| } | |
| // Save interests | |
| function saveInterests() { | |
| interestsContainer.classList.add('hidden'); | |
| // In a real app, we'd save the selected interests to the server | |
| } | |
| // Initialize the app | |
| init(); | |
| </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=ultronek01/gomegle" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |