android: the room list filtered by name, the rest on demand
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.
This commit is contained in:
1 parent
60303c8a95
commit
d95c3f48d1
5 files changed
+35
-2
No files matched your search
@@ -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
|
dimmed cards that open the catalog record page, the totals remembered in
|
||||||
`library.gaps.v1` so the line says its number before the lookup.
|
`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 peer, and their shares
|
||||||
|
|
||||||
A raw result's ⋯ (or a long press on its head) is the peer's sheet: play
|
A raw result's ⋯ (or a long press on its head) is the peer's sheet: play
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ const later = (ms, fn) => setTimeout(fn, ms);
|
|||||||
if (enabled && typeof window !== "undefined") window.__ssMock = { emit: mockEmit };
|
if (enabled && typeof window !== "undefined") window.__ssMock = { emit: mockEmit };
|
||||||
|
|
||||||
const MOCK_USER = "mockuser";
|
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 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 LINES = ["anyone got the 2024 remaster?", "the vinyl rip is warmer imo", "that folder is complete btw", "brb"];
|
||||||
const PEERS = [
|
const PEERS = [
|
||||||
|
|||||||
@@ -20,7 +20,17 @@
|
|||||||
|
|
||||||
const online = $derived(slsk.connection === "online");
|
const online = $derived(slsk.connection === "online");
|
||||||
const joinedNames = $derived(Object.keys(slsk.joined));
|
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(
|
const threads = $derived(
|
||||||
Object.entries(slsk.chats)
|
Object.entries(slsk.chats)
|
||||||
.map(([u, c]) => ({ u, c, last: c.messages[c.messages.length - 1] }))
|
.map(([u, c]) => ({ u, c, last: c.messages[c.messages.length - 1] }))
|
||||||
@@ -121,6 +131,13 @@
|
|||||||
<div class="sec" style="padding-top:{joinedNames.length ? 18 : 8}px"><h2>Rooms <em>· {slsk.rooms.length} on the server</em></h2></div>
|
<div class="sec" style="padding-top:{joinedNames.length ? 18 : 8}px"><h2>Rooms <em>· {slsk.rooms.length} on the server</em></h2></div>
|
||||||
{#if !slsk.rooms.length}
|
{#if !slsk.rooms.length}
|
||||||
<div class="sec-note">Asking the server for its rooms…</div>
|
<div class="sec-note">Asking the server for its rooms…</div>
|
||||||
|
{:else if slsk.rooms.length > 8}
|
||||||
|
<div class="sfield roomfilter">
|
||||||
|
<Icon name="search" size={18} />
|
||||||
|
<input value={roomQ} oninput={(e) => (roomQ = e.currentTarget.value)} type="search" placeholder="Find a room" autocomplete="off" autocapitalize="off" spellcheck="false" aria-label="Find a room" />
|
||||||
|
{#if roomQ}<button class="iconbtn sm" onclick={() => (roomQ = "")} aria-label="Clear"><Icon name="x" size={18} /></button>{/if}
|
||||||
|
</div>
|
||||||
|
{#if roomQ}<div class="sec-note">{roomsMatching.length} of {slsk.rooms.length} rooms</div>{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#each otherRooms as r (r.name)}
|
{#each otherRooms as r (r.name)}
|
||||||
<button class="row" onclick={() => open(r.name)}>
|
<button class="row" onclick={() => open(r.name)}>
|
||||||
@@ -129,6 +146,9 @@
|
|||||||
<span class="r"><Icon name="plus" size={18} /></span>
|
<span class="r"><Icon name="plus" size={18} /></span>
|
||||||
</button>
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
|
{#if roomsMatching.length > roomCap}
|
||||||
|
<div style="padding: 4px var(--pad) 8px"><button class="btn btn-ghost wide" onclick={() => (roomCap += 200)}>+ {roomsMatching.length - roomCap} more rooms</button></div>
|
||||||
|
{/if}
|
||||||
{:else if tab === "chat"}
|
{:else if tab === "chat"}
|
||||||
{#if !threads.length}
|
{#if !threads.length}
|
||||||
<div class="stub"><b>No conversations yet.</b>A name in a room, or a buddy, opens one.</div>
|
<div class="stub"><b>No conversations yet.</b>A name in a room, or a buddy, opens one.</div>
|
||||||
|
|||||||
@@ -1365,3 +1365,6 @@ html[data-motion="off"] *, html[data-motion="off"] *::before, html[data-motion="
|
|||||||
/* the lyrics face's way to its tools */
|
/* 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 { 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); }
|
.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; }
|
||||||
@@ -112,6 +112,7 @@ const PROBE = `(function () {
|
|||||||
plfilter: !!document.querySelector('.plfilter input'),
|
plfilter: !!document.querySelector('.plfilter input'),
|
||||||
plfirst: (document.querySelector('.pl-rows .trk .t') || {}).textContent || '',
|
plfirst: (document.querySelector('.pl-rows .trk .t') || {}).textContent || '',
|
||||||
qfirst: (document.querySelector('.q-face .row .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,
|
plthumbs: document.querySelectorAll('.pl-rows .thumb img').length,
|
||||||
imp: document.querySelectorAll('.imp-rows .trk').length,
|
imp: document.querySelectorAll('.imp-rows .trk').length,
|
||||||
impTags: [].map.call(document.querySelectorAll('.imp-rows .tag'), function (t) { return t.textContent.trim(); }).join('|'),
|
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: `__click('.halfsheet .prompt-acts .btn-fill', 'Open')`, name: "user-lookup", wait: 700 },
|
||||||
{ do: `document.querySelector('.scrim').click()`, wait: 500 },
|
{ do: `document.querySelector('.scrim').click()`, wait: 500 },
|
||||||
{ do: `__click('.segtabs button', 'Rooms')`, 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 */
|
/* the fake network: a room with a few lines in it */
|
||||||
{ do: `__click('.screen button.row', 'Lounge')`, name: "room", wait: 2400 },
|
{ do: `__click('.screen button.row', 'Lounge')`, name: "room", wait: 2400 },
|
||||||
{ do: `history.back()`, wait: 700 },
|
{ do: `history.back()`, wait: 700 },
|
||||||
@@ -422,6 +427,8 @@ const MOCK_EXPECT = {
|
|||||||
complete the set, following — the desktop's page */
|
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),
|
"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,
|
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
|
/* 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 */
|
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,
|
"cat-results": (i) => i.songs >= 4 && i.top.startsWith("Daft Punk") && i.heroImg && i.cardImgs === 1 && i.cardPhs === 1,
|
||||||
|
|||||||
Reference in new issue
Block a user