feat(instance): сервер установщика больше не «главный»
Понятие главного сервера убрано из поведения: сервер, создаваемый установщиком, обычный (is_main = false), автовступления в него нет, а в настройках инстанса он остаётся лишь справочно (main_guild_id → AdminGuildID в ответе API). Клиент от него больше не зависит: новичок начинает с пустым списком серверов.
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import type { VoiceDeviceKind } from '@/stores/voice';
|
||||
|
||||
/** Устройство ввода/вывода в том виде, в каком его показывает интерфейс. */
|
||||
export interface MediaDevice {
|
||||
deviceId: string;
|
||||
/** Подпись может быть пустой: браузер скрывает её без разрешения. */
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface MediaDevicesResult {
|
||||
devices: MediaDevice[];
|
||||
/** Доступен ли `navigator.mediaDevices.enumerateDevices()`. */
|
||||
supported: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Список устройств нужного вида через `navigator.mediaDevices`.
|
||||
*
|
||||
* Без разрешения на доступ браузер отдаёт устройства с пустыми подписями —
|
||||
* их показываем как «Устройство N». Если API недоступно (старый браузер или
|
||||
* тестовое окружение), возвращаем `supported: false`.
|
||||
*/
|
||||
export function useMediaDevices(kind: VoiceDeviceKind): MediaDevicesResult {
|
||||
const supported =
|
||||
typeof navigator !== 'undefined' &&
|
||||
typeof navigator.mediaDevices?.enumerateDevices === 'function';
|
||||
const [devices, setDevices] = useState<MediaDevice[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!supported) {
|
||||
setDevices([]);
|
||||
return;
|
||||
}
|
||||
let cancelled = false;
|
||||
|
||||
const load = (): void => {
|
||||
void navigator.mediaDevices
|
||||
.enumerateDevices()
|
||||
.then((list) => {
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
setDevices(
|
||||
list
|
||||
.filter((device) => device.kind === kind)
|
||||
.map((device) => ({ deviceId: device.deviceId, label: device.label })),
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
setDevices([]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
load();
|
||||
// Список меняется при подключении гарнитуры — обновляем его на лету.
|
||||
navigator.mediaDevices.addEventListener?.('devicechange', load);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
navigator.mediaDevices.removeEventListener?.('devicechange', load);
|
||||
};
|
||||
}, [kind, supported]);
|
||||
|
||||
return { devices, supported };
|
||||
}
|
||||
Reference in New Issue
Block a user