@@ -11,6 +11,7 @@ import 'package:flutter_genui_firebase_ai/flutter_genui_firebase_ai.dart';
11
11
12
12
import 'asset_images.dart' ;
13
13
import 'catalog.dart' ;
14
+ import 'tools/list_hotels_tool.dart' ;
14
15
import 'widgets/conversation.dart' ;
15
16
16
17
Future <void > loadImagesJson () async {
@@ -45,7 +46,8 @@ class TravelPlannerPage extends StatefulWidget {
45
46
State <TravelPlannerPage > createState () => _TravelPlannerPageState ();
46
47
}
47
48
48
- class _TravelPlannerPageState extends State <TravelPlannerPage > {
49
+ class _TravelPlannerPageState extends State <TravelPlannerPage >
50
+ with AutomaticKeepAliveClientMixin {
49
51
late final GenUiManager _genUiManager;
50
52
late final AiClient _aiClient;
51
53
late final StreamSubscription <UserMessage > _userMessageSubscription;
@@ -70,12 +72,11 @@ class _TravelPlannerPageState extends State<TravelPlannerPage> {
70
72
_userMessageSubscription = _genUiManager.onSubmit.listen (
71
73
_handleUserMessageFromUi,
72
74
);
75
+ final tools = _genUiManager.getTools ();
76
+ tools.add (ListHotelsTool (onListHotels: onListHotels));
73
77
_aiClient =
74
78
widget.aiClient ??
75
- FirebaseAiClient (
76
- tools: _genUiManager.getTools (),
77
- systemInstruction: prompt,
78
- );
79
+ FirebaseAiClient (tools: tools, systemInstruction: prompt);
79
80
_genUiManager.surfaceUpdates.listen ((update) {
80
81
setState (() {
81
82
switch (update) {
@@ -187,6 +188,7 @@ class _TravelPlannerPageState extends State<TravelPlannerPage> {
187
188
188
189
@override
189
190
Widget build (BuildContext context) {
191
+ super .build (context);
190
192
return SafeArea (
191
193
child: Center (
192
194
child: Column (
@@ -214,6 +216,9 @@ class _TravelPlannerPageState extends State<TravelPlannerPage> {
214
216
),
215
217
);
216
218
}
219
+
220
+ @override
221
+ bool get wantKeepAlive => true ;
217
222
}
218
223
219
224
class _ChatInput extends StatelessWidget {
@@ -330,6 +335,10 @@ to the user.
330
335
involves booking every accommodation, transport and activity in the itinerary
331
336
one step at a time.
332
337
338
+ When booking accommodation, you should use the `listHotels` tool to search
339
+ for hotels. You can then show the user the different options in a
340
+ `travelCarousel`.
341
+
333
342
Here, you should just focus on one item at a time, using an `inputGroup`
334
343
with chips to ask the user for preferences, and the `travelCarousel` to show
335
344
the user different options. When the user chooses an option, you can confirm
@@ -368,7 +377,7 @@ update existing content.
368
377
at the bottom of the conversation.
369
378
- Updating surfaces: You should update surfaces when you are running an
370
379
iterative search flow, e.g. the user is adjusting filter values and generating
371
- an itinerary or a booking accomodation etc. This is less confusing for the user
380
+ an itinerary or a booking accommodation etc. This is less confusing for the user
372
381
because it avoids confusing the conversation with many versions of the same
373
382
itinerary etc.
374
383
@@ -389,7 +398,7 @@ carousel. If there are only 2 or 3 obvious options, just think of some relevant
389
398
alternatives that the user might be interested in.
390
399
391
400
- Guiding the user: When the user has completes some action, e.g. they confirm
392
- they want to book some accomodation or activity, always show a trailhead
401
+ they want to book some accommodation or activity, always show a trailhead
393
402
suggesting what the user might want to do next (e.g. book the next detail in the
394
403
itinerary, repeat a search, research some related topic) so that they can click
395
404
rather than typing.
0 commit comments