diff options
| author | Adam Soltys <[email protected]> | 2026-08-27 23:11:01 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-27 23:11:01 -0700 |
| commit | 3a0f02b7624d72e73a4f92b635f5335ffd29f972 (patch) | |
| tree | 436fa37b5cee769507b703de2352c52c834472fe /src | |
| parent | ff9b87bb48130f638249412848c69b2d4a2a770a (diff) | |
| download | coinosv3-3a0f02b7624d72e73a4f92b635f5335ffd29f972.tar.gz coinosv3-3a0f02b7624d72e73a4f92b635f5335ffd29f972.zip | |
The face arrives with the key: sign-in warms the identity's profile and preloads the avatar bytes in parallel with the seed work, so the home screen's first paint already wears the picture instead of a blank circle
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
Diffstat (limited to 'src')
| -rw-r--r-- | src/features/messages.js | 11 | ||||
| -rw-r--r-- | src/features/nostrlogin.js | 3 |
2 files changed, 14 insertions, 0 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index c3ca466..3c03ce0 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -202,6 +202,11 @@ export function messagesFeature(ctx) { } wallet.saveFeatureState('profiles', s); } + // Pull the picture bytes into the HTTP cache the moment we learn the URL — + // an avatar div then paints instantly instead of holding its quiet circle + // while the image downloads. + const preloadPicture = (p) => { try { if (p && p.picture) new Image().src = p.picture; } catch {} }; + function profileOf(pk) { warmProfiles(); const cur = profiles.get(pk); @@ -211,6 +216,7 @@ export function messagesFeature(ctx) { const entry = { ...(p || {}), t: Date.now() }; profiles.set(pk, entry); persistProfile(pk, entry); + preloadPicture(entry); scheduleRepaint(); }).catch(() => profiles.set(pk, { t: Date.now() })); return cur || null; @@ -1207,6 +1213,7 @@ export function messagesFeature(ctx) { }; profiles.set(pk, entry); persistProfile(pk, entry); + preloadPicture(entry); if (ui.profilePk === pk) render(); else scheduleRepaint(); }).catch(() => { if (!fullProfiles.has(pk)) fullProfiles.set(pk, {}); }); @@ -2445,6 +2452,10 @@ export function messagesFeature(ctx) { // The light profile cache, read-only — lets the onboarding wizard skip // asks (like the avatar picker) that a loaded identity already answered. cachedProfile(pk) { return profileOf(pk); }, + // Start fetching a profile (and its picture bytes) NOW — the login flow + // calls this the moment it knows the identity, so the avatar is already + // in cache by the time the home screen first paints. + warmProfile(pk) { try { prefetchProfilePage(pk); profileOf(pk); } catch {} return true; }, // Publish (merge) kind-0 fields for the current identity — the onboarding // wizard sets name + picture through this. publishProfile(fields, opts = {}) { return publishProfileFields(fields, opts); }, diff --git a/src/features/nostrlogin.js b/src/features/nostrlogin.js index a084dd1..687a389 100644 --- a/src/features/nostrlogin.js +++ b/src/features/nostrlogin.js @@ -85,6 +85,9 @@ export function nostrLoginFeature(ctx) { let signer; try { signer = await makeSigner(); + // warm the identity's profile + avatar in parallel with the seed work, + // so the home screen's first paint already has the picture + ctx.hook('warmProfile', signer.pubkey); const res = await walletForSigner(signer); if (res.mode === 'new') { // No wallet on this identity yet — make one and walk straight in. |
