feat(soundboard): shared room/space packs (like emoji/stickers), grid picker, management
Soundboard v2 — a near-parallel of the custom-emoji image-pack system for in-call audio clips. - Data model: 3-tier packs mirroring MSC2545 — room/space pack (state event io.lotus.soundboard, inherited by child rooms via parent-space aggregation), global refs (io.lotus.soundboard_rooms), and the personal pack (io.lotus.soundboard account data; the v1 flat-list content is migrated to the pack shape on read). New plugins/soundboard/ (readers, SoundboardPack, utils) + hooks/useSoundboardPacks (useRelevantSoundboardPacks = user U global U room, deduped). Unit-tested (migration + slug). - Management: reusable SoundboardPackEditor (name + emoji + per-clip volume + delete + upload + batched save), power-level-gated for room packs like emoji packs; a Soundboard page wired into Room + Space settings. - In-call: CallSoundboard rewritten as a Discord-style grid grouped by pack (emoji + name tiles), sourcing room+parent-space U personal clips; a Manage toggle embeds the editors; per-clip volume x master volume on playback. - Spam guard: host gates on a playing key (fork enforces one clip at a time). - Control bar: Mute-Screenshare moved next to the Screenshare button. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { SoundboardMeta } from './types';
|
||||
|
||||
/** Parallels custom-emoji/PackMetaReader (no usage tiers for soundboard). */
|
||||
export class SoundboardMetaReader {
|
||||
private readonly meta: SoundboardMeta;
|
||||
|
||||
constructor(meta: SoundboardMeta) {
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
get name(): string | undefined {
|
||||
const displayName = this.meta.display_name;
|
||||
return typeof displayName === 'string' ? displayName : undefined;
|
||||
}
|
||||
|
||||
get avatar(): string | undefined {
|
||||
const avatarURL = this.meta.avatar_url;
|
||||
return typeof avatarURL === 'string' ? avatarURL : undefined;
|
||||
}
|
||||
|
||||
get attribution(): string | undefined {
|
||||
const { attribution } = this.meta;
|
||||
return typeof attribution === 'string' ? attribution : undefined;
|
||||
}
|
||||
|
||||
get content(): SoundboardMeta {
|
||||
return this.meta;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user