Визуальный редактор диалоговых деревьев бота в мобильном приложении

Мы разрабатываем визуальный редактор диалоговых деревьев для мобильных приложений. Это один из самых технически сложных UI-компонентов: бесконечный canvas, gesture-система с несколькими одновременными распознавателями, рендеринг тысяч элементов, undo/redo, сериализация графа. За 5+ лет на рынке мы р

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Визуальный редактор диалоговых деревьев бота в мобильном приложении
Сложный
от 1 недели до 3 месяцев

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    897
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    784
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1218
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1081
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1004
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    600

Мы разрабатываем визуальный редактор диалоговых деревьев для мобильных приложений. Это один из самых технически сложных UI-компонентов: бесконечный canvas, gesture-система с несколькими одновременными распознавателями, рендеринг тысяч элементов, undo/redo, сериализация графа. За 5+ лет на рынке мы реализовали десятки подобных проектов для чат-ботов в банкинге, e-commerce и поддержке. Наши инженеры владеют как нативными стеками (Swift, Kotlin), так и кроссплатформенными решениями (Flutter, React Native). Гарантируем корректную работу на всех целевых устройствах и соответствие гайдлайнам App Store и Google Play.

Как реализовать бесконечный холст?

Основа редактора — бесконечное масштабируемое пространство для размещения нод. Два принципиально разных подхода — сравним их в таблице.

Критерий UIScrollView как viewport Кастомный canvas с трансформацией
Простота реализации Высокая, нативный scroll Средняя, требуется ручная обработка жестов
Масштабирование текста Проблема: шрифты масштабируются Фикс через обратную трансформацию
Гибкость zoom-to-fit Ограниченная Полная, через матрицу
Производительность (100+ нод) Средняя Высокая (один CALayer)

На iOS UIScrollView с contentSize 5000×5000 pt — простой старт. Ноды — UIView внутри contentView. Масштабирование через minimumZoomScale/maximumZoomScale. Минус: при zoom текст становится нечитаемым. Фикс — обратная трансформация label'ов при scrollViewDidZoom. Кастомный canvas через CATransform3D даёт больше контроля: zoom-to-fit, snap-to-grid. Конфликт жестов решается через UIGestureRecognizerDelegate: pan на ноде — drag, pan на пустом месте — панорамирование.

В Jetpack Compose — Modifier.graphicsLayer с pointerInput для detectTransformGestures.

Почему важно корректное управление жестами?

Редактор использует одновременно pan, pinch, long press и tap. Без чёткой приоритетизации пользовательские действия будут интерпретироваться неверно. На iOS мы используем UIGestureRecognizerDelegate с shouldRecognizeSimultaneouslyWith для pan и pinch, а hit-test на начале жеста определяет, перетаскивается нода или холст. На Android — GestureDetector с различными слушателями. Такой подход исключает ложные срабатывания при интенсивной работе.

Рендеринг рёбер (стрелок)

Кривые Безье для соединений между нодами — визуально лучше прямых линий. Кубическая кривая от output handle к input handle:

let path = UIBezierPath() path.move(to: startPoint) let controlPoint1 = CGPoint(x: startPoint.x + (endPoint.x - startPoint.x) * 0.5, y: startPoint.y) let controlPoint2 = CGPoint(x: startPoint.x + (endPoint.x - startPoint.x) * 0.5, y: endPoint.y) path.addCurve(to: endPoint, controlPoint1: controlPoint1, controlPoint2: controlPoint2) edgeLayer.path = path.cgPath 

Каждое ребро — CAShapeLayer с strokeColor и стрелочным наконечником. При перемещении ноды — пересчитываем все CAShapeLayer.path для входящих и исходящих рёбер. CATransaction.begin(); CATransaction.setDisableActions(true) для мгновенного обновления. При большом количестве рёбер (50+) — рендеринг через один общий CALayer с draw-методом: один CGContext.addPath() для всех рёбер быстрее чем 50 отдельных слоёв.

