perf(ui): debounce mention popover refresh 200ms (LC-227) #271

Merged
nrupard merged 1 commit from feat/lc-227-mention-popover-debounce into main 2026-05-29 21:34:32 +02:00
Owner

Summary

Pre-LC-227 composer.html's mention-popover refresh() fired htmx.ajax('GET', '/users/mentions?...') directly on every input event. Typing @alice stacked 6 in-flight requests on a 100ms-latency network; the popover flickered as each landed.

Wrap refresh() in a 200ms setTimeout + clearTimeout-on-each-keystroke pattern, mirroring the existing 300ms refreshBroadcastCount debounce one line away. Picked 200ms vs 300ms because the mention popover should feel close to keystroke-immediate; broadcast count is a count-only HUD where 300ms is invisible.

activeToken() + close() calls move inside the timer callback so the popover does not flicker-close-then-reopen on rapid typing through a token boundary.

Defensive clearTimeout added to the existing teardown() function so a swap-out during the debounce window cannot fire an htmx.ajax targeting a detached #lc-mention-popover slot.

Test plan

  • cargo check -p lets-chat-server clean.
  • Manual smoke: type @alice rapidly. DevTools Network panel shows ONE request to /users/mentions (not six).
  • Natural-pause smoke: type @a, pause 250ms — popover opens with a candidates.
  • Combobox semantics unchanged: arrow-key navigation, Enter-to-insert, Escape-to-close, blur-to-close, click-to-select all work.

LC-228 / LC-229 / LC-230 cover the rest of the typing/sending-feel-clunky analysis surfaced from the same staging report.

## Summary Pre-LC-227 `composer.html`'s mention-popover `refresh()` fired `htmx.ajax('GET', '/users/mentions?...')` directly on every input event. Typing `@alice` stacked 6 in-flight requests on a 100ms-latency network; the popover flickered as each landed. Wrap `refresh()` in a 200ms `setTimeout` + `clearTimeout`-on-each-keystroke pattern, mirroring the existing 300ms `refreshBroadcastCount` debounce one line away. Picked 200ms vs 300ms because the mention popover should feel close to keystroke-immediate; broadcast count is a count-only HUD where 300ms is invisible. `activeToken()` + `close()` calls move inside the timer callback so the popover does not flicker-close-then-reopen on rapid typing through a token boundary. Defensive `clearTimeout` added to the existing `teardown()` function so a swap-out during the debounce window cannot fire an htmx.ajax targeting a detached `#lc-mention-popover` slot. ## Test plan - [x] `cargo check -p lets-chat-server` clean. - [ ] Manual smoke: type `@alice` rapidly. DevTools Network panel shows ONE request to `/users/mentions` (not six). - [ ] Natural-pause smoke: type `@a`, pause 250ms — popover opens with `a` candidates. - [ ] Combobox semantics unchanged: arrow-key navigation, Enter-to-insert, Escape-to-close, blur-to-close, click-to-select all work. ## Related LC-228 / LC-229 / LC-230 cover the rest of the typing/sending-feel-clunky analysis surfaced from the same staging report.
perf(ui): debounce mention popover refresh 200ms (LC-227)
All checks were successful
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 6s
check-secrets / TruffleHog (pull_request) Successful in 5s
check-secrets / Nosey parker (pull_request) Successful in 6s
check-secrets / Kingfisher (pull_request) Successful in 6s
Check / clippy + fmt + tests (pull_request) Successful in 2m12s
Create release / Create release from merged PR (pull_request) Has been skipped
af46d8d80c
`composer.html`'s mention-popover `refresh()` fired `htmx.ajax('GET', '/users/mentions?...')` directly on every input event. Typing `@alice` stacked 6 in-flight requests on a 100ms-latency connection; each response triggered a fresh `htmx:afterSwap` cycle and the popover flickered as each landed. Perceived as typing-feels-laggy-when-typing-@.

Mirror the same `setTimeout` + `clearTimeout` shape `refreshBroadcastCount` already uses for the broadcast-count probe (300ms debounce, L188-207). Picked 200ms instead of 300ms: a mention popover should feel close to keystroke-immediate; broadcast count is a count-only HUD where 300ms is invisible. 200ms swallows the rapid-typist N-keystroke burst without delaying the natural-pause popover open.

Defensive cleanup added to the existing `teardown()` function so a swap-out during the debounce window cannot fire an htmx.ajax targeting a detached `#lc-mention-popover` slot. Mirrors LC-216 / LC-227's same shape for `__lcComposerErrTimer` / `bcastTimer`.

Verified: `cargo check -p lets-chat-server` clean. Combobox semantics unchanged: arrow-key navigation, Enter-to-insert, Escape-to-close, blur-to-close, click-to-select all still fire through the same paths.

#LC-227
nrupard deleted branch feat/lc-227-mention-popover-debounce 2026-05-29 21:34:32 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!271
No description provided.