import { useCallback, useEffect, useState } from "react" import { useTranslation } from "react-i18next" /** * Хук для управления разрешениями на доступ к микрофону */ export function useAudioPermissions() { const { t } = useTranslation() const [permissionStatus, setPermissionStatus] = useState<"pending" | "granted" | "denied" | "error">("pending") const [errorMessage, setErrorMessage] = useState("") // Проверяем текущий статус разрешений const checkPermissions = useCallback(async () => { try { // В тестовой среде просто возвращаем true if (process.env.NODE_ENV === "test") { return true } // Проверяем поддержку mediaDevices if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { setPermissionStatus("error") setErrorMessage( t( "dialogs.voiceRecord.unsupportedBrowser", "Ваш браузер не поддерживает запись аудио. Используйте современный браузер.", ), ) return false } // Проверяем, поддерживает ли браузер API разрешений if (navigator.permissions && navigator.permissions.query) { const result = await navigator.permissions.query({ name: "microphone" as PermissionName }) if (result.state === "granted") { setPermissionStatus("granted") return true } if (result.state === "denied") { setPermissionStatus("denied") setErrorMessage( t("dialogs.voiceRecord.permissionsDenied", "Доступ к микрофону запрещен. Проверьте настройки браузера."), ) return false } // Если статус "prompt", нужно запросить разрешение setPermissionStatus("pending") return await requestPermissions() } // Если API разрешений не поддерживается, пробуем запросить доступ напрямую return await requestPermissions() } catch (error) { console.error("Ошибка при проверке разрешений:", error) setPermissionStatus("error") setErrorMessage( t("dialogs.voiceRecord.permissionCheckError", "Не удалось проверить разрешения. Попробуйте еще раз."), ) return false } }, [t]) // Запрашиваем разрешения на доступ к микрофону const requestPermissions = useCallback(async () => { try { setPermissionStatus("pending") setErrorMessage("") // В тестовой среде имитируем успешный запрос разрешений if (process.env.NODE_ENV === "test") { setPermissionStatus("granted") return true } // Запрашиваем доступ к микрофону const tempStream = await navigator.mediaDevices?.getUserMedia?.({ audio: true, }) if (!tempStream) { setPermissionStatus("error") setErrorMessage( t("dialogs.voiceRecord.permissionError", "Не удалось получить доступ к микрофону. Проверьте настройки."), ) return false } // После получения доступа останавливаем временный поток tempStream.getTracks().forEach((track) => track.stop()) setPermissionStatus("granted") return true } catch (error) { console.error("Ошибка при запросе разрешений:", error) // Определяем тип ошибки if (error instanceof DOMException) { if (error.name === "NotFoundError") { setPermissionStatus("error") setErrorMessage( t("dialogs.voiceRecord.deviceNotFound", "Микрофон не найден. Подключите микрофон и попробуйте снова."), ) } else if (error.name === "NotAllowedError" || error.name === "PermissionDeniedError") { setPermissionStatus("denied") setErrorMessage( t("dialogs.voiceRecord.permissionsDenied", "Доступ к микрофону запрещен. Проверьте настройки браузера."), ) } else { setPermissionStatus("error") setErrorMessage( t("dialogs.voiceRecord.permissionError", "Не удалось получить доступ к микрофону. Проверьте настройки."), ) } } else { setPermissionStatus("error") setErrorMessage( t("dialogs.voiceRecord.unknownError", "Произошла неизвестная ошибка при запросе доступа к микрофону."), ) } return false } }, [t]) // Проверяем разрешения при монтировании компонента useEffect(() => { void checkPermissions() }, [checkPermissions]) return { permissionStatus, errorMessage, requestPermissions, setErrorMessage, } }