Skip to content

Commit 2b5ae6d

Browse files
authored
Add example data and expose onsubmit in catalog view. (#299)
1 parent ee0fd7f commit 2b5ae6d

File tree

7 files changed

+130
-4
lines changed

7 files changed

+130
-4
lines changed

examples/travel_app/lib/main.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ void main() async {
2323
webProvider: ReCaptchaV3Provider('debug'),
2424
);
2525
await loadImagesJson();
26-
configureGenUiLogging(level: Level.ALL);
26+
final logger = configureGenUiLogging(level: Level.ALL);
27+
logger.onRecord.listen((record) {
28+
// ignore: avoid_print
29+
print(
30+
'${record.level.name}: ${record.time}: ${record.loggerName}: '
31+
'${record.message}',
32+
);
33+
});
2734
runApp(const TravelApp());
2835
}
2936

examples/travel_app/lib/src/catalog/travel_carousel.dart

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,89 @@ final travelCarousel = CatalogItem(
7070
dispatchEvent: dispatchEvent,
7171
);
7272
},
73+
exampleData: {
74+
'root': 'greece_inspiration_column',
75+
'widgets': [
76+
{
77+
'id': 'greece_inspiration_column',
78+
'widget': {
79+
'Column': {
80+
'children': ['inspiration_title', 'inspiration_carousel'],
81+
},
82+
},
83+
},
84+
{
85+
'id': 'inspiration_title',
86+
'widget': {
87+
'Text': {
88+
'text':
89+
"Let's plan your dream trip to Greece! What kind of experience"
90+
' are you looking for?',
91+
},
92+
},
93+
},
94+
{
95+
'widget': {
96+
'TravelCarousel': {
97+
'items': [
98+
{
99+
'title': 'Relaxing Beach Holiday',
100+
'imageChildId': 'santorini_beach_image',
101+
},
102+
{
103+
'imageChildId': 'akrotiri_fresco_image',
104+
'title': 'Cultural Exploration',
105+
},
106+
{
107+
'imageChildId': 'santorini_caldera_image',
108+
'title': 'Adventure & Outdoors',
109+
},
110+
{'title': 'Foodie Tour', 'imageChildId': 'greece_food_image'},
111+
],
112+
},
113+
},
114+
'id': 'inspiration_carousel',
115+
},
116+
{
117+
'id': 'santorini_beach_image',
118+
'widget': {
119+
'Image': {
120+
'fit': 'cover',
121+
'assetName': 'assets/travel_images/santorini_panorama.jpg',
122+
},
123+
},
124+
},
125+
{
126+
'id': 'akrotiri_fresco_image',
127+
'widget': {
128+
'Image': {
129+
'fit': 'cover',
130+
'assetName':
131+
'assets/travel_images/akrotiri_spring_fresco_santorini.jpg',
132+
},
133+
},
134+
},
135+
{
136+
'id': 'santorini_caldera_image',
137+
'widget': {
138+
'Image': {
139+
'assetName': 'assets/travel_images/santorini_from_space.jpg',
140+
'fit': 'cover',
141+
},
142+
},
143+
},
144+
{
145+
'widget': {
146+
'Image': {
147+
'fit': 'cover',
148+
'assetName':
149+
'assets/travel_images/saffron_gatherers_fresco_santorini.jpg',
150+
},
151+
},
152+
'id': 'greece_food_image',
153+
},
154+
],
155+
},
73156
);
74157

75158
extension type _TravelCarouselData.fromMap(Map<String, Object?> _json) {

packages/flutter_genui/USAGE.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,19 @@ If something is unclear or missing, please [create an issue](https://github.com/
153153

154154
## Troubleshooting
155155

156+
### Configure logging
157+
158+
To observe interaction between app and agent, enable logging:
159+
160+
```dart
161+
final logger = configureGenUiLogging(level: Level.ALL);
162+
logger.onRecord.listen((record) {
163+
print(
164+
'${record.loggerName}: ${record.message}',
165+
);
166+
});
167+
```
168+
156169
### Higher minimum macOS version is required
157170

158171
If you are getting the error similar to one below, re-clone your repo.

packages/flutter_genui/lib/flutter_genui_dev.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
export 'src/development_utilities/gallery.dart';
5+
export 'src/development_utilities/catalog_view.dart';

packages/flutter_genui/lib/src/development_utilities/gallery.dart renamed to packages/flutter_genui/lib/src/development_utilities/catalog_view.dart

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,25 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:async' show StreamSubscription;
6+
57
import 'package:flutter/material.dart';
68

79
import '../core/genui_manager.dart';
810
import '../core/genui_surface.dart';
911
import '../model/catalog.dart';
1012
import '../model/catalog_item.dart';
13+
import '../model/chat_message.dart';
1114

1215
/// A widget that displays a catalog of items using GenUI surfaces.
1316
///
1417
/// In order for a catalog item to be displayed, it must have example data
1518
/// defined.
1619
class CatalogView extends StatefulWidget {
17-
const CatalogView({required this.catalog});
20+
const CatalogView({this.onSubmit, required this.catalog});
1821

1922
final Catalog catalog;
23+
final ValueChanged<UserMessage>? onSubmit;
2024

2125
@override
2226
State<CatalogView> createState() => _CatalogViewState();
@@ -25,12 +29,18 @@ class CatalogView extends StatefulWidget {
2529
class _CatalogViewState extends State<CatalogView> {
2630
late final GenUiManager _genUi;
2731
final surfaceIds = <String>[];
32+
late final StreamSubscription<UserMessage>? _subscription;
2833

2934
@override
3035
void initState() {
3136
super.initState();
3237

3338
_genUi = GenUiManager(catalog: widget.catalog);
39+
if (widget.onSubmit != null) {
40+
_subscription = _genUi.onSubmit.listen(widget.onSubmit);
41+
} else {
42+
_subscription = null;
43+
}
3444

3545
final items = widget.catalog.items.where(
3646
(CatalogItem item) => item.exampleData != null,
@@ -44,6 +54,13 @@ class _CatalogViewState extends State<CatalogView> {
4454
}
4555
}
4656

57+
@override
58+
void dispose() {
59+
_subscription?.cancel();
60+
_genUi.dispose();
61+
super.dispose();
62+
}
63+
4764
@override
4865
Widget build(BuildContext context) {
4966
return ListView.builder(

packages/flutter_genui/lib/src/model/catalog_item.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,9 @@ class CatalogItem {
6363
final CatalogWidgetBuilder widgetBuilder;
6464

6565
/// Example data for this widget, for testing purposes.
66+
///
67+
/// To catch real data returned by the AI,
68+
/// [configure logging](https://github.com/flutter/genui/blob/main/packages/flutter_genui/USAGE.md#configure-logging)
69+
/// to Level.ALL and search for the string `"definition": {` in the logs.
6670
final JsonMap? exampleData;
6771
}

packages/flutter_genui/lib/src/primitives/logging.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ final genUiLogger = Logger('GenUI');
1111
///
1212
/// This function should be called by applications using the GenUI package to
1313
/// configure the desired log level and to listen for log messages.
14-
void configureGenUiLogging({
14+
Logger configureGenUiLogging({
1515
Level level = Level.INFO,
1616
void Function(Level, String)? logCallback,
1717
}) {
@@ -36,4 +36,6 @@ void configureGenUiLogging({
3636
}
3737
}
3838
});
39+
40+
return genUiLogger;
3941
}

0 commit comments

Comments
 (0)