ib_conversations 0.0.14-alpha
ib_conversations: ^0.0.14-alpha copied to clipboard
AI Conversations Flutter widget library
ib_conversations Library Documentation #
1. Architecture/Design #
1.1 How the Embedded Widget System Works #
The library allows embedding interactive widgets within chat messages using a custom Markdown syntax (` ```widget:widget_name ````).
Key Components:
- Widget Registry (
EmbeddedWidgetRegistry): Manages available widgets and their metadata. - Widget Builders: Functions that create widget instances with parameters.
- Markdown Integration: Custom parsers and builders to detect and render widget blocks.
Flow:
- A message containing ` ```widget:action_button {...} ```` is parsed.
- The
WidgetBlockSyntaxidentifies the widget block. - The
WidgetElementBuilderlooks up the widget in the registry and renders it.
1.2 The Registry Pattern Implementation #
The EmbeddedWidgetRegistry follows a centralized registration pattern:
Registration:
registry.registerWidget(
label: "action_button",
builder: (context, params, sendCommand) => ActionButton(params),
metadata: EmbeddedWidgetMetadata(...),
);
Usage:
final builder = registry.getBuilder("action_button");
if (builder != null) {
return builder(context, params, sendCommand);
}
Benefits:
- Decouples widget definitions from usage.
- Allows dynamic registration (e.g., plugins adding widgets).
1.3 Message Flow Between Components #
- User Sends Message →
ConversationWidgetcallssendChatDataToBackend. - Backend Responds → Renders response (may include embedded widgets).
- Widget Interaction → Triggers
sendCommandcallback. - Command Handling → Parent app processes the command (e.g., API call).
2. Implementation Details #
2.1 Custom Markdown Parsing & Rendering #
Syntax Detection (WidgetBlockSyntax):
- Looks for ` ```widget:name {...} ```` blocks.
- Extracts
label(widget name) anddata(JSON parameters).
Rendering (WidgetElementBuilder):
- Uses
MarkdownElementBuilderto convert parsed blocks into Flutter widgets.
Example:
Here's a button:
```widget:action_button
{
"label": "Click Me",
"commandType": "navigate",
"args": {"page": "home"}
}
---
### **2.2 Widget Command Handling**
- **Widgets receive a `SendCommandCallback`:**
```dart
typedef SendCommandCallback = void Function(String commandType, Map<String, dynamic> args);
- Example Usage:
ElevatedButton( onPressed: () => sendCommand("submit", {"data": "123"}), child: Text("Submit"), ); - Parent App Handles Commands:
void _handleCommand(String type, Map<String, dynamic> args) { if (type == "navigate") { Navigator.pushNamed(context, args["page"]); } }
2.3 State Management Approach #
- Provider: Used for
EmbeddedWidgetRegistry(global access). - Local State: Widgets manage their own state (e.g., form inputs).
- Parent-Managed State: Commands bubble up to the host app.
3. Usage #
3.1 Adding New Embedded Widgets #
- Define the Widget:
class _CustomWidget extends StatelessWidget { final Map<String, dynamic> params; final SendCommandCallback sendCommand; const _CustomWidget(this.params, this.sendCommand); @override Widget build(BuildContext context) { ... } } - Register It:
registry.registerWidget( label: "custom", builder: (ctx, params, cmd) => _CustomWidget(params, cmd), metadata: EmbeddedWidgetMetadata(...), ); - Use in Markdown:
```widget:custom {"text": "Hello"}
3.2 Customizing the Chat Interface #
- Styling: Pass theme parameters to
ConversationWidget:ConversationWidget( primaryColor: Colors.blue, bodyMediumStyle: TextStyle(fontSize: 16), ... ); - Behavior: Override
sendChatDataToBackendandhandleEmbeddedWidgetCommand.
3.3 Integrating with Different Backends #
Example: REST API
Future<String?> _sendChatDataToBackend({
required String message,
List<PlatformFile>? files,
}) async {
final response = await http.post(
Uri.parse("https://api.example.com/chat"),
body: jsonEncode({"text": message}),
);
return response.body;
}
Example: Firebase
final doc = await FirebaseFirestore.instance.collection("chats").add({
"text": message,
"user": userId,
});
4. Troubleshooting #
4.1 Debugging Widget Rendering Issues #
- Check Registry:
print(registry.getAllMetadata()); // Verify widget is registered - Inspect JSON: Ensure parameters are valid.
- Log Parsing:
print('Parsed widget: label=$label, data=$data');
4.2 Handling Errors in Chat Flow #
- Backend Errors: Return user-friendly messages:
if (response.statusCode != 200) { return "Error: Failed to send message"; } - Widget Errors: Wrap in
try/catch:try { return builder(context, params, sendCommand); } catch (e) { return Text("Error: Invalid widget"); }
5. Extensibility #
5.1 Adding New Widget Categories #
- Create a Registration File:
// health_widgets_registration.dart void registerHealthWidgets(EmbeddedWidgetRegistry registry) { registry.registerWidget(...); // e.g., medication_tracker } - Add to Global Registration:
void registerAllWidgets() { registerHealthWidgets(registry); registerEduWidgets(registry); }
5.2 Customizing Widget Behavior #
- Dynamic Parameters:
```widget:data_display {"style": "compact", "color": "blue"} - Lifecycle Hooks: Add
initState/disposein stateful widgets.
Summary #
This library enables rich, interactive chat UIs with:
✅ Embedded widgets in Markdown
✅ Centralized widget registry
✅ Custom command handling
✅ Easy backend integration
Would you like a deeper dive into any section? 🚀