Интерактивное создание связей

Пользователь тащит от output handle одной ноды к input handle другой — создаётся новое ребро. Реализация:

  1. UILongPressGestureRecognizer (duration 0.0) на handle view — начало drag
  2. При .began — создаём temporaryEdgeLayer, начало зафиксировано на handle
  3. При .changed — обновляем конец temporaryEdgeLayer на позицию пальца
  4. Hit-test при каждом .changed: canvas.hitTest(location, with: nil) — если попадаем на input handle — подсвечиваем её
  5. При .ended — если под пальцем input handle — создаём постоянное ребро, иначе удаляем temporaryEdgeLayer

Предотвращение невалидных связей: нельзя соединить ноду с собой, нельзя создать дублирующую связь, нельзя создать цикл (если граф должен быть DAG). Проверка цикла — DFS из target ноды. O(V + E) — быстро для типичных диалоговых деревьев.

Редактирование нод

Тап на ноду — открывается редактор содержимого. Для диалогового узла типа «Message»: UITextView с rich text поддержкой для текста сообщения, переключатель типа (текст/медиа/кнопки), список кнопок с возможностью добавить/удалить.

Bottom sheet (iOS 15+ UISheetPresentationController с .medium и .large detents) — пользователь видит граф и редактор одновременно в medium режиме. Keyboard avoidance: при появлении клавиатуры нижний padding UIScrollView внутри sheet увеличивается на keyboardFrame.height - sheet.frame.height + sheetMaxHeight. Обрабатывается через UIKeyboardWillShowNotification.

Undo/Redo

Command Pattern — каждое действие (перемещение ноды, создание/удаление ребра, редактирование содержимого) реализуется как объект команды с методами execute() и undo().

protocol GraphCommand { func execute() func undo() } struct MoveNodeCommand: GraphCommand { let node: GraphNode let fromPosition: CGPoint let toPosition: CGPoint func execute() { node.position = toPosition } func undo() { node.position = fromPosition } } 

UndoManager — встроен в iOS UIKit, работает с registerUndo(withTarget:handler:). Или собственный CommandStack с undoStack: [GraphCommand] и redoStack: [GraphCommand]. Группировка команд: перемещение нескольких выделенных нод — одна операция undo.

Выделение и multiple selection

Лассо-выделение: pan на пустом пространстве при удержании нажатия — рисует прямоугольник выделения через CAShapeLayer с fillColor = UIColor.blue.withAlphaComponent(0.1) и strokeColor = UIColor.blue. При завершении жеста — проверяем все ноды на пересечение. Выделенные ноды — синяя обводка через layer.borderColor. Pan на выделении перемещает все выделенные ноды одновременно. Delete — удаление всех выделенных нод и инцидентных рёбер.

Сериализация и синхронизация

Граф → JSON с полным описанием нод и рёбер. Автосохранение каждые 30 секунд или при каждом изменении с debounce 2 секунды. На iOS — Combine.debounce(for: .seconds(2), scheduler: RunLoop.main) на publisher изменений графа, затем URLSession.shared.dataTask для отправки на сервер.

Conflict resolution при совместном редактировании: Last-Write-Wins на уровне ноды с timestamp сервера. updatedAt: Date на каждой ноде — при merge берём версию с более поздним timestamp.

Что входит в работу?

  • Исследование и проектирование структуры узлов под ваш чат-бот
  • Реализация кастомного canvas с бесконечным холстом и масштабированием
  • Система undo/redo и multiple selection
  • Интеграция с вашим бэкендом через REST/GraphQL
  • Поддержка всех типов узлов (текст, медиа, кнопки, условия)
  • Тестирование на целевых устройствах и публикация в сторах
  • Документация и обучение вашей команды

Срок: от 1 недели до 3 месяцев. Стоимость рассчитывается индивидуально после анализа требований. Свяжитесь с нами — оценим ваш проект и предложим оптимальное решение.