diff options
| author | Adam Soltys <[email protected]> | 2026-09-28 22:05:29 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-28 22:05:29 -0700 |
| commit | d74b1ad667abea3b82bdb4bbddb9f1d0047903d4 (patch) | |
| tree | 5fdcb8001a19e57675863c1d6724e159ece1cbb6 /src/app.js | |
| parent | 613ab78f972277e963b7c7e49c3ffb1880bdd9d4 (diff) | |
| download | coinosv3-d74b1ad667abea3b82bdb4bbddb9f1d0047903d4.tar.gz coinosv3-d74b1ad667abea3b82bdb4bbddb9f1d0047903d4.zip | |
Send suggestions keep their rows across renders, so hovering one no longer flickers.
The panel was swapped for fresh nodes on every background render, which
dropped :hover each time. Now it's one node for the page's life and its
rows are rebuilt only when the results change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/app.js')
| -rw-r--r-- | src/app.js | 18 |
1 files changed, 13 insertions, 5 deletions
@@ -4832,7 +4832,7 @@ function destReady(a) { // Recipient search under the destination input: usernames and npubs resolve // to candidates with avatars; picking one runs the same path as pasting. -const sendSearch = { rows: null, sync: null }; +const sendSearch = { rows: null, sync: null, pick: null, el: null }; let sendRevealTimer = null; // With the phone keyboard up, the space under the recipient field is scarce — // park the field at the top of the view so the candidate list gets what's @@ -4882,12 +4882,19 @@ function recipientRow(s, r, i) { }; // The suggestions panel gets the same imperative treatment — see the // sendSearcher note: a render between key repeats kills backspace-hold. - const suggest = i === 0 ? h('div', { class: 'list send-suggest', style: 'display:none', 'data-fresh': '1' }) : null; + // One panel for the life of the page, rows rebuilt only when the results + // change: a background render must not swap the row under the pointer + // (a fresh node drops :hover, and the highlight blinked on every tick). + // data-fresh still installs this exact node wherever the morph lands it. + const suggest = i === 0 ? (sendSearch.el ||= h('div', { class: 'list send-suggest', style: 'display:none', 'data-fresh': '1' })) : null; const syncSuggest = () => { if (!suggest) return; - const show = sendSearch.rows && sendSearch.rows.length && searchable(r.address); - suggest.replaceChildren(...(show ? resultRows(h, sendSearch.rows, pickRecipient, (pk, node) => featureHook('wrapAvatar', pk, node)) : [])); - suggest.style.display = show ? '' : 'none'; + const show = !!(sendSearch.rows && sendSearch.rows.length && searchable(r.address)); + const rows = show ? sendSearch.rows : null; + if (suggest._rows === rows) return; + suggest._rows = rows; + suggest.replaceChildren(...(rows ? resultRows(h, rows, (cand) => sendSearch.pick(cand), (pk, node) => featureHook('wrapAvatar', pk, node)) : [])); + suggest.style.display = rows ? '' : 'none'; }; if (i === 0) sendSearch.sync = syncSuggest; @@ -4982,6 +4989,7 @@ function recipientRow(s, r, i) { ) : null ); syncCheck(); + if (i === 0) sendSearch.pick = pickRecipient; // the persistent rows call this render's syncSuggest(); return row; } |
