Реализация конструктора сценариев чат-бота в мобильном приложении
Конструктор сценариев — это инструмент для создания и редактирования диалоговых потоков бота без программирования. На мобильном устройстве это особенно сложно: ограниченная площадь экрана, нет мыши, нет клавиатуры как основного инвентаря. Всё через касания на холсте с нодами и связями.
Что представляет собой конструктор сценариев
Типичный сценарий бота — это граф: узлы (сообщения, вопросы, условия, действия) и рёбра (переходы между ними). Пользователь создаёт узлы, настраивает их содержимое и соединяет стрелками. Визуально похоже на Miro или диаграмму в Figma, только с предметной логикой чат-бота.
Ключевые типы узлов:
- Message — бот отправляет текст/медиа
- Input — бот ожидает ответ пользователя
- Condition — ветвление по условию (ответ содержит слово X, переменная Y > 0)
- Action — интеграция с внешней системой (отправить email, создать запись в CRM)
- GoTo — переход к другому узлу или сценарию
Архитектура графового редактора
Реализовать редактор графов на мобильном — нетривиальная задача. Два основных подхода:
WebView-based. Встраиваем веб-редактор (React Flow, JointJS, mxGraph) в WKWebView / WebView. Коммуникация через WKScriptMessageHandler / addJavascriptInterface. Плюс: повторное использование веб-версии редактора, богатые библиотеки для работы с графами. Минус: производительность на сложных графах, нативный look&feel теряется, bridge overhead при частых обновлениях.
Нативный Canvas. iOS — UIScrollView как контейнер для бесконечного холста, узлы как UIView/CALayer, рёбра рисуются через CAShapeLayer с UIBezierPath. Жесты: UIPanGestureRecognizer для перемещения узлов и прокрутки холста, UIPinchGestureRecognizer для масштабирования, UITapGestureRecognizer для выбора. В SwiftUI — Canvas API с GraphicsContext для отрисовки и Gesture модификаторы.
Конфликт жестов — самая болезненная проблема. Pan для перемещения узла vs pan для скролла холста: различаем по hit-test (view.hitTest(_:with:)) — если жест начался на узле, двигаем узел; если на пустом пространстве, скроллим холст. UIGestureRecognizerDelegate.gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) для настройки одновременного распознавания.
Для Flutter — библиотека flutter_flow_chart или кастомная реализация через CustomPainter + GestureDetector. CustomPainter.paint() вызывается при каждой перерисовке, нужно кешировать Path объекты для рёбер.
Модель данных сценария
Граф сериализуется в JSON для хранения и передачи. Минимальная схема:
{
"id": "scenario_123",
"nodes": [
{"id": "n1", "type": "message", "x": 100, "y": 200, "data": {"text": "Привет!"}},
{"id": "n2", "type": "input", "x": 300, "y": 200, "data": {"variable": "user_name"}}
],
"edges": [
{"id": "e1", "source": "n1", "target": "n2", "sourceHandle": "output", "targetHandle": "input"}
]
}
Валидация графа перед сохранением: нет изолированных узлов, нет циклов (если не предусмотрены), стартовый узел определён, все condition-узлы имеют хотя бы два исходящих ребра. Валидацию делаем как на клиенте (мгновенная обратная связь), так и на сервере (защита от некорректных данных).
Редактирование узлов на мобильном
Тап на узел — открывается bottom sheet или modal с формой редактирования. UISheetPresentationController (iOS 15+) с detents: [.medium(), .large()] — пользователь может развернуть до полного экрана для длинных текстов. В Compose — ModalBottomSheet из Material3.
Для message-узла с поддержкой rich text — UITextView с NSAttributedString или TextEditor в SwiftUI. Для условий — DSL-конструктор: выбор переменной + выбор оператора + ввод значения через три последовательных picker/input.
Масштабирование и навигация по холсту
При 50+ узлах на холсте нужна миникарта — уменьшенное превью всего графа с индикатором текущего viewport. Рисуем через UIGraphicsImageRenderer или Canvas.drawImage() из миниатюры холста, обновляем при каждом изменении позиции узла (дебаунс 200мс).
Auto-layout: кнопка «Упорядочить» раскладывает граф алгоритмом Sugiyama (layered graph drawing) или более простым topological sort с равномерным распределением по слоям. Готовые реализации: graphviz через WebAssembly, или упрощённая версия на 200 строк для деревьев без циклов.
Срок: от 1 недели до 3 месяцев. MVP с WebView-редактором и базовыми типами узлов — 1–2 недели. Полноценный нативный конструктор с кастомными типами узлов, валидацией, версионированием сценариев и тестированием диалогов прямо в редакторе — 1–3 месяца.







