transient.chat/static/assets/js/server_list.js

259 lines
No EOL
9.5 KiB
JavaScript

document.addEventListener("DOMContentLoaded", async () => {
const username = localStorage.getItem('username');
const userKey = localStorage.getItem('userKey');
if (!username || !userKey) {
window.location.href = '/';
return;
}
try {
const response = await fetch('/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, key: userKey })
});
if (!response.ok) {
localStorage.clear();
window.location.href = '/';
return;
}
} catch (err) {
console.error('Validation failed:', err);
localStorage.clear();
window.location.href = '/';
return;
}
function escapeHtml(text) {
if (!text) return text;
return text
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
// User header bar
const userInfoEl = document.getElementById('user-info');
const logoutBtn = document.createElement('button');
logoutBtn.textContent = 'Logout';
logoutBtn.className = 'logout-btn';
logoutBtn.onclick = async () => {
if (confirm("Are you sure you want to logout? This releases your username.")) {
try {
await fetch('/logout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, key: userKey })
});
} catch (e) {
console.error("Logout request failed:", e);
}
localStorage.clear();
sessionStorage.clear();
window.location.href = '/';
}
};
const userSpan = document.createElement('span');
userSpan.innerHTML = `Logged in as: <strong>${escapeHtml(username)}</strong>`;
userInfoEl.append(logoutBtn, userSpan);
const activeRoomsContainer = document.getElementById('active-rooms-container');
const statsBadge = document.getElementById('stats-badge');
// Modal elements
const joinModal = document.getElementById('join-modal');
const joinModalForm = document.getElementById('join-modal-form');
const modalRoomTitle = document.getElementById('modal-room-title');
const modalPasswordInput = document.getElementById('modal-room-password');
const modalCancelBtn = document.getElementById('modal-cancel-btn');
let pendingJoinRoom = null;
let pendingJoinHasWP = false;
function openJoinModal(roomName, hasWP) {
pendingJoinRoom = roomName;
pendingJoinHasWP = hasWP;
modalRoomTitle.textContent = `🔒 Join "${roomName}"`;
modalPasswordInput.value = '';
joinModal.classList.remove('hidden');
modalPasswordInput.focus();
}
function closeJoinModal() {
joinModal.classList.add('hidden');
pendingJoinRoom = null;
}
if (modalCancelBtn) {
modalCancelBtn.addEventListener('click', closeJoinModal);
}
if (joinModalForm) {
joinModalForm.addEventListener('submit', async (e) => {
e.preventDefault();
const password = modalPasswordInput.value.trim();
if (!password || !pendingJoinRoom) return;
const joinBtn = document.getElementById('modal-join-btn');
if (joinBtn) joinBtn.disabled = true;
try {
const res = await fetch('/rooms/join', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
room: pendingJoinRoom,
password: password,
username: username,
key: userKey
})
});
if (joinBtn) joinBtn.disabled = false;
if (!res.ok) {
const err = await res.json().catch(() => ({}));
alert(err.error || 'Incorrect room password.');
modalPasswordInput.value = '';
modalPasswordInput.focus();
return;
}
// Success
sessionStorage.setItem(`room_password_${pendingJoinRoom}`, password);
const wpParam = pendingJoinHasWP ? '&watchparty=1' : '';
window.location.href = `/chat.html?room=${encodeURIComponent(pendingJoinRoom)}${wpParam}`;
} catch (err) {
if (joinBtn) joinBtn.disabled = false;
console.error('Join error:', err);
alert('Network error while joining room.');
}
});
}
async function loadActiveRooms() {
try {
const res = await fetch('/rooms');
if (!res.ok) throw new Error('Failed to fetch rooms');
const data = await res.json();
const rooms = data.active_rooms || [];
const uniqueUsers = data.unique_users || 0;
statsBadge.innerHTML = `🟢 Active Rooms: <strong>${rooms.length}</strong> &nbsp;•&nbsp; 👥 Online Users: <strong>${uniqueUsers}</strong>`;
activeRoomsContainer.innerHTML = '';
if (rooms.length === 0) {
activeRoomsContainer.innerHTML = `
<div class="empty-state">
No active rooms right now.<br>Create an on-demand room below to start chatting!
</div>
`;
return;
}
rooms.forEach(room => {
const card = document.createElement('div');
card.className = 'room-card';
const left = document.createElement('div');
left.className = 'room-info-left';
const titleLink = document.createElement('span');
titleLink.className = 'room-title-link';
titleLink.textContent = room.name;
const badges = document.createElement('div');
badges.className = 'room-badges';
badges.innerHTML = `
<span>👥 ${room.users} user${room.users === 1 ? '' : 's'}</span>
<span class="badge-encrypted">🔒 Encrypted</span>
${room.has_watchparty ? '<span class="badge-watchparty">🎬 Watch Party</span>' : ''}
`;
left.append(titleLink, badges);
const joinBtn = document.createElement('button');
joinBtn.textContent = 'Join Room';
const handleJoin = () => {
const storedPass = sessionStorage.getItem(`room_password_${room.name}`);
if (storedPass) {
const wpParam = room.has_watchparty ? '&watchparty=1' : '';
window.location.href = `/chat.html?room=${encodeURIComponent(room.name)}${wpParam}`;
} else {
openJoinModal(room.name, room.has_watchparty);
}
};
titleLink.addEventListener('click', handleJoin);
joinBtn.addEventListener('click', handleJoin);
card.append(left, joinBtn);
activeRoomsContainer.appendChild(card);
});
} catch (err) {
console.error('Failed to load active rooms:', err);
statsBadge.textContent = 'Failed to load rooms';
}
}
await loadActiveRooms();
setInterval(loadActiveRooms, 3000); // Poll active rooms every 3 seconds
// On-Demand Room Creation Form
const createRoomForm = document.getElementById('create-room-form');
if (createRoomForm) {
createRoomForm.addEventListener('submit', async (e) => {
e.preventDefault();
const roomName = document.getElementById('new-room-name').value.trim();
const password = document.getElementById('new-room-password').value.trim();
const isWatchParty = document.getElementById('new-room-watchparty').checked;
if (!roomName || !password) {
alert('Please enter both a room name and password.');
return;
}
const createBtn = document.getElementById('create-room-btn');
createBtn.disabled = true;
try {
const res = await fetch('/rooms/join', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
room: roomName,
password: password,
username: username,
key: userKey
})
});
createBtn.disabled = false;
if (!res.ok) {
const err = await res.json().catch(() => ({}));
alert(err.error || 'Failed to create room.');
return;
}
// Store password in session
sessionStorage.setItem(`room_password_${roomName}`, password);
const wpParam = isWatchParty ? '&watchparty=1' : '';
window.location.href = `/chat.html?room=${encodeURIComponent(roomName)}${wpParam}`;
} catch (err) {
createBtn.disabled = false;
console.error('Room creation error:', err);
alert('Network error while creating room.');
}
});
}
});