feat(voice): саундборд, звуковая палитра, push-to-talk и статистика соединения

Клиентская часть Фазы 3 (AGENT.md 7.13, 7.14): звуки сервера, локальные
звуки интерфейса и телеметрия медиа.

- саундборд: `api/sounds.ts` (лимиты 512 КБ и 30 на вид, multipart-загрузка,
  play, `SOUND_EVENTS`), `lib/soundboard.ts` (blob-кэш `/files/{id}`,
  наложение до 8 звуков, громкость = `outputVolume`, тишина при дефене),
  попап в панели комнаты (`USE_SOUNDBOARD`), таймер на `rate_limited`,
  подпись «включил звук» и защита от двойного воспроизведения;
- звуковая палитра: `SOUNDBOARD_PLAY` и события сервера (вход/выход
  участника, упоминание, сообщение, вход/выход из голосовой, свои
  микрофон/камера/экран, серверный мьют) → `playEventSound`;
- секция «Звуки» в настройках сервера (`MANAGE_SOUNDS`): два вида со
  счётчиками, drag&drop, имя, эмодзи, событие палитры, переименование,
  удаление и клиентские проверки файла;
- push-to-talk: режим и клавиша (`event.code`), хук в `AppLayout`, вход в
  комнату с выключенным микрофоном, удержание включает публикацию, отпускание
  и потеря фокуса выключают, серверный мьют приоритетнее;
- статистика: поповер с разрешением, fps, кодеком, битрейтом, RTT, потерями
  и jitter (опрос раз в секунду, остановка при закрытии), выбор качества
  публикации low/medium/high, пресеты шаринга экрана 1080p60…480p30;
- данные: `guilds[].sounds` из READY, `GUILD_SOUNDS_UPDATE`, селектор
  `useGuildSounds`, тумблеры звуков в «Аудио-видео» (localStorage);
- тесты: `soundboard`, `soundSettings`, `pushToTalk`, `voiceStats` и
  расширенный фейковый LiveKit SDK.
This commit is contained in:
2026-09-20 19:30:43 +03:00
parent 2538e07ec3
commit 619bd91df4
40 changed files with 4269 additions and 48 deletions
+36
View File
@@ -41,6 +41,8 @@ export const PERMISSION_MANAGE_GUILD = 'MANAGE_GUILD';
export const PERMISSION_MANAGE_CHANNELS = 'MANAGE_CHANNELS';
export const PERMISSION_MANAGE_MESSAGES = 'MANAGE_MESSAGES';
export const PERMISSION_MANAGE_EMOJIS = 'MANAGE_EMOJIS';
export const PERMISSION_MANAGE_SOUNDS = 'MANAGE_SOUNDS';
export const PERMISSION_USE_SOUNDBOARD = 'USE_SOUNDBOARD';
export const PERMISSION_SEND_MESSAGES = 'SEND_MESSAGES';
export const PERMISSION_ATTACH_FILES = 'ATTACH_FILES';
export const PERMISSION_ADD_REACTIONS = 'ADD_REACTIONS';
@@ -186,6 +188,40 @@ export function canManageEmojis(
);
}
/**
* Может ли пользователь управлять звуками сервера (AGENT.md 7.13): владелец,
* ADMINISTRATOR, MANAGE_SOUNDS или администратор инстанса.
*/
export function canManageSounds(
permissions: readonly string[],
ownerId: string,
userId: string | undefined,
isInstanceAdmin = false,
): boolean {
if (isInstanceAdmin || (userId !== undefined && userId === ownerId)) {
return true;
}
return (
hasPermission(permissions, PERMISSION_ADMINISTRATOR) ||
hasPermission(permissions, PERMISSION_MANAGE_SOUNDS)
);
}
/**
* Может ли пользователь играть звуки саундборда (AGENT.md 7.13): право
* `USE_SOUNDBOARD`. Присутствие в голосовой комнате проверяется отдельно —
* сервер отвечает `voice.not_connected`, если мы не в комнате.
*/
export function canUseSoundboard(permissions: readonly string[], isInstanceAdmin = false): boolean {
if (isInstanceAdmin) {
return true;
}
return (
hasPermission(permissions, PERMISSION_ADMINISTRATOR) ||
hasPermission(permissions, PERMISSION_USE_SOUNDBOARD)
);
}
/** Может ли пользователь отправлять сообщения в комнату. */
export function canSendMessages(
permissions: readonly string[],