Skip to content

Архитектура

Виджет — это 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.

Синглтоны

Несколько модульных синглтонов гарантируют один разговор на всех поверхностях:

СинглтонФайлРоль
WebsocketConnectionsrc/services/WebsocketConnection.jsЕдинственное WS-соединение; несёт ws_token в query для восстановления сессии; реконнект при возврате вкладки / online.
WebsocketEventssrc/services/WebsocketEvents.jsРеестр обработчиков входящих событий; навешивается один раз в bootstrap.js.
Redux storesrc/store.jsВсе сообщения и UI-состояние. Редьюсеры: bot, menu, options, notifications, wsEvents.
StaticStoresrc/services/StaticStore.jsIn-memory кэш: ws-token, состояние header'а оператора и т.п.
overlayStoresrc/services/overlayStore.jsPub-sub видимости и open/close overlay-лаунчера (через useSyncExternalStore).

Bootstrap

Однократная инициализация сокета — в src/bootstrap.js (защищена от повторного запуска):

  1. Создать WebSocket и обработчики (WebsocketConnection.getInstance(), WebsocketEvents.getInstance()).
  2. Восстановить header оператора из sessionStorage, если есть.
  3. Отправить действие «start» на бэкенд (≈через 1 c).
  4. Навесить слушатели 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

См. также Сборку — как это превращается в один бандл.