diff options
| author | Adam Soltys <[email protected]> | 2026-10-02 07:48:32 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-02 07:48:32 -0700 |
| commit | 686e2d391d3a963535d5deec7043999b9b92b19b (patch) | |
| tree | f44167f4affaf38e63ed1bd637c7509f74a72679 /src/recipient-search.js | |
| parent | 53160e57a1bf65812ddade7e4e71d0c3a75e812c (diff) | |
| download | coinosv3-686e2d391d3a963535d5deec7043999b9b92b19b.tar.gz coinosv3-686e2d391d3a963535d5deec7043999b9b92b19b.zip | |
Profiles show Following and Followers, each a list you can open
Under the bio: "116 Following · 572 Followers". Tapping either opens the
people below it (50 at a time); tapping a person opens their profile.
Follows are the person's kind 3, now read from Primal's cache alongside
the relays (a list kept only on their outbox relays used to read as
nobody). Followers, which no relay counts, come from Primal: the count
from user_profile, the list from user_followers, a first screenful fast
and the rest after, without reordering what is on screen. Every event
taken from Primal is signature-checked in the verify worker first, and
the profiles among them fill names and faces the relays lacked.
Also translates the post-zap "no address" message.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dmcrt9KyNDKVWFKnb8BREo
Diffstat (limited to 'src/recipient-search.js')
| -rw-r--r-- | src/recipient-search.js | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/src/recipient-search.js b/src/recipient-search.js index b0a0edc..fdeaeaf 100644 --- a/src/recipient-search.js +++ b/src/recipient-search.js @@ -51,21 +51,25 @@ const MAX_RESULTS = 8; // to cost more than the query itself. Idle for a minute, it closes itself. let pws = null, pwsN = 0, pwsIdle = null; const pwsSubs = new Map(); // sub id -> { rows, finish } -function primalSearch(q, limit = MAX_RESULTS) { +// Any of Primal's cache calls over the shared socket; resolves with every +// event it answered (its own stats kinds included) at EOSE or the timeout. +export function primalCache(cmd, args, timeoutMs = 3500) { return new Promise((resolve) => { const sid = 'rs' + ++pwsN; const rows = []; const finish = () => { clearTimeout(to); pwsSubs.delete(sid); resolve(rows); }; - const to = setTimeout(finish, 3500); + const to = setTimeout(finish, timeoutMs); pwsSubs.set(sid, { rows, finish }); clearTimeout(pwsIdle); pwsIdle = setTimeout(() => { try { pws?.close(); } catch {} pws = null; }, 60_000); - const send = () => { try { pws.send(JSON.stringify(['REQ', sid, { cache: ['user_search', { query: q, limit }] }])); } catch { finish(); } }; + const send = () => { try { pws.send(JSON.stringify(['REQ', sid, { cache: [cmd, args] }])); } catch { finish(); } }; if (pws && pws.readyState === 1) return send(); if (!ensurePws()) return finish(); pws.addEventListener('open', send, { once: true }); }); } +const primalSearch = (q, limit = MAX_RESULTS) => + primalCache('user_search', { query: q, limit }).then((evs) => evs.filter((e) => e.kind === 0)); function ensurePws() { if (pws && pws.readyState <= 1) return true; @@ -75,7 +79,7 @@ function ensurePws() { const m = JSON.parse(ev.data); const sub = pwsSubs.get(m[1]); if (!sub) return; - if (m[0] === 'EVENT' && m[2] && m[2].kind === 0) sub.rows.push(m[2]); + if (m[0] === 'EVENT' && m[2]) sub.rows.push(m[2]); if (m[0] === 'EOSE') sub.finish(); } catch {} }; |
