Join/leave sounds: debounce a flapping participant (do not break sounds) #145

Closed
opened 2026-09-17 16:51:58 -04:00 by jared · 1 comment
Owner

Verify first: a participant whose connection flaps (leave+join within seconds) currently plays the leave and join cues each time? If so: suppress a join cue for a user id that left < 60 s ago, and suppress a leave cue if the same user rejoins within ~5 s (delay the leave cue by that grace, cancel on rejoin). Applies only to the sound; membership UI stays live. Unit-test the debounce helper; keep the existing sound selection, volume and PTT interplay untouched.

Verify first: a participant whose connection flaps (leave+join within seconds) currently plays the leave and join cues each time? If so: suppress a join cue for a user id that left < 60 s ago, and suppress a leave cue if the same user rejoins within ~5 s (delay the leave cue by that grace, cancel on rejoin). Applies only to the *sound*; membership UI stays live. Unit-test the debounce helper; keep the existing sound selection, volume and PTT interplay untouched.
jared added this to the Features 2026-Q4 milestone 2026-09-17 16:51:58 -04:00
jared added the bugpriority: mediumarea: calls labels 2026-09-17 16:51:58 -04:00
jared self-assigned this 2026-09-17 16:51:58 -04:00
Author
Owner

Verified, then implemented on the local calls stack (two headless clients, OscillatorNode.start instrumented to classify the chimes).

Before: bob leaves and rejoins ~3 s later → alice hears leave, join every time (and join, leave, join for a join/leave/join flap).

Fix (4e455ae4, src/app/utils/callSoundDebounce.ts + useCallJoinLeaveSounds.ts), per user (not per device):

  • a leave cue waits 5 s; if the same user is back before it fires, the leave is cancelled and no join cue is played either;
  • a join cue is suppressed for a user who left < 60 s ago;
  • same-kind cues within 250 ms collapse, so a batch of leaves still sounds once;
  • a second device of someone already present is not a new arrival; a device switch is quiet.

Only the sound is debounced — membership UI unchanged; style/volume/PTT untouched (style is read at play time). Timers are injected: 6 unit tests with a manual clock.

Re-ran the scenario headless after the change:

bob joined                                  → [ 'join' ]
bob flapped (leave, rejoin ~3 s later)      → []            (was: leave, join)
bob left for good → after 7 s               → [ 'leave' ]   (5 s late, by design)
bob back within 60 s                        → []

Ships with the next lotus deploy.

**Verified, then implemented** on the local calls stack (two headless clients, `OscillatorNode.start` instrumented to classify the chimes). Before: bob leaves and rejoins ~3 s later → alice hears `leave`, `join` every time (and `join, leave, join` for a join/leave/join flap). Fix (`4e455ae4`, `src/app/utils/callSoundDebounce.ts` + `useCallJoinLeaveSounds.ts`), per **user** (not per device): - a leave cue waits **5 s**; if the same user is back before it fires, the leave is cancelled and no join cue is played either; - a join cue is suppressed for a user who left **< 60 s** ago; - same-kind cues within 250 ms collapse, so a batch of leaves still sounds once; - a second device of someone already present is not a new arrival; a device switch is quiet. Only the sound is debounced — membership UI unchanged; style/volume/PTT untouched (style is read at play time). Timers are injected: 6 unit tests with a manual clock. Re-ran the scenario headless after the change: ``` bob joined → [ 'join' ] bob flapped (leave, rejoin ~3 s later) → [] (was: leave, join) bob left for good → after 7 s → [ 'leave' ] (5 s late, by design) bob back within 60 s → [] ``` Ships with the next `lotus` deploy.
jared closed this issue 2026-09-19 00:36:10 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#145