From f8efbfe38b1bc26d5fb74df8c42992e92a445275 Mon Sep 17 00:00:00 2001 From: Lotus CI Date: Sun, 18 Oct 2026 01:22:50 -0400 Subject: [PATCH] fix(calls): explain when the soundboard is not allowed in a voice channel (EC #47) The fork now refuses a clip it cannot publish (audio-only rooms grant only the microphone source) with reason "not_permitted". Say "The soundboard isn't available in this voice channel" instead of the generic error. Older forks are unaffected. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 --- src/app/features/call/CallSoundboard.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/app/features/call/CallSoundboard.tsx b/src/app/features/call/CallSoundboard.tsx index beadcc115..7c30203e0 100644 --- a/src/app/features/call/CallSoundboard.tsx +++ b/src/app/features/call/CallSoundboard.tsx @@ -50,6 +50,14 @@ type FlatClip = { * A management toggle reveals the pack editors (personal + this room, if * permitted). Space-wide packs are managed from Space settings. */ +/** [EC#13, EC#47] Why the fork refused to play a clip, for the user. */ +export const soundboardRefusalText = (reason: string | undefined): string => { + if (reason === 'muted') return 'Unmute your microphone to play a soundboard clip.'; + if (reason === 'not_permitted') + return "The soundboard isn't available in this voice channel (only microphone audio is allowed here)."; + return 'Could not play that clip.'; +}; + export function CallSoundboard({ callEmbed }: CallSoundboardProps) { const mx = useMatrixClient(); const { room } = callEmbed; @@ -122,13 +130,10 @@ export function CallSoundboard({ callEmbed }: CallSoundboardProps) { .catch(() => undefined); const result = await callEmbed.control.injectAudio(url, vol, clipBytes); if (!result.played) { - // [EC#13] Refused fork-side (only reason today: local mic muted) — + // [EC#13, EC#47] Refused fork-side (mic muted, or the room's token + // only allows the microphone source, as in audio-only rooms) — // don't play it locally either, or the user would think it went out. - setError( - result.reason === 'muted' - ? 'Unmute your microphone to play a soundboard clip.' - : 'Could not play that clip.', - ); + setError(soundboardRefusalText(result.reason)); done(); return; }