Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/custom_backend/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ class _IntegrationTesterState extends State<_IntegrationTester> {
if (surfaceId == null) {
return const Text('_surfaceId == null');
}
final SurfaceController controller = _genUi.getSurfaceController(surfaceId);
return GenUiSurface(
surfaceId: surfaceId,
host: _genUi,
controller: controller,
defaultBuilder: (_) => const Text('Fallback to defaultBuilder'),
);
}
Expand Down
14 changes: 9 additions & 5 deletions examples/simple_chat/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ class _ChatScreenState extends State<ChatScreen> {
);
}

void _handleSurfaceAdded(SurfaceAdded surface) {
void _handleSurfaceAdded(SurfaceController controller) {
if (!mounted) return;
setState(() {
_messages.add(MessageController(surfaceId: surface.surfaceId));
_messages.add(MessageController(surfaceId: controller.surfaceId));
});
_scrollToBottom();
}
Expand Down Expand Up @@ -150,9 +150,13 @@ class _ChatScreenState extends State<ChatScreen> {
itemCount: _messages.length,
itemBuilder: (context, index) {
final MessageController message = _messages[index];
return ListTile(
title: MessageView(message, _genUiConversation.host),
);
final SurfaceController? controller =
message.surfaceId == null
? null
: _genUiConversation.getSurfaceController(
message.surfaceId!,
);
return ListTile(title: MessageView(message, controller));
},
),
),
Expand Down
16 changes: 10 additions & 6 deletions examples/simple_chat/lib/message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,21 @@ class MessageController {
}

class MessageView extends StatelessWidget {
const MessageView(this.controller, this.host, {super.key});
const MessageView(
this.messageController,
this.surfaceController, {
super.key,
});

final MessageController controller;
final GenUiHost host;
final MessageController messageController;
final SurfaceController? surfaceController;

@override
Widget build(BuildContext context) {
final String? surfaceId = controller.surfaceId;
final SurfaceController? controller = surfaceController;

if (surfaceId == null) return Text(controller.text ?? '');
if (controller == null) return Text(messageController.text ?? '');

return GenUiSurface(host: host, surfaceId: surfaceId);
return GenUiSurface(controller: controller);
}
}
9 changes: 4 additions & 5 deletions examples/travel_app/lib/src/widgets/conversation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,12 @@ class Conversation extends StatelessWidget {
alignment: MainAxisAlignment.start,
);
case AiUiMessage():
final SurfaceController controller = manager.getSurfaceController(
message.surfaceId,
);
return Padding(
padding: const EdgeInsets.all(16.0),
child: GenUiSurface(
key: message.uiKey,
host: manager,
surfaceId: message.surfaceId,
),
child: GenUiSurface(key: message.uiKey, controller: controller),
);
case InternalMessage():
return InternalMessageWidget(content: message.text);
Expand Down
20 changes: 0 additions & 20 deletions examples/travel_app/test/widgets/conversation_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,25 +103,5 @@ void main() {
expect(find.byType(GenUiSurface), findsOneWidget);
expect(find.text('UI Content'), findsOneWidget);
});

