Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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