Skip to content
Merged
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ This repository is a collection of packages and applications for the Flutter Gen
## TODO before publishing

1. Clean up Google internal information.
2. Make colors and sizes consistent and organized in catalog.

## Packages

Expand Down
8 changes: 7 additions & 1 deletion doc/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@

## Getting Started

TODO: add 3P steps
1. Follow [the steps](https://firebase.google.com/docs/flutter/setup)
to configure Firebase for your project.

NOTE: see how secure it is to publish the generated files
[here](https://firebase.google.com/docs/projects/learn-more#config-files-objects).

2.
21 changes: 2 additions & 19 deletions examples/travel_app/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
# Example
# Travel App

This is prototype for agentic app.

## Diagrams

To regenerate diagrams:

```shell
dart pub global activate layerlens
layerlens
```

## TODO

TODO before productizing:

1. Make colors and sizes configurable.

## Next
TODO: describe
9 changes: 6 additions & 3 deletions examples/travel_app/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
// import 'package:firebase_core/firebase_core.dart';
// import 'firebase_options.dart';

import 'app.dart';
import 'firebase_options.dart';

void main() {
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const MyApp());
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: avoid_dynamic_calls

import 'package:firebase_ai/firebase_ai.dart';
import 'package:flutter/material.dart';

Expand Down Expand Up @@ -62,7 +64,9 @@ class _RadioGroupState extends State<_RadioGroup> {
return RadioListTile<String>(
title: Text(label),
value: label,
// ignore: deprecated_member_use
groupValue: _groupValue,
// ignore: deprecated_member_use
onChanged: changedCallback,
);
}).toList(),
Expand Down
2 changes: 2 additions & 0 deletions pkgs/flutter_genui/lib/src/catalog/core_widgets/text.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: avoid_dynamic_calls

import 'package:firebase_ai/firebase_ai.dart';
import 'package:flutter/material.dart';
import '../../model/catalog_item.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: avoid_dynamic_calls

import 'package:firebase_ai/firebase_ai.dart';
import 'package:flutter/material.dart';

Expand Down
14 changes: 7 additions & 7 deletions pkgs/flutter_genui/lib/src/core/conversation_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ import 'dart:async';
import 'package:collection/collection.dart';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:flutter/material.dart';
import 'package:flutter_genui/flutter_genui.dart';
import '../../flutter_genui.dart';

import '../model/catalog.dart';
import '../model/chat_message.dart';
import 'conversation_widget.dart';
import 'event_debouncer.dart';
import '../model/ui_models.dart';

class ConversationManager {
ConversationManager(
Expand All @@ -33,7 +30,8 @@ class ConversationManager {

int _outstandingRequests = 0;

// Stream of updates to the ui data which are used to build the Conversation Widget every time the conversation is updated.
// Stream of updates to the ui data which are used to build the
// Conversation Widget every time the conversation is updated.
final StreamController<List<ChatMessage>> _uiDataStreamController =
StreamController<List<ChatMessage>>.broadcast();

Expand All @@ -49,7 +47,8 @@ class ConversationManager {
_eventDebouncer.dispose();
}

/// Sends a prompt on behalf of the end user. This should update the UI and also trigger an LLM inference via the llmConnection.
/// Sends a prompt on behalf of the end user. This should update the UI and
/// also trigger an LLM inference via the llmConnection.
void sendUserPrompt(String prompt) {
if (prompt.isEmpty) {
return;
Expand Down Expand Up @@ -205,7 +204,8 @@ class ConversationManager {
'surfaceId': Schema.string(
description:
'The ID of the surface to perform the action on. For the '
'`add` action, this will be a new surface ID. For `update` and '
'`add` action, this will be a new surface ID. '
'For `update` and '
'`delete`, this will be an existing surface ID.',
),
'definition': Schema.object(
Expand Down
2 changes: 1 addition & 1 deletion pkgs/flutter_genui/lib/src/core/conversation_widget.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';

import '../model/catalog.dart';
import '../model/chat_message.dart';
import '../model/dynamic_ui.dart';
import '../model/ui_models.dart';
import '../model/chat_message.dart';

class ConversationWidget extends StatelessWidget {
const ConversationWidget({
Expand Down
2 changes: 1 addition & 1 deletion pkgs/flutter_genui/lib/src/core/core_catalog.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import '../model/catalog.dart';
import '../catalog/core_widgets/checkbox_group.dart';
import '../catalog/core_widgets/column.dart';
import '../catalog/core_widgets/elevated_button.dart';
import '../catalog/core_widgets/radio_group.dart';
import '../catalog/core_widgets/text.dart';
import '../catalog/core_widgets/text_field.dart';
import '../model/catalog.dart';

final coreCatalog = Catalog([
elevatedButtonCatalogItem,
Expand Down
7 changes: 5 additions & 2 deletions pkgs/flutter_genui/lib/src/model/catalog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,15 @@ class Catalog {

return Schema.object(
description:
'Represents a *single* widget in a UI widget tree. This widget could be one of many supported types.',
'Represents a *single* widget in a UI widget tree. '
'This widget could be one of many supported types.',
properties: {
'id': Schema.string(),
'widget': Schema.object(
description:
'The properties of the specific widget that this represents. This is a oneof - only *one* field should be set on this object!',
'The properties of the specific widget '
'that this represents. This is a oneof - only *one* '
'field should be set on this object!',
properties: schemaProperties,
optionalProperties: optionalSchemaProperties,
),
Expand Down
20 changes: 11 additions & 9 deletions pkgs/flutter_genui/lib/src/model/catalog_item.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import 'package:flutter/material.dart';
import 'package:firebase_ai/firebase_ai.dart';
import 'package:flutter/material.dart';

typedef CatalogWidgetBuilder = Widget Function(
dynamic
data, // The actual deserialized JSON data for this widget. The format of this data will exactly match dataSchema below.
String id, // The ID of this widget.
Widget Function(String id)
typedef CatalogWidgetBuilder =
Widget Function(
// The actual deserialized JSON data for this widget. The format of this
// data will exactly match dataSchema below.
dynamic data,
String id, // The ID of this widget.
Widget Function(String id)
buildChild, // A function used to build a child based on the given ID.
void Function(String widgetId, String eventType, Object? value)
void Function(String widgetId, String eventType, Object? value)
dispatchEvent, // A function used to dispatch an event.
BuildContext context, // The build context.
);
BuildContext context, // The build context.
);

/// Defines a UI layout type, its schema, and how to build its widget.
class CatalogItem {
Expand Down
3 changes: 2 additions & 1 deletion pkgs/flutter_genui/lib/src/model/dynamic_ui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class _DynamicUiState extends State<DynamicUi> {
}

/// The main recursive build function.
/// It reads a widget definition and its current state from [_widgetStates]
/// It reads a widget definition and its current state from
/// `widget.definition`
/// and constructs the corresponding Flutter widget.
Widget _buildWidget(String widgetId) {
return widget.catalog.buildWidget(
Expand Down
2 changes: 1 addition & 1 deletion pkgs/flutter_genui/lib/src/to_merge/model/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import 'dart:async';

import 'package:flutter/widgets.dart';

import 'image_catalog.dart';
import 'input.dart';
import 'simple_items.dart';
import 'image_catalog.dart';

typedef InputCallback = void Function(Input input);

Expand Down
2 changes: 1 addition & 1 deletion pkgs/flutter_genui/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ dependencies:
stream_channel: ^2.1.4

dev_dependencies:
dart_flutter_team_lints: ^3.5.2
flutter_test:
sdk: flutter
dart_flutter_team_lints: ^3.5.2
2 changes: 1 addition & 1 deletion pkgs/flutter_genui/test/dynamic_ui_test.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_genui/flutter_genui.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
final testCatalog = Catalog([elevatedButtonCatalogItem, text]);
Expand Down
64 changes: 35 additions & 29 deletions pkgs/spikes/fcp_client/test/core/widget_registry_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import 'package:flutter_test/flutter_test.dart';

void main() {
group('WidgetCatalogRegistry', () {
final testDefinition = WidgetDefinition({'properties': <String, Object?>{}});
final testDefinition = WidgetDefinition({
'properties': <String, Object?>{},
});

test('registering and retrieving a builder', () {
final registry = WidgetCatalogRegistry();
Expand All @@ -14,14 +16,15 @@ void main() {
LayoutNode node,
Map<String, Object?> properties,
Map<String, dynamic> children,
) =>
const SizedBox();
) => const SizedBox();

registry.register(CatalogItem(
name: 'TestWidget',
builder: testBuilder,
definition: testDefinition,
));
registry.register(
CatalogItem(
name: 'TestWidget',
builder: testBuilder,
definition: testDefinition,
),
);

final retrievedBuilder = registry.getBuilder('TestWidget');
expect(retrievedBuilder, isNotNull);
Expand All @@ -41,29 +44,31 @@ void main() {
LayoutNode node,
Map<String, Object?> properties,
Map<String, dynamic> children,
) =>
const Text('1');
) => const Text('1');
Widget builder2(
BuildContext context,
LayoutNode node,
Map<String, Object?> properties,
Map<String, dynamic> children,
) =>
const Text('2');
) => const Text('2');

registry.register(CatalogItem(
name: 'TestWidget',
builder: builder1,
definition: testDefinition,
));
registry.register(
CatalogItem(
name: 'TestWidget',
builder: builder1,
definition: testDefinition,
),
);
final retrievedBuilder1 = registry.getBuilder('TestWidget');
expect(retrievedBuilder1, equals(builder1));

registry.register(CatalogItem(
name: 'TestWidget',
builder: builder2,
definition: testDefinition,
));
registry.register(
CatalogItem(
name: 'TestWidget',
builder: builder2,
definition: testDefinition,
),
);
final retrievedBuilder2 = registry.getBuilder('TestWidget');
expect(retrievedBuilder2, equals(builder2));
});
Expand All @@ -75,15 +80,16 @@ void main() {
LayoutNode node,
Map<String, Object?> properties,
Map<String, dynamic> children,
) =>
const SizedBox();
) => const SizedBox();

expect(registry.hasBuilder('TestWidget'), isFalse);
registry.register(CatalogItem(
name: 'TestWidget',
builder: testBuilder,
definition: testDefinition,
));
registry.register(
CatalogItem(
name: 'TestWidget',
builder: testBuilder,
definition: testDefinition,
),
);
expect(registry.hasBuilder('TestWidget'), isTrue);
});
});
Expand Down
Loading