testWidgets('uses custom userPromptBuilder', (WidgetTester tester) async {
final messages = [
UserMessage(const [TextPart('Hello')]),
];
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Conversation(
messages: messages,
manager: manager,
userPromptBuilder: (context, message) =>
const Text('Custom User Prompt'),
),
),
),
);
expect(find.text('Custom User Prompt'), findsOneWidget);
expect(find.text('Hello'), findsNothing);
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,15 @@ class OrderConfirmationScreen extends ConsumerWidget {
.watch(aiProvider)
.when(
data: (aiState) {
final SurfaceController controller = aiState.genUiManager
.getSurfaceController('confirmation');
return ValueListenableBuilder<UiDefinition?>(
valueListenable: aiState.genUiManager.getSurfaceNotifier(
'confirmation',
),
valueListenable: controller.uiDefinitionNotifier,
builder: (context, definition, child) {
if (definition == null) {
return const Center(child: CircularProgressIndicator());
}
return GenUiSurface(
host: aiState.genUiManager,
surfaceId: 'confirmation',
);
return GenUiSurface(controller: controller);
},
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,17 @@ class _PresentationScreenState extends ConsumerState<PresentationScreen> {
.watch(aiProvider)
.when(
data: (aiState) {
final SurfaceController controller = aiState.genUiManager
.getSurfaceController('options');
return ValueListenableBuilder<UiDefinition?>(
valueListenable: aiState.genUiManager.getSurfaceNotifier(
'options',
),
valueListenable: controller.uiDefinitionNotifier,
builder: (context, definition, child) {
if (definition == null) {
return const Center(child: CircularProgressIndicator());
}
return SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
child: GenUiSurface(
host: aiState.genUiManager,
surfaceId: 'options',
),
child: GenUiSurface(controller: controller),
);
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,17 @@ class _QuestionnaireScreenState extends ConsumerState<QuestionnaireScreen> {
.watch(aiProvider)
.when(
data: (aiState) {
final SurfaceController controller = aiState.genUiManager
.getSurfaceController('questionnaire');
return ValueListenableBuilder<UiDefinition?>(
valueListenable: aiState.genUiManager.getSurfaceNotifier(
'questionnaire',
),
valueListenable: controller.uiDefinitionNotifier,
builder: (context, definition, child) {
if (definition == null) {
return const Center(child: CircularProgressIndicator());
}
return SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
child: GenUiSurface(
host: aiState.genUiManager,
surfaceId: 'questionnaire',
),
child: GenUiSurface(controller: controller),
);
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,15 @@ class ShoppingCartScreen extends ConsumerWidget {
.watch(aiProvider)
.when(
data: (aiState) {
final SurfaceController controller = aiState.genUiManager
.getSurfaceController('cart');
return ValueListenableBuilder<UiDefinition?>(
valueListenable: aiState.genUiManager.getSurfaceNotifier(
'cart',
),
valueListenable: controller.uiDefinitionNotifier,
builder: (context, definition, child) {
if (definition == null) {
return const Center(child: CircularProgressIndicator());
}
return GenUiSurface(
host: aiState.genUiManager,
surfaceId: 'cart',
);
return GenUiSurface(controller: controller);
},
);
},
Expand Down
21 changes: 11 additions & 10 deletions packages/genui/.guides/docs/connect_to_agent_provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,17 @@ To receive and display generated UI:
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _surfaceIds.length,
itemBuilder: (context, index) {
// For each surface, create a GenUiSurface to display it.
final id = _surfaceIds[index];
return GenUiSurface(host: _genUiConversation.host, surfaceId: id);
},
),
),
Expanded(
child: ListView.builder(
itemCount: _surfaceIds.length,
itemBuilder: (context, index) {
// For each surface, create a GenUiSurface to display it.
final id = _surfaceIds[index];
final controller = _genUiConversation.getSurfaceController(id);
return GenUiSurface(controller: controller);
},
),
),
SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
Expand Down
10 changes: 5 additions & 5 deletions packages/genui/.guides/examples/riddles.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ class _MyHomePageState extends State<MyHomePage> {
conversation = GenUiConversation(
contentGenerator: contentGenerator,
genUiManager: genUiManager,
onSurfaceAdded: (update) {
onSurfaceAdded: (controller) {
setState(() {
messages.add(
AiUiMessage(
definition: update.definition,
surfaceId: update.surfaceId,
definition: controller.uiDefinitionNotifier.value!,
surfaceId: controller.surfaceId,
),
);
});
Expand Down Expand Up @@ -123,8 +123,8 @@ class _MyHomePageState extends State<MyHomePage> {
return switch (message) {
AiUiMessage() => GenUiSurface(
key: message.uiKey,
host: conversation.host,
surfaceId: message.surfaceId,
controller:
conversation.getSurfaceController(message.surfaceId),
),
AiTextMessage() => ChatMessageWidget(
text: message.text,
Expand Down
3 changes: 2 additions & 1 deletion packages/genui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ To receive and display generated UI:
itemBuilder: (context, index) {
// For each surface, create a GenUiSurface to display it.
final id = _surfaceIds[index];
return GenUiSurface(host: _genUiConversation.host, surfaceId: id);
final controller = _genUiConversation.getSurfaceController(id);
return GenUiSurface(controller: controller);
},
),
),
Expand Down
1 change: 1 addition & 0 deletions packages/genui/lib/genui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export 'src/core/genui_configuration.dart';
export 'src/core/genui_manager.dart';
export 'src/core/genui_surface.dart';
export 'src/core/prompt_fragments.dart';
export 'src/core/surface_controller.dart';
export 'src/core/ui_tools.dart';
export 'src/core/widget_utilities.dart';
export 'src/core/widgets/chat_primitives.dart';
Expand Down
Loading
Loading