Архитектура
Виджет — это React-приложение, смонтированное в shadow DOM и общающееся с бэкендом (morzebot-backend-v2, Router) по WebSocket. Ниже — ключевые архитектурные идеи, важные при интеграции и доработке.
Custom element и shadow DOM
- Виджет регистрирует кастом-элемент
<mz-bot>(вsrc/index.js). - Основной виджет монтируется на хост
<mz-bot id="__mz-bot">, overlay — на<mz-bot id="__mz-bot-overlay">. - Shadow root открыт (
mode: 'open'), что позволяет извне читать CSS-переменные хоста. - Все стили инлайнятся в JS (через
vite-plugin-css-injected-by-js) и инжектятся в shadow root, а стили хоста не ломают виджет.
Поверхности (surfaces)
Виджет умеет монтировать несколько презентаций одного разговора одновременно. Каждая поверхность — свой <mz-bot> host + shadow root + React root, но один store и одинWebsocketConnection, поэтому все поверхности синхронны по одному сокету.
| Поверхность | Что это | Host |
|---|---|---|
| primary | Основной режим (static / inline / classic) | #__mz-bot |
| overlay | Опциональный плавающий лаунчер (chat.overlay.enabled) | #__mz-bot-overlay на <body> |
Дескриптор поверхности (id, host, mode, position) передаётся через SurfaceContext (src/contexts/SurfaceContext.js). Компоненты берут свой host/режим из useSurface(), не из getElementById('__mz-bot') и не из глобальных config.STATIC/INLINE/CHAT_TYPE.
Изоляция состояния поверхностей
Per-surface ключи в StaticStore (ChatOpen:<id>, ChatWasOpened:<id>, seen-count) — чтобы поверхности не затирали состояние друг друга. Видимость overlay — отдельный внешний стор src/services/overlayStore.js.
Синглтоны
Несколько модульных синглтонов гарантируют один разговор на всех поверхностях:
| Синглтон | Файл | Роль |
|---|---|---|
WebsocketConnection | src/services/WebsocketConnection.js | Единственное WS-соединение; несёт ws_token в query для восстановления сессии; реконнект при возврате вкладки / online. |
WebsocketEvents | src/services/WebsocketEvents.js | Реестр обработчиков входящих событий; навешивается один раз в bootstrap.js. |
Redux store | src/store.js | Все сообщения и UI-состояние. Редьюсеры: bot, menu, options, notifications, wsEvents. |
StaticStore | src/services/StaticStore.js | In-memory кэш: ws-token, состояние header'а оператора и т.п. |
overlayStore | src/services/overlayStore.js | Pub-sub видимости и open/close overlay-лаунчера (через useSyncExternalStore). |
Bootstrap
Однократная инициализация сокета — в src/bootstrap.js (защищена от повторного запуска):
- Создать WebSocket и обработчики (
WebsocketConnection.getInstance(),WebsocketEvents.getInstance()). - Восстановить header оператора из
sessionStorage, если есть. - Отправить действие «start» на бэкенд (≈через 1 c).
- Навесить слушатели visibility/online для авто-реконнекта.
Поток сообщения
виджет ──msg──► Router (morzebot-backend-v2, :9000)
▲ │ маршрутизирует в движок сценариев / Messenger
│ event:* по WS ▼
└───────────────────────┘ Router шлёт события (typing, caption_after, …) обратно по WSБэкенд этого виджета — именно Router (morzebot-backend-v2), не support-panel.
Структура src/
src/
index.js # entrypoint: разрешение конфига, монтирование поверхностей, установка MZBOT API
bootstrap.js # однократная инициализация сокета и обработчиков
config.js # итоговый разрешённый конфиг (генерится на старте; в .gitignore)
theme.js # машина состояний темы + глобальный MZBOT API
store.js # конфигурация Redux store
App.js # корневой компонент (монтируется на поверхность через SurfaceContext)
components/ # Main, Header, Logs, Controls, ClosedButton, Messengers, Options, Menu,
# Notification, ResizeWrapper, ReturnToBot, LazyImage, ErrorBoundary
contexts/ # SurfaceContext — дескриптор поверхности (id, host, mode, position)
services/ # WebsocketConnection, WebsocketEvents, StaticStore, overlayStore, Notification
reducers/ # bot, menu, options, notifications, wsEvents/
actions/ # bot, menu, options, notification, types
helpers/ # commonHelper (sendAction, botElement, userUuid), soundHelper, scrollLock,
# bitrixHelper, fileHelper, messageHelper, cookieHelper, …
hooks/ # usePrevious, animateOpacity, openToggleRoot
assets/ # styles (theme-runtime.scss), svg, fonts, imgСм. также Сборку — как это превращается в один бандл.