From d95c3f48d1c5e20487dcf1bc9968e1695db05b85 Mon Sep 17 00:00:00 2001 From: KeelrLeek <156356974+KeelrLeek@users.noreply.github.com> Date: Sun, 13 Sep 2026 21:07:11 -0500 Subject: [PATCH] android: the room list filtered by name, the rest on demand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Soulseek lists hundreds of rooms; the phone showed the first 80 and no way to the rest. Community → Rooms now has a filter by name and extends the list 200 at a time. --- ANDROID.md | 3 +++ src/lib/mockLibrary.js | 2 +- src/mobile/screens/Community.svelte | 22 +++++++++++++++++++++- src/mobile/shell.css | 3 +++ tests/mobile/smoke.mjs | 7 +++++++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/ANDROID.md b/ANDROID.md index 1eea913..e43f747 100644 --- a/ANDROID.md +++ b/ANDROID.md @@ -172,6 +172,9 @@ namesake), the catalog's released records minus the shelf's by loose title, dimmed cards that open the catalog record page, the totals remembered in `library.gaps.v1` so the line says its number before the lookup. +The server's room list on Community is filtered by name and shows 80 at a +time with a way to the rest (Soulseek lists hundreds). + ## A peer, and their shares A raw result's ⋯ (or a long press on its head) is the peer's sheet: play diff --git a/src/lib/mockLibrary.js b/src/lib/mockLibrary.js index 854ff80..b832d82 100644 --- a/src/lib/mockLibrary.js +++ b/src/lib/mockLibrary.js @@ -376,7 +376,7 @@ const later = (ms, fn) => setTimeout(fn, ms); if (enabled && typeof window !== "undefined") window.__ssMock = { emit: mockEmit }; const MOCK_USER = "mockuser"; -const ROOMS = [["Lounge", 412], ["Electronic", 98], ["Vinyl Rips", 37], ["Jazz", 61], ["Lossless Only", 23]]; +const ROOMS = [["Lounge", 412], ["Electronic", 98], ["Vinyl Rips", 37], ["Jazz", 61], ["Lossless Only", 23], ...Array.from({ length: 90 }, (_, i) => ["Room " + (i + 1), 90 - i])]; const PEOPLE = ["ada", "bo", "cy", "dee"]; const LINES = ["anyone got the 2024 remaster?", "the vinyl rip is warmer imo", "that folder is complete btw", "brb"]; const PEERS = [ diff --git a/src/mobile/screens/Community.svelte b/src/mobile/screens/Community.svelte index d5a88b3..19c1ee1 100644 --- a/src/mobile/screens/Community.svelte +++ b/src/mobile/screens/Community.svelte @@ -20,7 +20,17 @@ const online = $derived(slsk.connection === "online"); const joinedNames = $derived(Object.keys(slsk.joined)); - const otherRooms = $derived(slsk.rooms.filter((r) => !slsk.joined[r.name]).slice(0, 80)); + /* the server's rooms: filtered by name, the biggest first, 80 at a + time with a way to the rest */ + let roomQ = $state(""); + let roomCap = $state(80); + const roomsMatching = $derived.by(() => { + const k = roomQ.trim().toLowerCase(); + const list = slsk.rooms.filter((r) => !slsk.joined[r.name]); + return k ? list.filter((r) => r.name.toLowerCase().includes(k)) : list; + }); + const otherRooms = $derived(roomsMatching.slice(0, roomCap)); + $effect(() => { void roomQ; roomCap = 80; }); const threads = $derived( Object.entries(slsk.chats) .map(([u, c]) => ({ u, c, last: c.messages[c.messages.length - 1] })) @@ -121,6 +131,13 @@

Rooms · {slsk.rooms.length} on the server

{#if !slsk.rooms.length}
Asking the server for its rooms…
+ {:else if slsk.rooms.length > 8} +
+ + (roomQ = e.currentTarget.value)} type="search" placeholder="Find a room" autocomplete="off" autocapitalize="off" spellcheck="false" aria-label="Find a room" /> + {#if roomQ}{/if} +
+ {#if roomQ}
{roomsMatching.length} of {slsk.rooms.length} rooms
{/if} {/if} {#each otherRooms as r (r.name)} {/each} + {#if roomsMatching.length > roomCap} +
+ {/if} {:else if tab === "chat"} {#if !threads.length}
No conversations yet.A name in a room, or a buddy, opens one.
diff --git a/src/mobile/shell.css b/src/mobile/shell.css index cf2db57..0eb6442 100644 --- a/src/mobile/shell.css +++ b/src/mobile/shell.css @@ -1365,3 +1365,6 @@ html[data-motion="off"] *, html[data-motion="off"] *::before, html[data-motion=" /* the lyrics face's way to its tools */ .lyr-tools { display: block; margin: 18px auto 8px; padding: 7px 14px; border-radius: 999px; background: rgba(255, 255, 255, 0.08); color: var(--text-secondary); font-size: 12.5px; font-weight: 700; } .lyr-tools:active { background: rgba(255, 255, 255, 0.14); } + +/* Community: the room filter sits with the section, not the page's own field */ +.sfield.roomfilter { margin-top: 2px; } diff --git a/tests/mobile/smoke.mjs b/tests/mobile/smoke.mjs index d2ee3f3..bfba972 100644 --- a/tests/mobile/smoke.mjs +++ b/tests/mobile/smoke.mjs @@ -112,6 +112,7 @@ const PROBE = `(function () { plfilter: !!document.querySelector('.plfilter input'), plfirst: (document.querySelector('.pl-rows .trk .t') || {}).textContent || '', qfirst: (document.querySelector('.q-face .row .t') || {}).textContent || '', + rooms: document.querySelectorAll('.screen button.row .art.hash').length, plthumbs: document.querySelectorAll('.pl-rows .thumb img').length, imp: document.querySelectorAll('.imp-rows .trk').length, impTags: [].map.call(document.querySelectorAll('.imp-rows .tag'), function (t) { return t.textContent.trim(); }).join('|'), @@ -202,6 +203,10 @@ const MOCK_STEPS = [ { do: `__click('.halfsheet .prompt-acts .btn-fill', 'Open')`, name: "user-lookup", wait: 700 }, { do: `document.querySelector('.scrim').click()`, wait: 500 }, { do: `__click('.segtabs button', 'Rooms')`, wait: 500 }, + /* the room list: filtered by name, the rest on demand */ + { do: `(function () { var i = document.querySelector('.roomfilter input'); i.value = 'vin'; i.dispatchEvent(new Event('input', { bubbles: true })); })()`, name: "rooms-filtered", wait: 500 }, + { do: `(function () { var i = document.querySelector('.roomfilter input'); i.value = ''; i.dispatchEvent(new Event('input', { bubbles: true })); })()`, wait: 400 }, + { do: `__click('.screen .btn', 'more rooms')`, name: "rooms-more", wait: 500 }, /* the fake network: a room with a few lines in it */ { do: `__click('.screen button.row', 'Lounge')`, name: "room", wait: 2400 }, { do: `history.back()`, wait: 700 }, @@ -422,6 +427,8 @@ const MOCK_EXPECT = { complete the set, following — the desktop's page */ "home-again": (i) => /^(Good |Still)/.test(i.title) && /^Coming/.test(i.feat) && i.news >= 1 && /New from your artists/.test(i.secs) && /From the back catalogue/.test(i.secs) && /Recommended for you/.test(i.secs) && /Following/.test(i.secs), room: (i) => i.screen.includes("tr-push") && i.msgs >= 2, + "rooms-filtered": (i) => i.rooms === 1, + "rooms-more": (i) => i.rooms >= 95, /* the artist with a picture shows it on the hero and its card; the namesake under Deezer's empty-hash placeholder shows the app's own */ "cat-results": (i) => i.songs >= 4 && i.top.startsWith("Daft Punk") && i.heroImg && i.cardImgs === 1 && i.cardPhs === 1,