ib_conversations 0.0.14-alpha copy "ib_conversations: ^0.0.14-alpha" to clipboard
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:

  1. A message containing ` ```widget:action_button {...} ```` is parsed.
  2. The WidgetBlockSyntax identifies the widget block.
  3. The WidgetElementBuilder looks 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 #

  1. User Sends MessageConversationWidget calls sendChatDataToBackend.
  2. Backend Responds → Renders response (may include embedded widgets).
  3. Widget Interaction → Triggers sendCommand callback.
  4. 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) and data (JSON parameters).

Rendering (WidgetElementBuilder):

  • Uses MarkdownElementBuilder to 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 #

  1. 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) { ... }
    }
    
  2. Register It:
    registry.registerWidget(
      label: "custom",
      builder: (ctx, params, cmd) => _CustomWidget(params, cmd),
      metadata: EmbeddedWidgetMetadata(...),
    );
    
  3. 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 sendChatDataToBackend and handleEmbeddedWidgetCommand.

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 #

  1. Create a Registration File:
    // health_widgets_registration.dart
    void registerHealthWidgets(EmbeddedWidgetRegistry registry) {
      registry.registerWidget(...); // e.g., medication_tracker
    }
    
  2. 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/dispose in 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? 🚀