Project

General

Profile

Arhitecture Simplified » History » Version 1

Tomislav Pleše, 10/11/2025 08:48 PM

1 1 Tomislav Pleše
# Arhitecture Simplified
2
3
4
# Flutter Application Flow: User-AI Interaction Tree (Simplified)
5
6
**Project**: TestAI (fe_kommentall)  
7
**Framework**: Flutter/Dart  
8
**Purpose**: Multi-branch AI conversation interface with sub-prompt capabilities
9
10
---
11
12
## Table of Contents
13
14
1. [Application Entry Point](#1-application-entry-point)
15
2. [Home Screen Initialization](#2-home-screen-initialization)
16
3. [User Input Flow](#3-user-input-flow)
17
4. [Prompt Processing Flow](#4-prompt-processing-flow)
18
5. [Home Screen Manager Processing](#5-home-screen-manager-processing)
19
6. [Thread Map Update](#6-thread-map-update-core-logic)
20
7. [Tree View Update](#7-tree-view-update)
21
8. [Tree Rendering Flow](#8-tree-rendering-flow)
22
9. [Tree Structure Building](#9-tree-structure-building)
23
10. [Tree Item Rendering](#10-tree-item-rendering)
24
11. [Individual Tree Item Display](#11-individual-tree-item-display)
25
12. [Sub-Prompt Preparation](#12-sub-prompt-preparation)
26
13. [Node Selection](#13-node-selection)
27
14. [Data Models](#14-data-models)
28
15. [Complete Flow Summary](#15-complete-flow-summary)
29
16. [Key Architectural Patterns](#key-architectural-patterns)
30
31
---
32
33
## 1. Application Entry Point
34
35
### Flow
36
```
37
main.dart
38
  └─ main()
39
     └─ runApp(MyApp())
40
```
41
42
---
43
44
## 2. Home Screen Initialization
45
46
### `HomeScreen` (StatefulWidget)
47
**Location**: `lib/screens/home_screen.dart`
48
49
### Flow
50
```
51
HomeScreen
52
  └─ HomeScreenState.initState()
53
     ├─ Initialize PromptArgs (empty state)
54
     ├─ Create BackendService()
55
     ├─ Create PointManager(backendService)
56
     ├─ Create TreeViewManager()
57
     ├─ Create ShardManager(pointManager, backendService)
58
     ├─ Create ThreadManager(pointManager, shardManager, backendService, threadMap, onMapUpdated)
59
     ├─ Create ContextManager(threadManager, apiService, threadMap)
60
     └─ Create HomeScreenManager(all managers, callbacks)
61
```
62
63
### State Variables
64
```
65
- threadMap: Map<String, Point> (cache of all Points)
66
- treeViewList: List<Point> (Points to display)
67
- promptArgs: PromptArgs (current prompt context)
68
- loadingExchanges: Set<String> (track loading states)
69
- isLoading: bool (global loading state)
70
- errorMessage: String? (error display)
71
```
72
73
---
74
75
## 3. User Input Flow
76
77
### Flow
78
```
79
PromptInputField (StatefulWidget)
80
  └─ User types in TextField
81
     └─ User presses Send button
82
        └─ PromptInputField._handleSendRequest()
83
           ├─ Validate text (not empty)
84
           └─ widget.onPrompt(text)
85
              └─ HomeScreen.onPrompt(text)
86
```
87
88
---
89
90
## 4. Prompt Processing Flow
91
92
### Flow
93
```
94
HomeScreen.onPrompt(promptText)
95
  ├─ Clear errors: setState()
96
  ├─ Determine prompt type (regular vs sub-prompt)
97
  ├─ Create/update PromptArgs
98
  ├─ Call HomeScreenManager.handlePrompt(...)
99
  ├─ Clear promptArgs: setState()
100
  └─ Handle errors: setState()
101
```
102
103
---
104
105
## 5. Home Screen Manager Processing
106
107
### Flow
108
```
109
HomeScreenManager.handlePrompt(...)
110
  ├─ Validate prompt text
111
  ├─ onLoadingStateChanged(true)
112
  ├─ ThreadManager.updateThreadMap(promptText, promptArgs)
113
  │  └─ Returns: Point newPoint
114
  ├─ Create AiModelProperties (model config)
115
  ├─ ContextManager.createPromptContext(newPoint)
116
  │  └─ Returns: List<RequestMessage> promptContextMessages
117
  ├─ Track loading state:
118
  │  ├─ Extract exchangeId from newPoint
119
  │  └─ updateLoadingExchanges(add exchangeId)
120
  ├─ ApiService.sendPromptToAi(pointId, promptContextMessages, aiModelProperties)
121
  │  └─ Returns: Point updatedNewPoint (with response)
122
  ├─ updateLoadingExchanges(remove exchangeId)
123
  ├─ Update threadMap[updatedNewPoint.id]
124
  ├─ onMapUpdated()
125
  ├─ populateTreeViewList(treeViewList, updateTreeViewList)
126
  ├─ onClearPromptInput()
127
  └─ onLoadingStateChanged(false)
128
```
129
130
---
131
132
## 6. Thread Map Update (Core Logic)
133
134
### Flow - Decision Branch
135
```
136
ThreadManager.updateThreadMap(promptText, promptArgs)
137
  ├─ PointManager.createNewPoint(promptArgs, promptText)
138
  │  └─ Returns: Point newPoint
139
140
  ├─ IF newPoint.id == newPoint.parentPointId:
141
  │  └─ ROOT POINT: Add to threadMap and return
142
143
  ├─ Get Parent Point:
144
  │  ├─ IF NOT in threadMap:
145
  │  │  ├─ PointManager.getParentPoint(fetchArgs, newPoint.id)
146
  │  │  └─ Cache in threadMap
147
  │  └─ ELSE: Retrieve from threadMap
148
149
  └─ DECISION BRANCH:
150
151
     ├─ BRANCH A: SHARDING FLOW (isShardChild=true, selectedText exists)
152
     │  ├─ ShardManager.addShardToParentPoint(newPoint.id, parentPoint, promptArgs)
153
     │  │  └─ Returns: Point updatedParentPoint (with new Shard)
154
     │  ├─ getParentShardId(updatedParentPoint, newPoint.id)
155
     │  ├─ newPoint.copyWith(parentShardId: parentShardId)
156
     │  ├─ Update threadMap with both points
157
     │  └─ onMapUpdated()
158
159
     └─ BRANCH B: REGULAR FLOW (continue conversation)
160
        ├─ PointManager.updateParentPoint(newPoint.id, parentPoint)
161
        │  └─ Returns: Point updatedParentPoint
162
        ├─ Update threadMap with both points
163
        └─ onMapUpdated()
164
```
165
166
---
167
168
## 7. Tree View Update
169
170
### Flow
171
```
172
HomeScreenManager.populateTreeViewList(treeViewList, updateTreeViewList)
173
  └─ TreeViewManager.updateTreeViewList(threadMap, treeViewList)
174
     └─ Returns: List<Point> newTreeViewList
175
        └─ updateTreeViewList(newTreeViewList)
176
           └─ HomeScreen.setState()
177
```
178
179
---
180
181
## 8. Tree Rendering Flow
182
183
### Flow
184
```
185
TreeSliverThread (StatefulWidget)
186
187
  ├─ _TreeSliverThreadState.initState()
188
  │  ├─ Create TreeSliverManager()
189
  │  └─ _updateTreeList()
190
191
  ├─ didUpdateWidget(oldWidget)
192
  │  └─ IF treeViewList or threadMap changed:
193
  │     └─ _updateTreeList()
194
195
  └─ _updateTreeList()
196
     └─ TreeSliverManager.buildFlatTreeList(threadMap, treeViewList)
197
        └─ Returns: List<TreeNodeModel> _flatTreeList
198
           └─ setState()
199
              └─ Triggers build()
200
```
201
202
### Build Method
203
```
204
TreeSliverThread.build()
205
  └─ SliverList.builder(itemCount: _flatTreeList.length)
206
     └─ For each TreeNodeModel:
207
        ├─ Check if isLoading (exchangeId in loadingExchanges)
208
        └─ Return TreeSliverItem(node, isLoading, onTap, prepareSubPromptInput)
209
```
210
211
### Node Tap Handler
212
```
213
_handleNodeTap(node)
214
  ├─ IF node.hasChildren:
215
  │  ├─ TreeSliverManager.toggleExpansion(node.id)
216
  │  └─ _updateTreeList()
217
  └─ widget.onNodeSelected(node.pointId)
218
```
219
220
---
221
222
## 9. Tree Structure Building
223
224
### Main Algorithm
225
```
226
TreeSliverManager.buildFlatTreeList(threadMap, treeViewList)
227
  ├─ _buildTreeStructure(treeViewList, threadMap)
228
  │  └─ Returns: List<TreeNodeModel> treeNodes
229
230
  └─ For each node in treeNodes:
231
     └─ _flattenNode(node, flatList) [Recursive]
232
        └─ Returns: List<TreeNodeModel> flatList
233
```
234
235
### Build Tree Structure (Three-Pass Algorithm)
236
```
237
TreeSliverManager._buildTreeStructure(treeViewList, threadMap)
238
239
  ├─ PASS 1: Create all nodes
240
  │  └─ For each Point in treeViewList:
241
  │     ├─ Check if Point has valid shards
242
  │     │
243
  │     ├─ IF has valid shards:
244
  │     │  └─ _createShardPointNode(point, exchange, nodeMap, threadMap)
245
  │     │     ├─ Creates main prompt node (no response)
246
  │     │     ├─ Creates shard segment nodes (response parts)
247
  │     │     ├─ Adds child points under shard segments
248
  │     │     └─ Creates "after" segment if text remains
249
  │     │
250
  │     └─ ELSE:
251
  │        └─ Create TreeNodeModel (regular, full response)
252
253
  ├─ PASS 2: Build hierarchy
254
  │  └─ For each Point:
255
  │     ├─ IF root (parentPointId == id):
256
  │     │  ├─ Add to rootNodes
257
  │     │  └─ Add shard segments as siblings (if any)
258
  │     │
259
  │     └─ ELSE (child):
260
  │        ├─ Find parent (could be shard segment)
261
  │        ├─ Add as child to parent
262
  │        ├─ Update level (parent.level + 1)
263
  │        └─ Add child's shard segments as siblings (if any)
264
265
  └─ PASS 3: Update flags
266
     └─ For each node:
267
        └─ IF node.children.isNotEmpty:
268
           └─ node.copyWith(hasChildren: true)
269
```
270
271
### Create Shard Point Node
272
```
273
TreeSliverManager._createShardPointNode(point, exchange, nodeMap, threadMap)
274
  ├─ Create main prompt node (responseContent: null)
275
  ├─ Filter valid shards (validate anchor positions)
276
  ├─ Sort shards by start position
277
278
  └─ For each shard:
279
     ├─ Extract response segment (currentPosition to shard.endPosition)
280
     ├─ Create TreeNodeModel for segment (level 0, sibling of prompt)
281
     ├─ Store in nodeMap (NOT child of main node)
282
283
     ├─ For each child in shard.shardChildren:
284
     │  ├─ Get childPoint from threadMap
285
     │  ├─ _buildChildNode(childPoint, shardSegment.id, shard.shardId, level=1, ...)
286
     │  ├─ Add child to shard segment's children
287
     │  └─ IF child has shards:
288
     │     └─ Add child's shard segments as siblings
289
290
     └─ Create "after" segment if text remains after last shard
291
```
292
293
### Build Child Node (Recursive)
294
```
295
TreeSliverManager._buildChildNode(childPoint, parentId, parentShardId, level, threadMap, nodeMap)
296
  ├─ Check if childPoint has valid shards
297
298
  ├─ IF has valid shards:
299
  │  └─ _createShardPointNodeRecursive(childPoint, exchange, level, parentId, parentShardId, ...)
300
  │     └─ [Same logic as _createShardPointNode but with baseLevel parameter]
301
302
  └─ ELSE:
303
     └─ Create TreeNodeModel (regular child node)
304
```
305
306
### Flatten Node (Recursive)
307
```
308
TreeSliverManager._flattenNode(node, flatList)
309
  ├─ flatList.add(node)
310
311
  └─ IF node.isExpanded AND node.children.isNotEmpty:
312
     └─ For each child:
313
        └─ _flattenNode(child, flatList) [Recursive]
314
```
315
316
**Visual Representation**:
317
```
318
Regular Point (no shards):
319
├─ Prompt: "What's Earth?"
320
└─ Response: "Third planet from the Sun"
321
322
Shard Point (with shards):
323
├─ Prompt: "What's Earth?"
324
├─ Response Segment 1: "Third planet from the "
325
├─ Response Segment 2: "Sun"
326
│  └─ Child Point (sub-prompt)
327
│     ├─ Prompt: "Sun - what's this?"
328
│     └─ Response: "The star..."
329
└─ Response Segment 3: " [remaining text]"
330
```
331
332
---
333
334
## 10. Tree Item Rendering
335
336
### Flow
337
```
338
TreeSliverThread.build()
339
  └─ SliverList.builder()
340
     └─ For each index:
341
        ├─ Get TreeNodeModel from _flatTreeList[index]
342
        ├─ Check isLoading (node.exchangeId in loadingExchanges)
343
        └─ Return TreeSliverItem(node, isLoading, onTap, prepareSubPromptInput)
344
```
345
346
---
347
348
## 11. Individual Tree Item Display
349
350
### Flow
351
```
352
TreeSliverItem.build()
353
  └─ Container(margin: left = node.level * _levelIndent)
354
     └─ Card
355
        └─ InkWell(onTap: onTap)
356
           └─ Column
357
              ├─ IF node.hasChildren:
358
              │  └─ _buildExpansionHeader()
359
360
              ├─ IF node.promptContent != null:
361
              │  └─ _buildPromptSection()
362
              │     └─ _buildContentSection(promptStyle)
363
364
              └─ Response rendering (varies by nodeType):
365
366
                 ├─ IF nodeType == exchange AND responseContent != null:
367
                 │  └─ isLoading ? _buildStatusSection() : _buildResponseSection()
368
369
                 ├─ IF nodeType == shard AND promptContent != null:
370
                 │  └─ isLoading ? _buildStatusSection() 
371
                 │     : (responseContent ? _buildResponseSection() : _buildStatusSection())
372
373
                 └─ IF nodeType == shardResponse:
374
                    └─ _buildResponseSection()
375
```
376
377
### Content Section (with Sub-Prompt Menu)
378
```
379
TreeSliverItem._buildContentSection(config)
380
  └─ _buildSelectableText(text, textStyle)
381
     └─ SelectableText(contextMenuBuilder: ...)
382
        └─ IF selectedText.isNotEmpty:
383
           └─ AdaptiveTextSelectionToolbar with "Sub-prompt" option
384
              └─ onPressed: _handleSubPrompt(selectedText, selection)
385
```
386
387
### Handle Sub-Prompt
388
```
389
TreeSliverItem._handleSubPrompt(selectedText, selection)
390
  ├─ Clipboard.setData(ClipboardData(text: selectedText))
391
  ├─ Create PromptArgs with shard information:
392
  │  ├─ currentPointId: node.pointId
393
  │  ├─ parentPointId: node.pointId
394
  │  ├─ parentShardId: node.shardId
395
  │  ├─ isShardChild: true
396
  │  ├─ selectedText, startPosition, endPosition
397
  ├─ prepareSubPromptInput(promptArgs)
398
  └─ ContextMenuController.removeAny()
399
```
400
401
---
402
403
## 12. Sub-Prompt Preparation
404
405
### Flow
406
```
407
HomeScreen.prepareSubPromptInput(promptArgs)
408
  ├─ Validate selectedText
409
  ├─ setState():
410
  │  ├─ Clear errorMessage
411
  │  └─ Update this.promptArgs (mark isShardChild = true)
412
  ├─ Show SnackBar: "Text copied to input..."
413
  └─ WidgetsBinding.instance.addPostFrameCallback():
414
     ├─ PromptInputField.setText(selectedText)
415
     └─ PromptInputField.focusInput()
416
```
417
418
---
419
420
## 13. Node Selection
421
422
### Flow
423
```
424
HomeScreen.onNodeSelected(currentPointId)
425
  ├─ setState():
426
  │  └─ Update promptArgs (mark isShardChild = false)
427
  └─ PromptInputField.focusInput()
428
```
429
430
---
431
432
## 14. Data Models
433
434
**Location**: `lib/models/`
435
436
### Point Model
437
```
438
Point
439
  ├─ id: String
440
  ├─ parentPointId: String
441
  ├─ pointChildren: List<String>
442
  ├─ parentShardId: String?
443
  ├─ shardsList: List<Shard>
444
  ├─ exchangesList: List<Exchange>
445
  └─ metadata: Metadata?
446
```
447
448
### Shard Model
449
```
450
Shard
451
  ├─ shardId: String
452
  ├─ shardChildren: List<String>
453
  └─ anchor: Anchor
454
      ├─ startPosition: int
455
      ├─ endPosition: int
456
      └─ selectedText: String
457
```
458
459
### Exchange Model
460
```
461
Exchange
462
  ├─ exchangeId: String
463
  ├─ exchangeTitle: String?
464
  ├─ prompt: Prompt
465
  │   ├─ model: String
466
  │   ├─ promptMessage: PromptMessage (role, content)
467
  │   └─ maxTokens: int
468
  └─ response: Response?
469
      ├─ id, model, created, etc.
470
      ├─ choices: List<Choice>
471
      │   └─ message: Message (role, content)
472
      └─ usage: Usage
473
```
474
475
### TreeNodeModel
476
```
477
TreeNodeModel (UI representation)
478
  ├─ id: String
479
  ├─ pointId: String
480
  ├─ level: int (indentation)
481
  ├─ isExpanded: bool
482
  ├─ hasChildren: bool
483
  ├─ promptContent: String?
484
  ├─ responseContent: String?
485
  ├─ nodeType: NodeType (exchange, shard, shardResponse)
486
  ├─ children: List<TreeNodeModel>
487
  └─ ... (other fields)
488
```
489
490
### PromptArgs
491
```
492
PromptArgs (context for prompt)
493
  ├─ currentPointId: String
494
  ├─ parentPointId: String?
495
  ├─ parentShardId: String?
496
  ├─ isShardChild: bool
497
  ├─ selectedText: String?
498
  ├─ startPosition, endPosition: int?
499
  └─ ... (other fields)
500
```
501
502
---
503
504
## 15. Complete Flow Summary
505
506
### Example: "What's Earth?" Conversation
507
508
#### Step 1: Initial Prompt
509
510
```
511
User types: "What's Earth?"
512
513
PromptInputField._handleSendRequest()
514
515
HomeScreen.onPrompt("What's Earth?")
516
517
HomeScreenManager.handlePrompt(...)
518
519
ThreadManager.updateThreadMap()
520
  ├─ PointManager.createNewPoint() → Point T001
521
  └─ (T001.id == T001.parentPointId) → Root point
522
523
ContextManager.createPromptContext(T001)
524
525
OpenAIService.sendPromptToAi(...) → Returns T001 with response
526
527
TreeViewManager.updateTreeViewList() → treeViewList = [T001]
528
529
TreeSliverManager.buildFlatTreeList()
530
  ├─ _buildTreeStructure() → Creates TreeNodeModel for T001
531
  └─ _flattenNode() → [T001]
532
533
TreeSliverThread.build() → TreeSliverItem renders:
534
  ├─ _buildPromptSection() → Blue "You" box
535
  └─ _buildResponseSection() → Green "AI Assistant" box
536
```
537
538
**UI Result**:
539
```
540
┌──────────────────────────────┐
541
│ 👤 You                       │
542
│ What's Earth?                │
543
└──────────────────────────────┘
544
┌──────────────────────────────┐
545
│ 🤖 AI Assistant              │
546
│ Third planet from the Sun    │
547
└──────────────────────────────┘
548
```
549
550
---
551
552
#### Step 2: First Sub-Prompt (Selected: "Sun")
553
554
```
555
User selects "Sun" → Right-click → "Sub-prompt"
556
557
TreeSliverItem._handleSubPrompt("Sun", selection)
558
  ├─ Clipboard.setData()
559
  └─ Creates PromptArgs (isShardChild=true, selectedText="Sun", positions)
560
561
HomeScreen.prepareSubPromptInput(promptArgs)
562
  ├─ setState() updates promptArgs
563
  └─ PromptInputField.setText("Sun")
564
565
User modifies: "Sun - what's this?" and sends
566
567
HomeScreen.onPrompt("Sun - what's this?")
568
569
HomeScreenManager.handlePrompt(...)
570
571
ThreadManager.updateThreadMap() [isShardChild=true]
572
  ├─ ShardManager.addShardToParentPoint(T001, promptArgs)
573
  │  └─ Creates Shard S01 in T001 (anchor: start=24, end=27)
574
  ├─ PointManager.createNewPoint() → Point T002 (parentShardId: S01)
575
  └─ Updates T001.shardsList[0].shardChildren = ["T002"]
576
577
OpenAIService.sendPromptToAi(T002, ...) → Returns T002 with response
578
579
TreeViewManager.updateTreeViewList() → treeViewList = [T001, T002]
580
581
TreeSliverManager.buildFlatTreeList()
582
  ├─ _buildTreeStructure()
583
  │  └─ Detects T001 has valid shards
584
  │     └─ _createShardPointNode(T001, ...)
585
  │        ├─ Creates main prompt node (T001)
586
  │        ├─ Creates shard segment (T001_shard_S01) with response text
587
  │        └─ Adds T002 as child of shard segment (level 1)
588
  └─ _flattenNode() → [T001_prompt, T001_shard_S01, T002]
589
590
UI renders nested structure:
591
  ├─ T001 prompt
592
  ├─ T001_shard_S01 (response segment)
593
  └─── T002 (indented, level 1)
594
```
595
596
**UI Result**:
597
```
598
┌──────────────────────────────┐
599
│ 👤 You                       │
600
│ What's Earth?                │
601
└──────────────────────────────┘
602
┌──────────────────────────────┐
603
│ ✂️ Shard Segment             │
604
│ Third planet from the Sun    │
605
│   ┌──────────────────────────┤
606
│   │ 👤 Shard                 │
607
│   │ Sun - what's this?       │
608
│   └──────────────────────────┤
609
│   ┌──────────────────────────┐
610
│   │ 🤖 AI Assistant          │
611
│   │ The star                 │
612
│   └──────────────────────────┘
613
└──────────────────────────────┘
614
```
615
616
---
617
618
#### Step 3: Second Sub-Prompt (Selected: "star")
619
620
```
621
User selects "star" → "star - what's this?"
622
623
Similar flow creates:
624
  ├─ Shard S02 in Point T002
625
  ├─ Point T003 (child of T002, shard S02)
626
  └─ TreeSliverManager recursively splits T002's response
627
628
UI renders with 2 levels of nesting:
629
  T001 → T001_shard_S01 → T002 → T002_shard_S02 → T003
630
```
631
632
---
633
634
#### Step 4: Third Sub-Prompt (Selected: "sphere")
635
636
```
637
User selects "sphere" → "sphere - what's this?"
638
639
Creates:
640
  ├─ Shard S03 in Point T003
641
  ├─ Point T004 (child of T003, shard S03)
642
  └─ TreeSliverManager recursively splits at 3 levels
643
644
Final nested structure (as seen in screenshot):
645
  T001
646
    └─ T001_shard_S01
647
       └─ T002
648
          └─ T002_shard_S02
649
             └─ T003
650
                └─ T003_shard_S03
651
                   └─ T004
652
```
653
654
**Final UI** (matching screenshot):
655
```
656
┌──────────────────────────────┐
657
│ 👤 You                       │
658
│ What's Earth?                │
659
└──────────────────────────────┘
660
┌──────────────────────────────┐
661
│ ✂️ Shard Segment             │
662
│ Third planet from the Sun    │
663
│   ┌──────────────────────────┤
664
│   │ 👤 Shard                 │
665
│   │ Sun - what's this?       │
666
│   └──────────────────────────┤
667
│   ┌──────────────────────────┐
668
│   │ ✂️ Shard Segment         │
669
│   │ The star                 │
670
│   │   ┌──────────────────────┤
671
│   │   │ 👤 Shard             │
672
│   │   │ star - what's this?  │
673
│   │   └──────────────────────┤
674
│   │   ┌──────────────────────┐
675
│   │   │ ✂️ Shard Segment     │
676
│   │   │ A luminous sphere    │
677
│   │   │   ┌──────────────────┤
678
│   │   │   │ 👤 Shard         │
679
│   │   │   │ sphere - what's? │
680
│   │   │   └──────────────────┤
681
│   │   │   ┌──────────────────┐
682
│   │   │   │ 🤖 AI Assistant  │
683
│   │   │   │ 3D geometric...  │
684
│   │   │   └──────────────────┘
685
│   │   └──────────────────────┘
686
│   │   ┌──────────────────────┐
687
│   │   │ ✂️ Response Segment  │
688
│   │   │ of plasma...         │
689
│   │   └──────────────────────┘
690
│   │   [... more segments ...]
691
│   └──────────────────────────┘
692
└──────────────────────────────┘
693
```
694
695
---
696
697
### Key Call Sequence for Complete Flow
698
699
```
700
User Action (type/select/send)
701
702
PromptInputField._handleSendRequest()
703
704
HomeScreen.onPrompt()
705
706
HomeScreenManager.handlePrompt()
707
  ├─ ThreadManager.updateThreadMap()
708
  │  ├─ PointManager.createNewPoint()
709
  │  │  └─ BackendService.createPoint()
710
  │  ├─ IF isShardChild:
711
  │  │  └─ ShardManager.addShardToParentPoint()
712
  │  │     └─ BackendService.updatePoint()
713
  │  └─ PointManager.updateParentPoint()
714
  │     └─ BackendService.updatePoint()
715
  ├─ ContextManager.createPromptContext()
716
  ├─ OpenAIService.sendPromptToAi()
717
  │  └─ BackendService.updatePoint()
718
  └─ HomeScreenManager.populateTreeViewList()
719
     └─ TreeViewManager.updateTreeViewList()
720
        └─ TreeSliverManager.buildFlatTreeList()
721
           ├─ TreeSliverManager._buildTreeStructure()
722
           │  └─ TreeSliverManager._createShardPointNode() [if has shards]
723
           │     └─ TreeSliverManager._buildChildNode() [recursive]
724
           └─ TreeSliverManager._flattenNode() [recursive]
725
726
HomeScreen.setState()
727
728
TreeSliverThread.didUpdateWidget()
729
730
TreeSliverThread._updateTreeList()
731
732
TreeSliverThread.setState()
733
734
TreeSliverThread.build()
735
  ├─ SliverList.builder()
736
  │  └─ For each TreeNodeModel:
737
  │     └─ TreeSliverItem.build()
738
  │        ├─ _buildPromptSection()
739
  │        ├─ _buildResponseSection()
740
  │        └─ _buildSelectableText()
741
  │           └─ (custom context menu with "Sub-prompt")
742
  └─ User interaction continues...
743
```
744
745
---
746
747
## Key Architectural Patterns
748
749
### 1. Manager Pattern
750
- **PointManager**: Point CRUD operations
751
- **ShardManager**: Shard creation/management
752
- **ThreadManager**: Conversation orchestration
753
- **ContextManager**: AI context building
754
- **TreeViewManager**: Tree data transformation
755
- **TreeSliverManager**: Tree rendering logic
756
- **HomeScreenManager**: Overall orchestration
757
758
### 2. State Management via Callbacks
759
- Parent (HomeScreen) manages state
760
- Children receive callbacks
761
- Callbacks trigger setState() in parent
762
- UI rebuilds reactively
763
764
### 3. Immutable Data Structures
765
- Never mutate, always copy
766
- `point.copyWith(field: newValue)`
767
- Predictable state changes
768
769
### 4. Tree Flattening
770
- Hierarchical → Flat list
771
- Based on expansion states
772
- Efficient rendering (SliverList.builder)
773
774
### 5. Error Boundaries
775
- Try-catch at every level
776
- Graceful degradation
777
- User feedback on errors
778
- App never crashes
779
780
### 6. Lazy Loading / Caching
781
- Fetch only when needed
782
- Cache in threadMap
783
- Reduce network calls
784
785
### 7. Separation of Data/Display
786
- Point (backend) → TreeNodeModel (display) → Widget (UI)
787
- Backend changes don't break UI
788
789
### 8. Composite Pattern
790
- TreeNodeModel contains children of same type
791
- Recursive algorithms naturally
792
793
### 9. Factory Pattern
794
- Specialized node creation methods
795
- `_createShardPointNode()`
796
- `_buildChildNode()`
797
798
### 10. Observer Pattern (via Callbacks)
799
- `onMapUpdated.call()`
800
- Notifies all listeners
801
- Triggers UI updates
802
803
### 11. Production Logging
804
- `developer.log()` instead of `print()`
805
- Structured, filterable logs
806
807
### 12. Context Preservation
808
- PromptArgs carries full context
809
- Easy to pass between methods
810
811
### 13. Defensive Programming
812
- Validate everything
813
- Check `mounted` before setState
814
- Null-safe access (`.firstOrNull`)
815
816
### 14. Key-based Widget Identity
817
- GlobalKey for programmatic control
818
- Preserve state across rebuilds
819
820
### 15. Three-Pass Tree Building
821
- Pass 1: Create nodes
822
- Pass 2: Build hierarchy
823
- Pass 3: Update flags
824
825
---
826
827
## Conclusion
828
829
### Core Features
830
1. Multi-level conversation threading
831
2. Sub-prompt creation from text
832
3. Response segmentation
833
4. Dynamic expand/collapse
834
5. Granular loading states
835
836
### Technical Excellence
837
1. Production-ready error handling
838
2. Immutable data structures
839
3. Manager pattern separation
840
4. Efficient rendering
841
5. Type-safe models
842
6. Comprehensive logging
843
844
### User Experience
845
1. Responsive UI
846
2. Clear visual hierarchy
847
3. Color-coded types
848
4. Contextual actions
849
5. Per-exchange loading
850
6. Error feedback
851
852
### Scalability
853
1. Lazy loading
854
2. Efficient rendering
855
3. Recursive algorithms
856
4. Modular architecture
857
5. Clean separation
858
859
---
860
861
**End of Document**