Visual Bot Dialog Tree Editor in Mobile App

TRUETECH is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Visual Bot Dialog Tree Editor in Mobile App
Complex
from 1 week to 3 months
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Implementing Visual Dialog Tree Editor for Bot in Mobile Apps

A visual dialog tree editor is a full-featured graph editor right in the mobile app. User moves nodes around canvas, connects them with arrows, edits each node's content. One of the most technically complex UI components in mobile development: infinite canvas, multi-gesture system, rendering thousands of elements, undo/redo, graph serialization.

Foundation: Infinite Canvas

Base of the editor — infinite scalable space for node placement. Two fundamentally different approaches:

UIScrollView as Viewport

On iOS, UIScrollView with contentSize much larger than visible area (e.g., 5000×5000 pt). Nodes — UIView inside contentView. Zoom via UIScrollView.minimumZoomScale / maximumZoomScale and viewForZooming(in:). Pros: native scroll, momentum, rubber band — free. Cons: at zoom, nodes scale with text, labels become too small or large. Fix — inverse transform text: on scrollViewDidZoom apply CGAffineTransform(scaleX: 1/zoomScale, y: 1/zoomScale) to text inside nodes so font stays readable.

Custom Canvas with Transform

More flexible: canvas — single UIView with CATransform3D transform. UIPinchGestureRecognizer updates scale, UIPanGestureRecognizertranslation. All nodes positioned in "world" coordinates, screen space conversion via transform matrix. This enables zoom-to-fit, zoom-to-selection, snap-to-grid more precisely.

Gesture conflict solved via UIGestureRecognizerDelegate: pan and pinch work simultaneously, but pan on node — drag node, pan on empty space — pan canvas. Hit-test on gesture start determines mode.

In Jetpack Compose — Modifier.graphicsLayer { scaleX = canvasScale; scaleY = canvasScale; translationX = offsetX; translationY = offsetY } with pointerInput for pan and pinch via detectTransformGestures.

Edge (Arrow) Rendering

Bezier curves for connections between nodes — visually better than straight lines. Cubic curve from source node's output handle to target's 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

Each edge — CAShapeLayer with strokeColor and arrow head via additional CAShapeLayer with triangle or lineCap = .round with custom endcap via CAShapeLayer + UIBezierPath.

Update edges on node movement: on pan.changed on node — recalculate all CAShapeLayer.path for incoming and outgoing edges. CATransaction.begin(); CATransaction.setDisableActions(true) for instant update without implicit animation.

With many edges (50+) — render via single CALayer with draw-method and setNeedsDisplay() on changes. One large CGContext.addPath() for all edges faster than 50 separate CAShapeLayer.

Interactive Connection Creation

User drags from output handle of one node to input handle of another — new edge created. Implementation:

  1. UILongPressGestureRecognizer (duration 0.0) on handle view — start drag
  2. On .began — create temporaryEdgeLayer, start fixed on handle
  3. On .changed — update temporaryEdgeLayer end to finger position
  4. Hit-test on each .changed: canvas.hitTest(location, with: nil) — if hit input handle, highlight it
  5. On .ended — if input handle under finger, create permanent edge, else remove temporaryEdgeLayer

Prevent invalid connections: can't connect output to itself, no duplicate connections, no cycles (if graph should be DAG). Cycle check — DFS from target node, check source reachability. O(V + E) — fast for typical dialog trees.

Node Editing

Tap node — opens content editor. For "Message" dialog node: UITextView with rich text for message text, type toggle (text/media/buttons), button list with add/delete.

Bottom sheet (iOS 15+ UISheetPresentationController with .medium and .large detents) for editor — user sees graph and editor simultaneously in medium. At full expansion, graph hidden. sheetPresentationController.animateChanges { self.detentIdentifier = .large } for programmatic toggle.

Keyboard avoidance: on keyboard show, bottom UIScrollView padding inside sheet increases by keyboardFrame.height - sheet.frame.height + sheetMaxHeight. Handle via UIKeyboardWillShowNotification.

Undo/Redo

Command Pattern — each action (move node, create/delete edge, edit content) as command object with execute() and undo() methods.

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 — built-in iOS, works with registerUndo(withTarget:handler:). Or custom CommandStack with undoStack: [GraphCommand] and redoStack: [GraphCommand]. Shake-to-undo on iOS works automatically with UndoManager on motionBegan(_:with:).

Group commands: moving multiple selected nodes — one undo operation. UndoManager.beginUndoGrouping() / endUndoGrouping() or wrapper CompositeCommand.

Selection and Multiple Selection

Lasso selection: pan on empty space while held — draws selection rectangle via CAShapeLayer with fillColor = UIColor.blue.withAlphaComponent(0.1) and strokeColor = UIColor.blue. On gesture end — check all nodes for intersection with rectangle via node.frame.intersects(selectionRect) in world coordinates.

Selected nodes — visual highlight (blue border via layer.borderColor, layer.borderWidth). Pan on selection moves all selected nodes together, preserving relative positions. Delete — remove all selected nodes and incident edges.

Serialization and Sync

Graph → JSON with complete node and edge description. Auto-save every 30 seconds or on each change with 2-second debounce. On iOS — Combine.debounce(for: .seconds(2), scheduler: RunLoop.main) on graph change publisher, then URLSession.shared.dataTask to send server.

Conflict resolution in collaborative editing: Operational Transform (complex) or CRDT (Conflict-free Replicated Data Types) — for dialog trees, Last-Write-Wins per node with server timestamp suffices. updatedAt: Date on each node, on merge take version with later timestamp.

Timeline: 1 week to 3 months. WebView-based React Flow editor with native wrapper — 1–2 weeks. Full native editor with custom canvas, undo/redo, multi-select, real-time sync and all node types — 1.5–3 months.