feat(call): in-call soundboard, quality controls, room call-permissions
Element Call is now consumed as our self-built fork (@lotusguild/element-call-embedded); wire up its previously-dormant capabilities and document the fork as live. Soundboard (P5-15): a call-bar button plays user-uploaded audio clips into the call as a real published track (io.lotus.inject_audio) plus local playback. Clips are uploadable like emoji/sticker packs, stored in io.lotus.soundboard account data (synced across devices). Gated by a Settings toggle + volume. Quality controls (P5-31): per-user mic/screenshare bitrate + screenshare framerate (Settings -> Calls), applied via io.lotus.set_quality clamped to any room cap. Room admins set caps and hard call-permissions (allow_screenshare / allow_camera) in Room Settings -> Voice; the call bar hides blocked buttons. - New: CallSoundboard, useSoundboard, soundboardClips; RoomQuality, useCallQuality, callQuality (+ unit tests). - Optimistic-write RoomQuality admin UI (no stale-state clobber). - Docs: mark EC fork live across README/FEATURES/TODO/BUGS/TESTING; add D2 manual-test steps. Numeric quality caps are client-cooperative; screenshare/camera permissions are hard-enforced server-side (see LotusGuild/matrix voice-limit-guard). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,13 @@ export type DenoiseModelId = 'rnnoise' | 'speex' | 'dtln' | 'deepfilternet';
|
||||
// 'soft' / 'retro' are synthesized in-browser (see utils/ringtones.ts);
|
||||
// 'none' is silent (visual-only incoming-call UI).
|
||||
export type RingtoneId = 'classic' | 'chime' | 'soft' | 'retro' | 'none';
|
||||
// [P5-31] Granular call quality caps. 'auto' = don't cap (the EC fork keeps its
|
||||
// default encoding). Numbers are kbps (audio/screenshare bitrate) or fps
|
||||
// (screenshare framerate); converted to the fork's bits/sec + fps payload in
|
||||
// utils/callQuality.ts and applied via the io.lotus.set_quality widget action.
|
||||
export type CallAudioBitrate = 'auto' | '32' | '64' | '96' | '128' | '256';
|
||||
export type ScreenshareBitrate = 'auto' | '500' | '1500' | '3000' | '8000';
|
||||
export type ScreenshareFramerate = 'auto' | '15' | '30' | '60';
|
||||
export type ChatBackground =
|
||||
| 'none'
|
||||
| 'blueprint'
|
||||
@@ -156,6 +163,14 @@ export interface Settings {
|
||||
ringtoneId: RingtoneId;
|
||||
ringtoneVolume: number; // 0–100
|
||||
|
||||
// [P5-31] Call quality controls
|
||||
callAudioBitrate: CallAudioBitrate;
|
||||
screenshareBitrate: ScreenshareBitrate;
|
||||
screenshareFramerate: ScreenshareFramerate;
|
||||
// [P5-15] In-call soundboard
|
||||
soundboardEnabled: boolean;
|
||||
soundboardVolume: number; // 0–100
|
||||
|
||||
seasonalThemeOverride:
|
||||
| 'auto'
|
||||
| 'off'
|
||||
@@ -253,6 +268,12 @@ const defaultSettings: Settings = {
|
||||
ringtoneId: 'classic',
|
||||
ringtoneVolume: 70,
|
||||
|
||||
callAudioBitrate: 'auto',
|
||||
screenshareBitrate: 'auto',
|
||||
screenshareFramerate: 'auto',
|
||||
soundboardEnabled: true,
|
||||
soundboardVolume: 80,
|
||||
|
||||
seasonalThemeOverride: 'auto',
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user