aboutsummaryrefslogtreecommitdiffstats
path: root/src/app.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-03 21:20:46 -0700
committerAdam Soltys <[email protected]>2026-09-03 21:20:46 -0700
commit3b65462549269e3895345919b51164e017bcd13d (patch)
treecf81448d195c18f877f876ee7649983879082112 /src/app.js
parent5e960611887b4eae51caa1973e411a78caf3d92e (diff)
downloadcoinosv3-3b65462549269e3895345919b51164e017bcd13d.tar.gz
coinosv3-3b65462549269e3895345919b51164e017bcd13d.zip
The balance carousel stops stuttering during boot: the post-render alignment no longer reads layout (offsetLeft/scrollLeft) on every one of the many boot renders — an _alignedTo guard short-circuits before any layout touch once the card is in place, and the scroll's own settle marks itself aligned so it never re-aligns behind the user. The pass moved to rAF, and each slide gets layout containment so the history list building in below can't force it to reflow mid-scroll
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
Diffstat (limited to 'src/app.js')
-rw-r--r--src/app.js17
1 files changed, 13 insertions, 4 deletions
diff --git a/src/app.js b/src/app.js
index 5ff665b..2173b68 100644
--- a/src/app.js
+++ b/src/app.js
@@ -3384,16 +3384,22 @@ function balanceCard() {
// active one's edge and drags/snaps into place, BlueWallet-style.
const ORDER2 = ['spending', 'savings'];
// Align the carousel to the selected card after this render lands — but
- // never fight a finger or live momentum.
- setTimeout(() => {
+ // never fight a finger or live momentum, and NEVER touch layout when it's
+ // already where it belongs. Boot fires many renders (cache, ark connect,
+ // scan, nostr, balance ticks); reading offsetLeft/scrollLeft on each one
+ // forced a synchronous layout mid-scroll — the stutter. `_alignedTo`
+ // short-circuits before any layout read once the card is in place.
+ requestAnimationFrame(() => {
const el = document.querySelector('.bal-carousel');
- if (!el || Date.now() - (el._lastScroll || 0) < 350) return;
+ if (!el || el._alignedTo === sel) return;
+ if (Date.now() - (el._lastScroll || 0) < 350) return;
const k = el.children[ORDER2.indexOf(sel)];
if (!k) return;
const target = k.offsetLeft + k.offsetWidth / 2 - el.clientWidth / 2;
if (Math.abs(el.scrollLeft - target) > 6) el.scrollTo({ left: target, behavior: el._inited ? 'smooth' : 'auto' });
+ el._alignedTo = sel;
el._inited = true;
- }, 0);
+ });
_accDir = null; // the drag is the animation here
// The settled-card check, shared by the scroll debounce and drag release.
// While a finger or mouse button is still DOWN nothing switches — hovering
@@ -3408,6 +3414,9 @@ function balanceCard() {
});
const view = ORDER2[best];
if (view && view !== accountSel()) {
+ // the scroll already rests on this card — mark it aligned so the
+ // post-render pass skips its layout read instead of re-aligning
+ el._alignedTo = view;
ui.account = view;
try { localStorage.setItem(ACCOUNT_KEY, view); } catch {}
// selecting an account lands on its history (home), any open