feat: soundboard, account menu, and call timer
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
Soundboard: the trigger travels over the WebSocket and every client in the call plays the clip locally, instead of mixing it into the presser's microphone or publishing a LiveKit track. No upstream bandwidth, no media stack changes, and the clip is not degraded by voice processing. Fan-out uses a new sendToRoomParticipants rather than sendToRoom: the latter broadcasts a space room to the whole space, which is right for the presence the sidebar shows and wrong for anything audible. The cooldown is enforced server-side — a client-side one only slows down people not trying to abuse it, and a soundboard is the easiest thing here to turn into a weapon. Playing is open to anyone in the call; deciding what the buttons are needs MANAGE_SPACE. Account menu: the name in the user bar had cursor-pointer and no handler, so the interface was already promising a click that did nothing. Offers profile, status and copy-id — not the Clips or account switching the reference design shows, which would be dead UI here. Call timer: startedAt comes from the server, so a late joiner sees the call's age rather than their own arrival. Empty space rooms are destroyed already, which is what makes the next call start from zero — no reset logic needed.
This commit is contained in:
@@ -33,6 +33,26 @@ export const en = {
|
||||
'settings.voice.micTest.idle': 'Test your mic without joining a call.',
|
||||
'settings.voice.micTest.failed': 'Could not open the microphone. Check the device and its permission.',
|
||||
|
||||
// Soundboard
|
||||
'soundboard.title': 'Soundboard',
|
||||
'soundboard.empty': 'No sounds yet.',
|
||||
'soundboard.add': 'Add sound',
|
||||
'soundboard.adding': 'Uploading...',
|
||||
'soundboard.remove': 'Remove',
|
||||
'soundboard.namePrompt': 'Name for this sound',
|
||||
'soundboard.joinFirst': 'Join a voice channel to use the soundboard.',
|
||||
'soundboard.tooLarge': 'Sound must be under 1 MB and a few seconds long.',
|
||||
|
||||
// Account menu (own name in the user bar)
|
||||
'accountMenu.editProfile': 'Edit Profile',
|
||||
'accountMenu.status': 'Status',
|
||||
'accountMenu.status.online': 'Online',
|
||||
'accountMenu.status.idle': 'Idle',
|
||||
'accountMenu.status.dnd': 'Do Not Disturb',
|
||||
'accountMenu.status.offline': 'Invisible',
|
||||
'accountMenu.copyId': 'Copy User ID',
|
||||
'accountMenu.copied': 'Copied',
|
||||
|
||||
// Statistics
|
||||
'stats.title': 'Statistics',
|
||||
'stats.range.7': 'Last 7 days',
|
||||
|
||||
@@ -32,6 +32,26 @@ export const ptBR: Partial<Dictionary> = {
|
||||
'settings.voice.micTest.idle': 'Teste seu microfone sem entrar numa call.',
|
||||
'settings.voice.micTest.failed': 'Não foi possível abrir o microfone. Verifique o dispositivo e a permissão.',
|
||||
|
||||
// Soundboard
|
||||
'soundboard.title': 'Soundboard',
|
||||
'soundboard.empty': 'Nenhum som ainda.',
|
||||
'soundboard.add': 'Adicionar som',
|
||||
'soundboard.adding': 'Enviando...',
|
||||
'soundboard.remove': 'Remover',
|
||||
'soundboard.namePrompt': 'Nome deste som',
|
||||
'soundboard.joinFirst': 'Entre num canal de voz para usar o soundboard.',
|
||||
'soundboard.tooLarge': 'O som precisa ter menos de 1 MB e poucos segundos.',
|
||||
|
||||
// Menu da conta (próprio nome na barra de usuário)
|
||||
'accountMenu.editProfile': 'Editar perfil',
|
||||
'accountMenu.status': 'Status',
|
||||
'accountMenu.status.online': 'Disponível',
|
||||
'accountMenu.status.idle': 'Ausente',
|
||||
'accountMenu.status.dnd': 'Não perturbe',
|
||||
'accountMenu.status.offline': 'Invisível',
|
||||
'accountMenu.copyId': 'Copiar ID do usuário',
|
||||
'accountMenu.copied': 'Copiado',
|
||||
|
||||
// Estatísticas
|
||||
'stats.title': 'Estatísticas',
|
||||
'stats.range.7': 'Últimos 7 dias',
|
||||
|
||||
Reference in New Issue
Block a user