aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-26 11:13:03 -0700
committerAdam Soltys <[email protected]>2026-08-26 11:13:03 -0700
commit6be9a45c4d085988c8bfaf210df762dbc83c8ab1 (patch)
tree6d3a48e3b69b0851d127b1ad10ade3d31969c9fe /src
parent7a108d1e1ae46bcbaded1d73fe22c551c40a2232 (diff)
downloadcoinosv3-6be9a45c4d085988c8bfaf210df762dbc83c8ab1.tar.gz
coinosv3-6be9a45c4d085988c8bfaf210df762dbc83c8ab1.zip
The landing settles as one motion: the resolving shell now holds the frame over every screen — an auto-restored wallet no longer flashes its home page — and the animation clock stands still until the profile has replaced the shell in place, so nothing slides twice
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
Diffstat (limited to 'src')
-rw-r--r--src/app.js6
-rw-r--r--src/features/messages.js25
2 files changed, 21 insertions, 10 deletions
diff --git a/src/app.js b/src/app.js
index 6ad7dcc..237808e 100644
--- a/src/app.js
+++ b/src/app.js
@@ -474,7 +474,11 @@ function renderInner() {
const navKey = [ui.screen, ui.tab === 'settings', ui.chatOpen, ui.msgView, ui.msgPeer, ui.msgCommunity,
ui.profilePk, ui.settingsPage, ui.addrScan, ui.arkExitPage, ui.txDetail, ui.giftMode, ui.claimStep, ui.nameEditOpen,
ui.noteThread && ui.noteThread.focusId, !!ui.userSearch, !!ui.zapSetup, !!ui.hatShop].join('|');
- if (uiChanged('nav', navKey)) _navAt = performance.now();
+ // A deep-linked profile landing is ONE page settling, not a chain of
+ // navigations: boot screens shuffle beneath the shell (unlock → restored
+ // wallet), then the resolved profile replaces the shell in place. The key
+ // still updates, but nothing slides or re-animates until the landing ends.
+ if (uiChanged('nav', navKey) && !(ui.pubProfPending || ui.pubProfHold)) _navAt = performance.now();
applyAnim(screen, 'anim-page', (performance.now() - _navAt) < 340 ? performance.now() - _navAt : -1);
morphChildren(root, [screen, footer()]);
if (fpath) {
diff --git a/src/features/messages.js b/src/features/messages.js
index 94e8909..c4ed990 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -652,11 +652,16 @@ export function messagesFeature(ctx) {
if (!profiles.has(pk)) profiles.set(pk, { name, t: 0 });
}
}
- ui.pubProfPending = null;
if (pk && /^[0-9a-f]{64}$/.test(pk)) {
+ // hold the pinned nav key across this render: the profile replaces
+ // the shell in place, with no page-slide re-animation
+ ui.pubProfHold = true;
+ ui.pubProfPending = null;
if (ui.screen === 'wallet') ui.pubProf = null; // wallet chrome owns it
openProfile(pk);
+ ui.pubProfHold = null;
} else {
+ ui.pubProfPending = null;
ui.pubProf = null; // unknown name: fall through to the front door
render();
}
@@ -2384,6 +2389,16 @@ export function messagesFeature(ctx) {
unreadMessages() { return unreadCount(); },
notifySettingsCards() { return [notifyCard()]; },
screenView() {
+ // A profile deep link mid-resolution holds the frame over EVERY screen
+ // — an auto-restored wallet would otherwise flash its home page for the
+ // beat the registrar lookup takes. The shell shows 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))));
if (ui.screen !== 'wallet') {
// The public (no-wallet) surface: a deep-linked profile, and the
// threads reachable from it, are public nostr content — shown
@@ -2391,14 +2406,6 @@ 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;
}