feat: voice channel user limit (P5-10) + call join/leave sounds (P5-16)
P5-10 Voice Channel User Limit:
- New StateEvent.LotusVoiceLimit (io.lotus.voice_limit) with { max_users }
- RoomVoiceLimit admin control in Room Settings > General > Voice
(power-level gated via permissions.stateEvent)
- CallPrescreen reads the limit reactively and disables Join with a
'Channel Full (N/N)' message at capacity; existing members can rejoin
P5-16 Custom Join/Leave Sound Effects:
- useCallJoinLeaveSounds hook wired into CallUtils; detects participant
join/leave via MatrixRTCSession membership changes (sender|deviceId),
filters out self, only fires while joined
- Sounds synthesized in-browser with Web Audio (callSounds.ts) - no
assets bundled; styles Off/Chime/Soft/Retro
- 'Join & Leave Sounds' selector in Settings > Calls (previews on change)
Docs: LOTUS_FEATURES.md, README.md, LOTUS_TODO.md (P5-10/P5-16 marked done)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -251,6 +251,39 @@ Automatically mutes the microphone after a configurable period of microphone-on
|
||||
|
||||
Hook: `src/app/hooks/useAfkAutoMute.ts`
|
||||
|
||||
### Voice Channel User Limit (P5-10)
|
||||
|
||||
Room admins can cap the number of participants allowed in a room's voice call.
|
||||
|
||||
**Implementation:**
|
||||
|
||||
- Limit is stored in the `io.lotus.voice_limit` room state event with content `{ max_users: N }` (0 / absent = no limit)
|
||||
- `RoomVoiceLimit` component in Room Settings → General → **Voice** lets admins set the cap with a number input. Editing is gated by `permissions.stateEvent(StateEvent.LotusVoiceLimit, …)`, so only users with `state_default` power (or above) can change it
|
||||
- `CallPrescreen` (`CallView.tsx`) reads the limit reactively via `useStateEvent` and compares it against the live `useCallMembers` count
|
||||
- When the call is at capacity, the **Join** button is disabled and a "Channel Full (N/N)" message is shown
|
||||
- A user who is already a member of the session (rejoining) is never blocked — only new joiners are gated
|
||||
- Enforcement is local to Lotus Chat clients (no server-side gatekeeping)
|
||||
|
||||
Files: `src/app/features/common-settings/general/RoomVoiceLimit.tsx`, `src/app/features/call/CallView.tsx`, `StateEvent.LotusVoiceLimit` in `src/types/matrix/room.ts`
|
||||
|
||||
### Custom Join / Leave Sound Effects (P5-16)
|
||||
|
||||
A local sound plays when another participant joins or leaves a call you're in.
|
||||
|
||||
**Implementation:**
|
||||
|
||||
- `useCallJoinLeaveSounds(embed)` hook (wired in `CallUtils` inside `CallEmbedProvider`) listens to `MatrixRTCSession` membership changes via `useCallMembersChange`
|
||||
- Membership identity is tracked by `sender|deviceId`; a snapshot is taken when the session (re)starts so participants already present never trigger a sound
|
||||
- Your own membership is filtered out (`mx.getSafeUserId()` prefix), and sounds fire only while you are actually joined (`useCallJoined`)
|
||||
- Sounds are synthesized in-browser with the Web Audio API (`OscillatorNode` + envelope) — no audio assets to bundle. Join uses a rising motif, leave a falling one
|
||||
- Three styles: **Chime** (sine), **Soft** (triangle), **Retro** (square arpeggio), plus **Off**
|
||||
|
||||
**Settings (Settings → Calls):**
|
||||
|
||||
- **Join & Leave Sounds** dropdown — Off / Chime / Soft / Retro (default: Chime). Selecting a style previews the join sound immediately
|
||||
|
||||
Files: `src/app/utils/callSounds.ts`, `src/app/hooks/useCallJoinLeaveSounds.ts`
|
||||
|
||||
### Noise Suppression Toggle
|
||||
|
||||
A `noiseSuppression` URL parameter is passed to the Element Call widget URL, allowing the noise suppression feature to be toggled from within Lotus settings.
|
||||
|
||||
Reference in New Issue
Block a user