perf(ui): cut composer per-keystroke costs (LC-229) #293
Loading…
Reference in a new issue
No description provided.
Delete branch "perf/lc-229-composer-keystroke-costs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes LC-229.
Three per-keystroke costs in
room/composer.htmlcompounded into laggy typing (staging report; siblings: LC-227 mention debounce #271, LC-228 NO_CONTENT #292).Changes
oninputdid write ->scrollHeightread -> write, forcing a synchronous reflow per keystroke (~0.3-1ms even when height unchanged). Now wrapped in a singlerequestAnimationFramewith cancel-and-reschedule, so rapid input collapses into one frame's resize. Teardown cancels a pending rAF so it cannot run against a detached textarea (same pattern as the LC-216/LC-227 timer cleanup).hx-on::after-requestcalledta.focus()unconditionally, including the LC-216 failure-debounced path; on mobile that snapped the keyboard back open 2s after submit. Focus now lives in theevent.detail.successfulbranch only. Rapid-fire send (success path) unchanged.document.getElementById('composer-send')every keystroke. Button captured once in the setup IIFE (mirrors the existingta/slot/bcastSlotcaptures); toggle moved to aninputlistener closing over it.Testing
just checkclean (clippy standalone + saas + desktop, fmt).just testandjust test-saaspass, 0 failures.🤖 Generated with Claude Code
Three per-keystroke costs in room/composer.html compounded into laggy typing on fast typists (staging report; sibling fixes LC-227 mention debounce, LC-228 NO_CONTENT response). - Auto-resize forced reflow: the inline oninput did write -> scrollHeight read -> write, forcing a synchronous layout pass per keystroke. Now batched into a single requestAnimationFrame with cancel-and-reschedule so rapid input collapses into one frame's resize. Pending rAF is cancelled in the IIFE teardown so it cannot run against a detached textarea. - Always-focus after send: hx-on::after-request called ta.focus() unconditionally, including the LC-216 failure-debounced path, which on mobile snapped the keyboard back open 2s after submit. Focus now fires only on the event.detail.successful branch (rapid-fire send case unchanged). - Per-keystroke DOM query: the send-disabled toggle did document.getElementById('composer-send') on every keystroke. The button is now captured once in the setup IIFE (alongside the existing ta/slot/bcastSlot captures) and the toggle moved to an input listener closing over it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>