Skip to main content
Хук useThunderPhone предоставляет полный контроль над пользовательским интерфейсом, пока ThunderPhone управляет голосовым сеансом, маршрутизацией аудио и состоянием подключения. Используйте его, если нужен полностью кастомный UI — собственные кнопки, макеты, анимации и брендинг, — пока ThunderPhone берёт на себя всю внутреннюю работу.

Когда использовать Headless-хук

Готовый компонент ThunderPhoneWidget покрывает большинство сценариев, но используйте headless-хук, если вам нужны:
  • Полностью кастомный интерфейс звонка, соответствующий дизайн-системе вашего приложения
  • Визуализации, реагирующие на аудио в реальном времени (волновые формы, сферы, пульсирующие индикаторы)
  • Кастомные сценарии звонка, например формы перед звонком, опросы после звонка или встроенный чат рядом с голосовым взаимодействием
  • Интеграция с существующей библиотекой компонентов (Material UI, Chakra, Radix и т. д.)

Установка

Headless-хук не требует импортировать @thunderphone/widget/style.css, поскольку вы создаёте собственный UI. Однако всё равно необходимо установить тот же пакет @thunderphone/widget.

Базовое использование

Необходимо отрендерить phone.audio где-либо в дереве компонентов. Это невидимый элемент React, который управляет базовым аудиоподключением. Если его не добавить, аудио не будет воспроизводиться, а сеанс не будет работать.

Параметры

Передавайте эти параметры в useThunderPhone через UseThunderPhoneOptions:
Хук не имеет интерфейса: он не принимает свойства оформления ThunderPhoneWidget (theme, primaryColor, title, position, className). Их передача вызывает ошибку TypeScript — всё представление вы реализуете самостоятельно.

Возвращаемое значение

Хук возвращает объект UseThunderPhoneReturn:

Интерфейс, реагирующий на аудио

Ссылка audioLevelRef предоставляет уровни аудио с частотой кадров без запуска повторного рендеринга React, поэтому она идеально подходит для плавной визуализации волновой формы, пульсирующих сфер или любой анимации, связанной с разговором. Уровень отражает более громкий источник: голос агента или микрофон посетителя.

Пример волновой формы

Пример пульсирующей сферы

Пример индикатора речи

Для интерфейса, рендерируемого React и меняющегося в зависимости от громкости — например, бейджа «говорит» на основе порогового значения — считывайте audioLevelRef.current через интервалы и сохраняйте результат в состоянии:
Всегда считывайте уровни из audioLevelRef.current. Число audioLevel в возвращаемом объекте устарело и всегда равно 0 — любая логика, основанная на нём, будет незаметно получать ноль.

Конечный автомат

Свойство state проходит следующий жизненный цикл:

Примеры

С элементом управления отключением микрофона

С рингтоном

Воспроизводите звук звонка во время подключения, чтобы имитировать телефонный вызов:
Рингтон воспроизводится по кругу в состоянии connecting и постепенно затихает, когда агент подключается. Передайте true, чтобы использовать встроенный рингтон по умолчанию, или строку URL, чтобы использовать собственный аудиофайл.

С обратными вызовами событий

Полностью пользовательский интерфейс


Советы

Элемент phone.audio невидим, но обязателен. Разместите его в любом месте JSX — он не рендерит видимый DOM, но внутренне управляет аудиосоединением WebRTC.
Состояние connecting может длиться 1–3 секунды. Отключайте кнопку звонка в этом состоянии, чтобы предотвратить повторные попытки подключения.
Когда состояние равно error, покажите пользователю phone.error и оставьте кнопку звонка включённой. Хук не выходит из состояния error самостоятельно — повторный вызов connect() запускает новую попытку и очищает предыдущую ошибку.
Колбэки onConnect, onDisconnect и onError идеально подходят для аналитики, логирования или запуска другой логики приложения без опроса состояния.
audioLevelRef — единственный источник уровня аудио в реальном времени. Считывайте audioLevelRef.current внутри requestAnimationFrame для плавных анимаций, таких как волновые формы (чтение ref не вызывает повторный рендеринг), или считывайте его с интервалом и сохраняйте результат в состоянии для интерфейса, рендеримого React. Число audioLevel устарело и всегда равно 0 — не стройте на нём логику.