From 63e2e36511e14f6d07bce44f05adade42a37d8bb Mon Sep 17 00:00:00 2001 From: Sam Hadow Date: Mon, 10 Mar 2025 15:07:14 +0100 Subject: [PATCH] tabbed navigation + db request fix --- src/db.js | 4 +-- src/public/chat.js | 4 ++- src/public/rooms.js | 73 ++++++++++++++++++++++++++++++++++++++------ src/public/style.css | 34 +++++++++++++++++++++ 4 files changed, 103 insertions(+), 12 deletions(-) diff --git a/src/db.js b/src/db.js index 6ee1366..d665441 100644 --- a/src/db.js +++ b/src/db.js @@ -142,10 +142,10 @@ const database = { `SELECT m.room_uuid, u.pubkey FROM room_members m, users u WHERE m.user_uuid = u.uuid - AND m.room_uuid IN ( + AND m.room_uuid in ( SELECT room_uuid FROM room_members - WHERE user_uuid != (SELECT uuid FROM users WHERE pubkey = $1) + WHERE user_uuid = (SELECT uuid FROM users WHERE pubkey = $1) ) AND u.pubkey != $1`, [pubkey] ); diff --git a/src/public/chat.js b/src/public/chat.js index be33d8f..9b122ce 100644 --- a/src/public/chat.js +++ b/src/public/chat.js @@ -42,7 +42,9 @@ socket.on('chat message', (msg, room, tag_received, iv, nonce) => { console.log(tag); console.log(tag_received); messages.appendChild(item); - window.scrollTo(0, document.body.scrollHeight); + if (document.getElementById(`room-${room}`).style.display === 'block') { + window.scrollTo(0, document.body.scrollHeight); + } }); socket.on('key exchange', (user_pubkey, pubkey, part) => { diff --git a/src/public/rooms.js b/src/public/rooms.js index 2f67363..c10108c 100644 --- a/src/public/rooms.js +++ b/src/public/rooms.js @@ -10,37 +10,92 @@ async function render_rooms_wrapper() { function render_rooms(room_info) { const roomsContainer = document.getElementById('rooms'); - roomsContainer.innerHTML= ''; + roomsContainer.innerHTML = ''; - room_info.forEach(([roomId, pubkey]) => { + const tabBar = document.createElement('div'); + tabBar.className = 'tab-bar'; + roomsContainer.appendChild(tabBar); + + const contentContainer = document.createElement('div'); + contentContainer.className = 'room-content-container'; + roomsContainer.appendChild(contentContainer); + + room_info.forEach(([roomId, pubkey], index) => { + // tab button + const tabButton = document.createElement('button'); + tabButton.className = 'tab-button'; + tabButton.textContent = roomId; + tabButton.dataset.roomId = roomId; + tabButton.addEventListener('click', () => openRoom(roomId)); + tabBar.appendChild(tabButton); + + // room content const roomDiv = document.createElement('div'); roomDiv.id = `room-${roomId}`; - roomDiv.classList.add(`key-${pubkey}`); + roomDiv.className = 'room-content'; + + // public key textarea + const pubKeyText = document.createElement('textarea'); + pubKeyText.value = pubkey; + pubKeyText.readOnly = true; + roomDiv.appendChild(pubKeyText); + + // messages list const messagesUl = document.createElement('ul'); messagesUl.id = `messages-${roomId}`; - messagesUl.classList.add(`key-${pubkey}`); + messagesUl.className = `key-${pubkey}`; + roomDiv.appendChild(messagesUl); + + // message form const form = document.createElement('form'); form.id = `form-${roomId}`; - form.classList.add(`key-${pubkey}`); - form.action = ''; + form.className = `key-${pubkey}`; + const input = document.createElement('input'); input.id = `input-${roomId}`; - input.classList.add(`key-${pubkey}`); + input.className = `key-${pubkey}`; input.autocomplete = 'off'; + const button = document.createElement('button'); button.textContent = 'Send'; form.appendChild(input); form.appendChild(button); - roomDiv.appendChild(messagesUl); roomDiv.appendChild(form); + contentContainer.appendChild(roomDiv); - roomsContainer.appendChild(roomDiv); + // show first room by default + if (index === 0) { + roomDiv.style.display = 'block'; + tabButton.classList.add('active'); + } else { + roomDiv.style.display = 'none'; + } create_listener(form, input); }); } +// handle tab switching +function openRoom(roomId) { + const roomIdStr = String(roomId); + + document.querySelectorAll('.room-content').forEach(div => { + div.style.display = 'none'; + }); + document.querySelectorAll('.tab-button').forEach(button => { + button.classList.remove('active'); + }); + + const roomDiv = document.getElementById(`room-${roomIdStr}`); + const tabButton = document.querySelector(`.tab-button[data-room-id="${roomIdStr}"]`); + + if (roomDiv && tabButton) { + roomDiv.style.display = 'block'; + tabButton.classList.add('active'); + } +} + async function request_rooms() { const apiUrl = '/chat/rooms'; const response = await fetch(apiUrl, { method: 'GET' }); diff --git a/src/public/style.css b/src/public/style.css index 3ba6ddf..44a048b 100644 --- a/src/public/style.css +++ b/src/public/style.css @@ -58,3 +58,37 @@ body { font-size: 12px; color: #ffffff; } + +/* Tabbed navigation */ +.tab-bar { + display: flex; + gap: 5px; + padding: 10px; + background-color: #f1f1f1; + border-bottom: 1px solid #ddd; +} + +.tab-button { + padding: 10px 20px; + background: none; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; + cursor: pointer; +} + +.tab-button.active { + background-color: #fff; + border-color: #ddd #ddd #fff; +} + +.room-content { + display: none; + padding: 20px; +} + +.room-content textarea { + width: 100%; + height: 60px; + margin-bottom: 10px; + resize: none; +}