From 48e8e588f1a3dee26a2497d1a1757f2f294413a3 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 10 Sep 2026 23:00:21 -0700 Subject: A face we've never seen is drawn from the pubkey, not left blank. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The avatar delay left on the messages page wasn't the image at all. A person with no cached profile got an empty circle until a relay answered — and the one that stayed blank longest (npub1k6f89cg, in the live cache) is never cached at all: persistProfile deliberately refuses to write a row with no name and no picture, so every boot re-asked the relays and every boot sat blank for seconds. When it finally arrived it was a punk, which is why it looked like slow art rather than a slow lookup. The punk is derived from the pubkey alone, so it can be drawn in the first frame. It's already the right answer for everyone with no picture, and for a coinos user who kept the default it IS their published picture — same formula, same file. A real photo replaces it when it lands. A name lookup in flight still gets the quiet circle: a picture is expected there, and punk art must not flash in front of it. Also: the punk rewrite now recognises the bare relative path a few older profiles carry, not just the absolute URL. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx --- tools/avatar-thumb-test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tools') diff --git a/tools/avatar-thumb-test.js b/tools/avatar-thumb-test.js index 50ceadc..73277bc 100644 --- a/tools/avatar-thumb-test.js +++ b/tools/avatar-thumb-test.js @@ -139,6 +139,19 @@ try { return i ? i.getAttribute('src') : ''; }); check('the default face is the small punk', /^punks-sm\//.test(punkSrc), punkSrc); + + // And someone we have never cached at all — the case that used to sit as a + // blank circle until a relay answered — is drawn from their pubkey alone. + await page.evaluate(() => { + for (const k of Object.keys(localStorage).filter((x) => /^btc-wallet-cache:[0-9a-f]+:profiles$/.test(x))) localStorage.removeItem(k); + }); + await page.reload({ waitUntil: 'domcontentloaded' }); + await waitText('receive', 20000); + const strangerSrc = await page.evaluate(() => { + const i = document.querySelector('.header-avatar img.punk') || document.querySelector('img.punk'); + return i ? i.getAttribute('src') : ''; + }); + check('an uncached face is drawn straight away, not left blank', /^punks-sm\//.test(strangerSrc), strangerSrc || 'blank circle'); } finally { await browser.close(); server.stop(true); } console.log(ok ? '\n✅ faces come back instantly' : '\n❌ failed'); process.exit(ok ? 0 : 1); -- cgit v1.2.3