aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-26 10:37:30 -0700
committerAdam Soltys <[email protected]>2026-08-26 10:37:30 -0700
commit7a108d1e1ae46bcbaded1d73fe22c551c40a2232 (patch)
treefcd394e9d4b290804023fafa5c168e03d3331ef6 /src/features
parent2af7811e243ec94d340869b2b420c382fe9350f8 (diff)
downloadcoinosv3-7a108d1e1ae46bcbaded1d73fe22c551c40a2232.tar.gz
coinosv3-7a108d1e1ae46bcbaded1d73fe22c551c40a2232.zip
The door opens on the right room: a profile link claims the very first paint — a shell with the asked-for name holds the frame while the registrar answers, the username seeds the avatar's fallback art so no npub prefix or empty circle shows, and an unknown name falls quietly through to the front door
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
Diffstat (limited to 'src/features')
-rw-r--r--src/features/messages.js27
1 files changed, 26 insertions, 1 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index ca55334..94e8909 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -626,6 +626,11 @@ export function messagesFeature(ctx) {
// the unlock screen (ui.pubProf gates that surface) — nostr profiles are
// public data, and Back lands on the app's own front door.
if (urlProfile) {
+ // Claim the first paint synchronously: these are set before the boot
+ // render, so the visitor sees a profile shell from the first frame —
+ // never a flash of the front door while the registrar lookup runs.
+ ui.pubProf = true;
+ ui.pubProfPending = urlProfile;
(async () => {
await new Promise((r) => setTimeout(r, 0)); // never render mid-boot
let pk = parseNostrPubkey(urlProfile);
@@ -638,10 +643,22 @@ export function messagesFeature(ctx) {
.then((r) => r.json());
pk = (j.names || {})[name] || null;
} catch {}
+ // The username is real display material: seed the light cache (stale,
+ // t:0, so the kind 0 still gets fetched) and the page paints the name
+ // and fallback avatar art immediately instead of an npub prefix and
+ // an empty circle while the relays answer.
+ if (pk && /^[0-9a-f]{64}$/.test(pk)) {
+ warmProfiles();
+ if (!profiles.has(pk)) profiles.set(pk, { name, t: 0 });
+ }
}
+ ui.pubProfPending = null;
if (pk && /^[0-9a-f]{64}$/.test(pk)) {
- if (ui.screen !== 'wallet') ui.pubProf = true;
+ if (ui.screen === 'wallet') ui.pubProf = null; // wallet chrome owns it
openProfile(pk);
+ } else {
+ ui.pubProf = null; // unknown name: fall through to the front door
+ render();
}
})();
}
@@ -2374,6 +2391,14 @@ export function messagesFeature(ctx) {
if (ui.pubProf) {
if (ui.noteThread) return threadScreen();
if (ui.profilePk) return profileScreen();
+ // resolution in flight: the shell holds the layout with the name
+ // straight off the URL — no spinner, the empty beat reads calmer
+ if (ui.pubProfPending) return h('div', { class: 'col', style: 'gap:16px' },
+ ctx.brandHeader(false),
+ h('div', { class: 'card col', style: 'gap:12px' },
+ h('div', { class: 'row gap6', style: 'align-items:center' },
+ h('div', { class: 'chat-avatar profile-avatar fallback loading' }),
+ h('div', { class: 'chat-title' }, ui.pubProfPending))));
}
return null;
}