fix(soundboard): read MANAGE_SPACE from the space bitfield
OpenSSF Scorecard / Scorecard analysis (push) Waiting to run
CI / Build & test (Node 20) (push) Canceled after 0s
CI / Build & test (Node 24) (push) Canceled after 0s
CI / Build & test (push) Canceled after 0s
CodeQL / Analyze (javascript-typescript) (push) Canceled after 0s
Security / Secret scan (gitleaks) (push) Canceled after 0s
Security / Dependency scan (OSV-Scanner) (push) Canceled after 0s
Security / IaC/config scan (Trivy) (push) Canceled after 0s
Security / License compliance scan (Trivy) (push) Canceled after 0s
OpenSSF Scorecard / Scorecard analysis (push) Waiting to run
CI / Build & test (Node 20) (push) Canceled after 0s
CI / Build & test (Node 24) (push) Canceled after 0s
CI / Build & test (push) Canceled after 0s
CodeQL / Analyze (javascript-typescript) (push) Canceled after 0s
Security / Secret scan (gitleaks) (push) Canceled after 0s
Security / Dependency scan (OSV-Scanner) (push) Canceled after 0s
Security / IaC/config scan (Trivy) (push) Canceled after 0s
Security / License compliance scan (Trivy) (push) Canceled after 0s
The add-sound control was gated on channelPermissions, which carries the per-channel bitfield; MANAGE_SPACE lives in the space-level one. The check silently evaluated false for everybody, including owners, so the button never rendered and there was no way to add a sound at all. Also raise the clip cap to 2 MB — a 30-second clip at a high bitrate cleared 1 MB — and stop reporting every upload failure as 'too large', which sent people to shrink a file that was not the problem.
This commit is contained in:
@@ -12,7 +12,7 @@ interface SoundboardPopoverProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Clips are short gags; anything larger is a music file in disguise. */
|
/** Clips are short gags; anything larger is a music file in disguise. */
|
||||||
const MAX_SOUND_BYTES = 1024 * 1024;
|
const MAX_SOUND_BYTES = 2 * 1024 * 1024;
|
||||||
|
|
||||||
export function SoundboardPopover({ spaceId, canManage, onClose }: SoundboardPopoverProps) {
|
export function SoundboardPopover({ spaceId, canManage, onClose }: SoundboardPopoverProps) {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
@@ -66,7 +66,9 @@ export function SoundboardPopover({ spaceId, canManage, onClose }: SoundboardPop
|
|||||||
const created = await api.soundboard.add(spaceId, name, filename);
|
const created = await api.soundboard.add(spaceId, name, filename);
|
||||||
setSounds((prev) => [...prev, created]);
|
setSounds((prev) => [...prev, created]);
|
||||||
} catch {
|
} catch {
|
||||||
setError(t('soundboard.tooLarge'));
|
// Distinct from the size check above: reporting every failure as "too
|
||||||
|
// large" sends people to shrink a file that was never the problem.
|
||||||
|
setError(t('soundboard.uploadFailed'));
|
||||||
} finally {
|
} finally {
|
||||||
setUploading(false);
|
setUploading(false);
|
||||||
if (fileRef.current) fileRef.current.value = '';
|
if (fileRef.current) fileRef.current.value = '';
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ export function VoiceControls() {
|
|||||||
|
|
||||||
const activeDmCall = useVoiceStore((s) => s.activeDmCall);
|
const activeDmCall = useVoiceStore((s) => s.activeDmCall);
|
||||||
const channelPerms = useSpaceStore((s) => currentVoiceChannelId ? s.channelPermissions.get(currentVoiceChannelId) : undefined);
|
const channelPerms = useSpaceStore((s) => currentVoiceChannelId ? s.channelPermissions.get(currentVoiceChannelId) : undefined);
|
||||||
|
// MANAGE_SPACE lives in the space-level bitfield, not the per-channel one —
|
||||||
|
// reading it from channelPermissions silently yielded false for everyone.
|
||||||
|
const spacePerms = useSpaceStore((s) => currentVoiceSpaceId ? s.spacePermissions.get(currentVoiceSpaceId) : undefined);
|
||||||
|
const canManageSpace = hasPermissionBit(spacePerms, PermissionBits.MANAGE_SPACE);
|
||||||
|
|
||||||
// In DM calls, all permissions are granted; in space channels, check SPEAK and STREAM
|
// In DM calls, all permissions are granted; in space channels, check SPEAK and STREAM
|
||||||
const isDmCall = !!activeDmCall;
|
const isDmCall = !!activeDmCall;
|
||||||
@@ -128,7 +132,7 @@ export function VoiceControls() {
|
|||||||
{showSoundboard && currentVoiceSpaceId && (
|
{showSoundboard && currentVoiceSpaceId && (
|
||||||
<SoundboardPopover
|
<SoundboardPopover
|
||||||
spaceId={currentVoiceSpaceId}
|
spaceId={currentVoiceSpaceId}
|
||||||
canManage={hasPermissionBit(channelPerms, PermissionBits.MANAGE_SPACE)}
|
canManage={canManageSpace}
|
||||||
onClose={() => setShowSoundboard(false)}
|
onClose={() => setShowSoundboard(false)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ export const en = {
|
|||||||
'soundboard.remove': 'Remove',
|
'soundboard.remove': 'Remove',
|
||||||
'soundboard.namePrompt': 'Name for this sound',
|
'soundboard.namePrompt': 'Name for this sound',
|
||||||
'soundboard.joinFirst': 'Join a voice channel to use the soundboard.',
|
'soundboard.joinFirst': 'Join a voice channel to use the soundboard.',
|
||||||
'soundboard.tooLarge': 'Sound must be under 1 MB and a few seconds long.',
|
'soundboard.tooLarge': 'Sound must be under 2 MB and a few seconds long.',
|
||||||
|
'soundboard.uploadFailed': 'Could not upload that file. Try a different one.',
|
||||||
|
|
||||||
// Account menu (own name in the user bar)
|
// Account menu (own name in the user bar)
|
||||||
'accountMenu.editProfile': 'Edit Profile',
|
'accountMenu.editProfile': 'Edit Profile',
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ export const ptBR: Partial<Dictionary> = {
|
|||||||
'soundboard.remove': 'Remover',
|
'soundboard.remove': 'Remover',
|
||||||
'soundboard.namePrompt': 'Nome deste som',
|
'soundboard.namePrompt': 'Nome deste som',
|
||||||
'soundboard.joinFirst': 'Entre num canal de voz para usar o soundboard.',
|
'soundboard.joinFirst': 'Entre num canal de voz para usar o soundboard.',
|
||||||
'soundboard.tooLarge': 'O som precisa ter menos de 1 MB e poucos segundos.',
|
'soundboard.tooLarge': 'O som precisa ter menos de 2 MB e poucos segundos.',
|
||||||
|
'soundboard.uploadFailed': 'Não foi possível enviar esse arquivo. Tente outro.',
|
||||||
|
|
||||||
// Menu da conta (próprio nome na barra de usuário)
|
// Menu da conta (próprio nome na barra de usuário)
|
||||||
'accountMenu.editProfile': 'Editar perfil',
|
'accountMenu.editProfile': 'Editar perfil',
|
||||||
|
|||||||
Reference in New Issue
Block a user