strenger-chat / static /js /script.js
prince1604
use native ui elements for url alerts instead of window.alert
76ab121
Raw
History Blame Contribute Delete
7.95 kB
document.addEventListener('DOMContentLoaded', () => {
// ================= DOM ELEMENTS =================
const screens = {
home: document.getElementById('home-screen'),
loading: document.getElementById('loading-screen'),
chat: document.getElementById('chat-screen')
};
// Inputs
const nickInput = document.getElementById('input-nick');
const interestsInput = document.getElementById('input-interests');
const chatInput = document.getElementById('chat-input');
// Buttons
const startBtn = document.getElementById('start-btn');
const cancelSearchBtn = document.getElementById('cancel-search-btn');
const skipBtn = document.getElementById('skip-btn');
const sendBtn = document.getElementById('send-btn');
// Display Areas
const messageLog = document.getElementById('messagelog');
const partnerNameDisplay = document.getElementById('partner-name');
const partnerStatusDisplay = document.getElementById('partner-status');
const loadingStatus = document.getElementById('loading-status');
// ================= STATE =================
let socket = null;
let isConnected = false;
let typingTimeout = null;
// ================= NAVIGATION =================
function showScreen(screenName) {
Object.values(screens).forEach(s => s.classList.remove('active'));
screens[screenName].classList.add('active');
}
// ================= WEBSOCKET LOGIC =================
function connect() {
if (socket) {
socket.close();
}
const nick = nickInput.value.trim() || "Stranger";
const interests = interestsInput.value.trim();
const clientId = Math.random().toString(36).substring(7);
const proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
// Encode query params
const url = `${proto}//${window.location.host}/ws/${clientId}?nick=${encodeURIComponent(nick)}&interests=${encodeURIComponent(interests)}`;
socket = new WebSocket(url);
socket.onopen = () => {
console.log("Connected to server");
loadingStatus.textContent = "Looking for a match...";
};
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
handleMessage(data);
};
socket.onclose = () => {
console.log("Disconnected");
isConnected = false;
updatePartnerStatus("Disconnected", "offline");
};
socket.onerror = (err) => {
console.error("WebSocket Error:", err);
loadingStatus.textContent = "Connection Error. Retrying...";
};
}
function handleMessage(data) {
switch (data.type) {
case 'connected':
isConnected = true;
partnerNameDisplay.textContent = data.partner;
updatePartnerStatus("Online", "online");
messageLog.innerHTML = ''; // Clear chat
addSystemMessage(`You are talking to ${data.partner}. Say Hi!`);
showScreen('chat');
break;
case 'waiting':
showScreen('loading');
loadingStatus.textContent = data.message || "Searching...";
break;
case 'message':
addMessage(data.content, 'stranger', data.sender);
// Clear typing indicator if message received
updatePartnerStatus("Online", "online");
break;
case 'partner_disconnected':
isConnected = false;
updatePartnerStatus("Stranger Disconnected", "offline");
addSystemMessage("Partner disconnected. Press ESC to find new.");
break;
case 'typing':
if (data.state) {
updatePartnerStatus("Typing...", "typing");
} else {
updatePartnerStatus("Online", "online");
}
break;
}
}
function sendMessage() {
const content = chatInput.value.trim();
const urlPattern = /(https?:\/\/[^\s]+)|(www\.[^\s]+)|(\b[a-zA-Z0-9-]+\.[a-zA-Z]{2,}\b)/i;
if (urlPattern.test(content)) {
addSystemMessage("⚠ URLs are not allowed.");
chatInput.value = '';
return;
}
if (content && isConnected) {
socket.send(JSON.stringify({ type: 'message', content: content }));
addMessage(content, 'user');
chatInput.value = '';
}
}
function skip() {
if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: 'skip' }));
showScreen('loading');
loadingStatus.textContent = "Skipping... finding new match";
messageLog.innerHTML = '';
} else {
// Reconnect if socket closed
connect();
showScreen('loading');
}
}
// ================= UI HELPERS =================
function addMessage(text, type, senderName = null) {
const div = document.createElement('div');
div.className = `message ${type}`;
// Allow HTML for bolding names in group chat
if (senderName && type === 'stranger' && text.includes('<b>')) {
div.innerHTML = text;
} else {
div.textContent = text;
}
messageLog.appendChild(div);
scrollToBottom();
}
function addSystemMessage(text) {
const div = document.createElement('div');
div.className = 'system-message';
div.textContent = text;
messageLog.appendChild(div);
scrollToBottom();
}
function scrollToBottom() {
messageLog.scrollTop = messageLog.scrollHeight;
}
function updatePartnerStatus(text, state) {
partnerStatusDisplay.textContent = text;
// Visual indicator could be added here
if (state === 'typing') {
partnerStatusDisplay.style.color = 'var(--primary)';
} else if (state === 'offline') {
partnerStatusDisplay.style.color = 'var(--danger)';
} else {
partnerStatusDisplay.style.color = 'var(--primary)';
}
}
// ================= EVENTS =================
startBtn.addEventListener('click', () => {
showScreen('loading');
connect();
});
cancelSearchBtn.addEventListener('click', () => {
if (socket) socket.close();
showScreen('home');
});
sendBtn.addEventListener('click', sendMessage);
chatInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
sendMessage();
}
});
chatInput.addEventListener('paste', (e) => {
const pastedText = (e.clipboardData || window.clipboardData).getData('text');
const urlPattern = /(https?:\/\/[^\s]+)|(www\.[^\s]+)|(\b[a-zA-Z0-9-]+\.[a-zA-Z]{2,}\b)/i;
if (urlPattern.test(pastedText)) {
e.preventDefault();
addSystemMessage("⚠ URLs are not allowed.");
}
});
// Typing Indicator Logic
chatInput.addEventListener('input', () => {
if (!isConnected) return;
// Send typing ON
socket.send(JSON.stringify({ type: 'typing', state: true }));
// Debounce typing OFF
clearTimeout(typingTimeout);
typingTimeout = setTimeout(() => {
if (isConnected) {
socket.send(JSON.stringify({ type: 'typing', state: false }));
}
}, 1000); // 1 second after stop typing
});
skipBtn.addEventListener('click', skip);
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
if (screens.chat.classList.contains('active')) {
skip();
}
}
});
});