Реалізація конструктора сценаріїв чат-бота в мобільному додатку
Конструктор сценаріїв — це інструмент для створення та редагування діалогових потоків без програмування. На мобільному це особливо складно: обмежена площа екрана, немає миші, немає клавіатури як основного інвентарю. Все через касання на холсті з вузлами та зв'язками.
Що представляє собой конструктор сценаріїв
Типовий сценарій бота — це граф: вузли (повідомлення, питання, умови, дії) та ребра (переходи між ними). Користувач створює вузли, налаштовує їхній вміст та з'єднує стрілками. Візуально подібно до 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-вузли мають хоча б два вихідних ребра. Валідуємо як на клієнті (мгновенний feedback), так і на сервері (захист від некоректних даних).
Редагування вузлів на мобільному
Тап на вузел — відкривається 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() з мініатюри холсту, оновлюємо при кожній зміні позиції вузла (debounce 200мс).
Auto-layout: кнопка «Упорядкувати» раскладує граф алгоритмом Sugiyama (layered graph drawing) або простішим topological sort з рівномірним розподілом по шарам. Готові реалізації: graphviz через WebAssembly, або спрощена версія на 200 строк для дерев без циклів.
Терміни: від 1 тижня до 3 місяців. MVP з WebView-редактором та базовими типами вузлів — 1–2 тижні. Повнофункціональний нативний конструктор з кастомними типами вузлів, валідацією, версіюванням сценаріїв та тестуванням діалогів прямо в редакторі — 1–3 місяці.







