Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
b49f458
-
polina-c Dec 24, 2025
62e769d
-
polina-c Dec 24, 2025
5b70ebc
Update mesage.dart
polina-c Dec 24, 2025
47f4ef5
Update mesage.dart
polina-c Dec 24, 2025
ed024ad
-
polina-c Dec 24, 2025
0f37256
Update genai_primitives.dart
polina-c Dec 24, 2025
918e4d9
Update genai_primitives_test.dart
polina-c Dec 24, 2025
daaa464
-
polina-c Dec 24, 2025
0452bea
-
polina-c Dec 24, 2025
87cc5dd
-
polina-c Dec 24, 2025
724ba2b
-
polina-c Dec 24, 2025
2ea87b5
-
polina-c Dec 24, 2025
5887cc4
-
polina-c Dec 24, 2025
f6af083
-
polina-c Dec 24, 2025
f259308
Update genai_primitives_test.dart
polina-c Dec 24, 2025
5110939
-
polina-c Dec 24, 2025
31e666a
Update message_parts.dart
polina-c Dec 24, 2025
6a245e8
-
polina-c Dec 26, 2025
52eb3a7
Update message_parts.dart
polina-c Dec 26, 2025
af0d06b
ci: add workflow_dispatch to enable manual CI triggers (#633)
andrewkolos Jan 5, 2026
4ebab33
Add A2UI support section to README (#648)
jacobsimionato Jan 5, 2026
0d4e92d
Update dartantic_ai dependency (#649)
gspencergoog Jan 5, 2026
910f4c5
Post publish commit to add sections to CHANGELOGs (#650)
gspencergoog Jan 5, 2026
4bf48a4
[docs] Suggest using `flutter pub add` for adding dependencies (#645)
parlough Jan 6, 2026
9f14e62
Improve error handling for catalog example loading (#653)
nan-yu Jan 6, 2026
c29fca4
-
polina-c Jan 9, 2026
56e12a8
Update message.dart
polina-c Jan 9, 2026
36593a0
---
polina-c Jan 9, 2026
167109f
--
polina-c Jan 9, 2026
dee7e6b
-
polina-c Jan 9, 2026
1eb2b23
-
polina-c Jan 9, 2026
b3c3014
Create custom_part_test.dart
polina-c Jan 9, 2026
aebee60
Update custom_part_test.dart
polina-c Jan 9, 2026
62a421d
-
polina-c Jan 9, 2026
29381ee
[examples] Verdure client cleanup and dependency updates (#646)
parlough Jan 8, 2026
1715110
Document how to get permissions to publish. (#657)
polina-c Jan 12, 2026
f16ca7d
- (#658)
polina-c Jan 13, 2026
1742057
-
polina-c Jan 15, 2026
006181f
-
polina-c Jan 15, 2026
f6814ee
Update genai_primitives_test.dart
polina-c Jan 15, 2026
19e9ad3
-
polina-c Jan 15, 2026
85825a6
-
polina-c Jan 15, 2026
41b1d1c
-
polina-c Jan 15, 2026
bc12115
-
polina-c Jan 15, 2026
551b51c
-
polina-c Jan 15, 2026
57b30c6
-
polina-c Jan 15, 2026
d6f56a0
-
polina-c Jan 15, 2026
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
1 change: 1 addition & 0 deletions .github/workflows/flutter_packages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
name: Flutter GenUI CI

on:
workflow_dispatch:
push:
branches:
- main
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ graph TD
genui_google_generative_ai --> genui
```

## A2UI Support

The Flutter Gen UI SDK uses the [A2UI protocol](https://a2ui.org) to represent UI content internally. The [genui_a2ui](packages/genui_a2ui/) package allows it to act as a renderer for UIs generated by an A2UI backend agent, similar to the [other A2UI renderers](https://github.com/google/A2UI/tree/main/renderers) which are maintained within the A2UI repository.

The Flutter Gen UI SDK currently supports A2UI v0.8.

## Getting started

See the [genui getting started guide](packages/genui/README.md#getting-started-with-genui).
Expand Down
2 changes: 1 addition & 1 deletion examples/verdure/client/lib/features/ai/ai_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class AiClientState {
required this.surfaceUpdateController,
});

/// The A2uiMessageProcessor.
/// The A2UI message processor.
final A2uiMessageProcessor a2uiMessageProcessor;

/// The content generator.
Expand Down
21 changes: 10 additions & 11 deletions examples/verdure/client/lib/features/ai/ai_provider.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class OrderConfirmationScreen extends ConsumerWidget {
error: (error, stackTrace) => Center(child: Text('Error: $error')),
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16),
child: ElevatedButton(
onPressed: () => context.go('/'),
child: const Text('Back to Start'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ class _QuestionnaireScreenState extends ConsumerState<QuestionnaireScreen> {
@override
Widget build(BuildContext context) {
ref.listen<AsyncValue<AiClientState>>(aiProvider, (previous, next) {
if (next is AsyncData && !_initialRequestSent) {
if (_initialRequestSent) return;
if (next case AsyncData(value: final aiState)) {
setState(() {
_initialRequestSent = true;
});
final AiClientState? aiState = next.value;
aiState?.conversation.sendRequest(
aiState.conversation.sendRequest(
UserMessage.text('USER_SUBMITTED_DETAILS'),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class UploadPhotoScreen extends ConsumerWidget {
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expand All @@ -52,7 +52,9 @@ class UploadPhotoScreen extends ConsumerWidget {
),
const SizedBox(height: 16),
Text(
'''Upload a photo of your front or back yard, and our designers will use it to create a custom vision. Get ready to see the potential.''',
'Upload a photo of your front or back yard, '
'and our designers will use it to create a custom vision. '
'Get ready to see the potential.',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onSurface,
Expand Down Expand Up @@ -146,34 +148,34 @@ class InfoCard extends StatelessWidget {
child: InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
spacing: 16,
children: [
CircleAvatar(
maxRadius: 25,
child: Icon(icon, size: 25, color: const Color(0xff15a34a)),
),
if (title != null || subtitle != null) const SizedBox(width: 16),
if (title != null || subtitle != null)
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4,
children: [
if (title != null)
if (title case final title?)
Text(
title!,
title,
style: Theme.of(context).textTheme.titleMedium!
.copyWith(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.onSurface,
),
),
if (subtitle != null) const SizedBox(height: 4),
if (subtitle != null)
if (subtitle case final subtitle?)
Text(
subtitle!,
subtitle,
style: Theme.of(context).textTheme.bodyMedium!
.copyWith(
color: Theme.of(context).colorScheme.onSurface,
Expand Down
14 changes: 7 additions & 7 deletions examples/verdure/client/lib/features/screens/welcome_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ class WelcomeScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(top: 64.0),
padding: const EdgeInsets.only(top: 64),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 8,
children: [
const Icon(Icons.eco, color: Colors.white, size: 32),
const SizedBox(width: 8),
Text(
'Verdure',
style: Theme.of(context).textTheme.headlineSmall
Expand All @@ -55,8 +55,9 @@ class WelcomeScreen extends StatelessWidget {
),
),
const Padding(
padding: EdgeInsets.all(16.0),
padding: EdgeInsets.all(16),
child: Column(
spacing: 16,
children: [
Text(
'Envision Your Dream Landscape',
Expand All @@ -68,9 +69,9 @@ class WelcomeScreen extends StatelessWidget {
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 16),
Text(
'''Bring your perfect outdoor space to life with our suite of AI design agents.''',
'Bring your perfect outdoor space to life with '
'our suite of AI design agents.',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'SpaceGrotesk',
Expand All @@ -89,6 +90,7 @@ class WelcomeScreen extends StatelessWidget {
Container(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
child: Column(
spacing: 16,
children: [
ElevatedButton(
onPressed: () => context.push('/upload_photo'),
Expand All @@ -99,12 +101,10 @@ class WelcomeScreen extends StatelessWidget {
),
child: const Text('Start New Project'),
),
const SizedBox(height: 16),
TextButton(
onPressed: () {},
child: const Text('Explore Ideas'),
),
const SizedBox(height: 16),
TextButton(
onPressed: () {},
child: const Text('I\'m a returning user'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class LoadingState {
} else if (_isProcessingValue && !isProcessing.value) {
// Went from true to false, reset messages after a short delay
// to allow the fade-out animation to complete.
Future.delayed(const Duration(milliseconds: 500), clearMessages);
Future<void>.delayed(const Duration(milliseconds: 500), clearMessages);
}
_isProcessingValue = isProcessing.value;
});
Expand Down
10 changes: 5 additions & 5 deletions examples/verdure/client/lib/features/widgets/app_navigator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ class AppNavigator extends ConsumerStatefulWidget {
}

class _AppNavigatorState extends ConsumerState<AppNavigator> {
StreamSubscription? _subscription;
StreamSubscription<void>? _subscription;

@override
void initState() {
super.initState();
// It's safe to use ref.read here because we are not rebuilding the widget
// when the provider changes, but instead subscribing to a stream.
final AsyncValue<AiClientState> aiState = ref.read(aiProvider);
if (aiState is AsyncData) {
_subscription = aiState.value!.surfaceUpdateController.stream.listen(
if (aiState case AsyncData(:final value)) {
_subscription = value.surfaceUpdateController.stream.listen(
_onSurfaceUpdate,
);
}
Expand Down Expand Up @@ -62,9 +62,9 @@ class _AppNavigatorState extends ConsumerState<AppNavigator> {
@override
Widget build(BuildContext context) {
ref.listen<AsyncValue<AiClientState?>>(aiProvider, (previous, next) {
if (next is AsyncData) {
if (next case AsyncData(:final value?)) {
_subscription?.cancel();
_subscription = next.value!.surfaceUpdateController.stream.listen(
_subscription = value.surfaceUpdateController.stream.listen(
_onSurfaceUpdate,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,27 +111,27 @@ class _LoadingMessagesState extends State<_LoadingMessages> {
color: Colors.transparent,
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Container(
height: 80.0,
height: 80,
padding: const EdgeInsets.symmetric(horizontal: 24),
decoration: BoxDecoration(
color: colorScheme.primary,
borderRadius: BorderRadius.circular(8.0),
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
spacing: 16,
children: [
const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2.0,
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
),
const SizedBox(width: 16),
Expanded(
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 500),
Expand Down
14 changes: 8 additions & 6 deletions examples/verdure/client/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
# found in the LICENSE file.

name: verdure
description: "A new Flutter project."
publish_to: "none"
description: >-
A sample of a Flutter client interacting with a Python-based A2A
(Agent-to-Agent) server for landscape design.
publish_to: none
version: 0.1.0

environment:
Expand All @@ -16,23 +18,23 @@ dependencies:
device_info_plus: ^12.2.0
flutter:
sdk: flutter
flutter_riverpod: ^3.0.3
flutter_riverpod: ^3.1.0
flutter_svg: ^2.2.2
genui: ^0.6.0
genui_a2ui: ^0.6.0
go_router: ^17.0.0
image_picker: ^1.2.0
logging: ^1.3.0
mime: ^2.0.0
riverpod_annotation: ^3.0.3
riverpod_annotation: ^4.0.0

dev_dependencies:
build_runner: ^2.7.1
build_runner: ^2.10.3
dart_flutter_team_lints: ^3.5.2
flutter_lints: ^6.0.0
flutter_test:
sdk: flutter
riverpod_generator: ^3.0.3
riverpod_generator: ^4.0.0

flutter:
uses-material-design: true
Expand Down
Loading
Loading