feat(calls): debounce join/leave cues for a flapping participant (#145)

Verified first on the local calls stack: a participant who left and rejoined
~3 s later played "leave" then "join" every time. Cues now go through
createCallSoundDebouncer (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, and a
  device switch is quiet.

Only the sound is debounced; membership UI is unchanged. Sound style, volume
and PTT interplay untouched (the style is read at play time). Timers are
injected — unit-tested with a manual clock. Re-ran the flap scenario headless:
join → flap → (silence) → real leave → one "leave" 5 s later → rejoin within
60 s → silence.

Also enables msc4133 (custom profile fields → in-call avatar decorations) on
the dev Synapse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
2026-09-19 00:15:34 -04:00
co-authored by Claude Opus 5
parent 30fd22a5c5
commit 4e455ae42e
4 changed files with 273 additions and 8 deletions
+1
View File
@@ -62,6 +62,7 @@ experimental_features:
msc4140_enabled: true
msc4143_enabled: true
msc3266_enabled: true
msc4133_enabled: true
matrix_rtc:
transports:
- type: livekit