diff --git a/firebase_ai_logic_showcase/lib/demos/chat/chat_demo.dart b/firebase_ai_logic_showcase/lib/demos/chat/chat_demo.dart index b6abb56..73eab04 100644 --- a/firebase_ai_logic_showcase/lib/demos/chat/chat_demo.dart +++ b/firebase_ai_logic_showcase/lib/demos/chat/chat_demo.dart @@ -24,7 +24,7 @@ import '../../shared/ui/app_frame.dart'; import '../../shared/ui/app_spacing.dart'; import './ui_components/ui_components.dart'; import './firebaseai_chat_service.dart'; -import 'ui_components/model_picker.dart'; + import './models/models.dart'; class ChatDemo extends ConsumerStatefulWidget { @@ -189,14 +189,14 @@ class _ChatDemoState extends ConsumerState { ), ), ), - MessageInputBar( - textController: _userTextInputController, - loading: _loading, - sendMessage: sendMessage, - onPickImagePressed: _pickImage, - ), ], ), + bottomNavigationBar: MessageInputBar( + textController: _userTextInputController, + loading: _loading, + sendMessage: sendMessage, + onPickImagePressed: _pickImage, + ), ); } -} \ No newline at end of file +} diff --git a/firebase_ai_logic_showcase/lib/demos/chat_nano/chat_nano_demo.dart b/firebase_ai_logic_showcase/lib/demos/chat_nano/chat_nano_demo.dart index 1d7c3b9..4754441 100644 --- a/firebase_ai_logic_showcase/lib/demos/chat_nano/chat_nano_demo.dart +++ b/firebase_ai_logic_showcase/lib/demos/chat_nano/chat_nano_demo.dart @@ -206,14 +206,14 @@ class ChatDemoNanoState extends ConsumerState { ), ), ), - MessageInputBar( - textController: _userTextInputController, - loading: _loading, - sendMessage: sendMessage, - onPickImagePressed: _pickImage, - ), ], ), + bottomNavigationBar: MessageInputBar( + textController: _userTextInputController, + loading: _loading, + sendMessage: sendMessage, + onPickImagePressed: _pickImage, + ), ); } -} \ No newline at end of file +} diff --git a/firebase_ai_logic_showcase/lib/demos/chat_nano/models/gemini_model_nano.dart b/firebase_ai_logic_showcase/lib/demos/chat_nano/models/gemini_model_nano.dart index e5d2f8e..8bd8ddf 100644 --- a/firebase_ai_logic_showcase/lib/demos/chat_nano/models/gemini_model_nano.dart +++ b/firebase_ai_logic_showcase/lib/demos/chat_nano/models/gemini_model_nano.dart @@ -1,5 +1,4 @@ import 'package:firebase_ai/firebase_ai.dart'; -import '../../../shared/function_calling/tools.dart'; var geminiModels = GeminiModelsNano(); diff --git a/firebase_ai_logic_showcase/lib/demos/imagen/imagen_demo.dart b/firebase_ai_logic_showcase/lib/demos/imagen/imagen_demo.dart deleted file mode 100644 index 5d32ba9..0000000 --- a/firebase_ai_logic_showcase/lib/demos/imagen/imagen_demo.dart +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'dart:typed_data'; -import '../../shared/ui/app_frame.dart'; -import '../../shared/ui/app_spacing.dart'; -import '../../shared/firebaseai_imagen_service.dart'; -import './ui_components/ui_components.dart'; - -class ImageGenerationDemo extends StatefulWidget { - const ImageGenerationDemo({super.key}); - - @override - State createState() => _ImageGenerationDemoState(); -} - -class _ImageGenerationDemoState extends State { - // Service for interacting with the Gemini API. - final _imagenService = ImageGenerationService(); - - // UI State - bool _loading = false; - List images = []; - TextEditingController promptController = TextEditingController( - text: - 'Hot air balloons rising over the San Francisco Bay at golden hour ' - 'with a view of the Golden Gate Bridge. Make it anime style.', - ); - - void generateImages(BuildContext context, String prompt) async { - setState(() { - _loading = true; - images = []; // Clear previous images while loading - }); - - try { - final image = await _imagenService.generateImage(prompt); - setState(() { - images = [image]; - }); - } catch (e) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(e.toString()), - backgroundColor: Theme.of(context).colorScheme.error, - ), - ); - } finally { - setState(() { - _loading = false; - }); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: Text('Image Generation Demo')), - body: SingleChildScrollView( - padding: EdgeInsets.only( - bottom: MediaQuery.viewInsetsOf(context).bottom, - ), - child: AppFrame( - child: Padding( - padding: const EdgeInsets.all(AppSpacing.s8), - child: Column( - children: [ - ImageDisplay(loading: _loading, images: images), - const SizedBox.square(dimension: AppSpacing.s8), - PromptInput( - promptController: promptController, - loading: _loading, - generateImages: generateImages, - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/firebase_ai_logic_showcase/lib/demos/imagen/ui_components/image_display.dart b/firebase_ai_logic_showcase/lib/demos/imagen/ui_components/image_display.dart deleted file mode 100644 index 01224ab..0000000 --- a/firebase_ai_logic_showcase/lib/demos/imagen/ui_components/image_display.dart +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:typed_data'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import '../../../shared/ui/app_spacing.dart'; -import '../../../shared/ui/blaze_warning.dart'; - -class ImageDisplay extends StatelessWidget { - final bool loading; - final List images; - - const ImageDisplay({super.key, required this.loading, required this.images}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(AppSpacing.s4), - child: LayoutBuilder( - builder: (context, constraints) { - return ConstrainedBox( - constraints: BoxConstraints.loose( - Size(double.infinity, constraints.maxWidth), - ), - child: Center( - child: loading - ? CircularProgressIndicator() - : images.isEmpty - ? Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodyLarge, - 'Write a prompt below to generate images.', - ), - SizedBox.square(dimension: AppSpacing.s8), - BlazeWarning(), - ], - ) - : CarouselView.weighted( - enableSplash: false, - itemSnapping: true, - flexWeights: [1, 6, 1], - children: images - .map((image) => Image.memory(image)) - .toList(), - ), - ), - ); - }, - ), - ); - } -} diff --git a/firebase_ai_logic_showcase/lib/demos/imagen/ui_components/prompt_input.dart b/firebase_ai_logic_showcase/lib/demos/imagen/ui_components/prompt_input.dart deleted file mode 100644 index b203ba2..0000000 --- a/firebase_ai_logic_showcase/lib/demos/imagen/ui_components/prompt_input.dart +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import '../../../shared/ui/app_spacing.dart'; - -class PromptInput extends StatelessWidget { - final TextEditingController promptController; - final bool loading; - final void Function(BuildContext, String) generateImages; - - const PromptInput({ - super.key, - required this.promptController, - required this.loading, - required this.generateImages, - }); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: AppSpacing.s8), - child: TextField( - decoration: InputDecoration( - label: const Text('Prompt'), - fillColor: Theme.of(context).colorScheme.onSecondaryFixed, - filled: true, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(AppSpacing.s16), - ), - ), - maxLines: 4, - controller: promptController, - enabled: !loading, - onTap: () { - promptController.selection = TextSelection( - baseOffset: 0, - extentOffset: promptController.text.length, - ); - }, - ), - ), - ), - Padding( - padding: const EdgeInsets.all(AppSpacing.s8), - child: ElevatedButton( - style: ButtonStyle( - shape: WidgetStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppSpacing.s16), - ), - ), - backgroundColor: WidgetStatePropertyAll( - Theme.of(context).colorScheme.primaryContainer, - ), - ), - onPressed: loading - ? null - : () => generateImages(context, promptController.text), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: AppSpacing.s24, - horizontal: 0, - ), - child: Column( - children: [ - const Icon(size: 32, Icons.brush), - const SizedBox.square(dimension: AppSpacing.s8), - const Text(textAlign: TextAlign.center, 'Create\nImage'), - ], - ), - ), - ), - ), - ], - ); - } -} diff --git a/firebase_ai_logic_showcase/lib/demos/imagen/ui_components/ui_components.dart b/firebase_ai_logic_showcase/lib/demos/imagen/ui_components/ui_components.dart deleted file mode 100644 index 759ffad..0000000 --- a/firebase_ai_logic_showcase/lib/demos/imagen/ui_components/ui_components.dart +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -export 'image_display.dart'; -export 'prompt_input.dart'; diff --git a/firebase_ai_logic_showcase/lib/demos/live_api/live_api_demo.dart b/firebase_ai_logic_showcase/lib/demos/live_api/live_api_demo.dart index bc2580b..a1785cd 100644 --- a/firebase_ai_logic_showcase/lib/demos/live_api/live_api_demo.dart +++ b/firebase_ai_logic_showcase/lib/demos/live_api/live_api_demo.dart @@ -255,7 +255,6 @@ class _LiveAPIDemoState extends ConsumerState { backgroundColor: Theme.of(context).colorScheme.surface, body: Column( children: [ - const SizedBox(height: 24.0), Expanded( child: LiveApiBody( cameraIsActive: _cameraIsActive, @@ -274,7 +273,9 @@ class _LiveAPIDemoState extends ConsumerState { : null, ), VideoButton( - isActive: _cameraIsActive, onPressed: toggleVideoStream), + isActive: _cameraIsActive, + onPressed: toggleVideoStream, + ), AudioVisualizer( audioStreamIsActive: _isCallActive, amplitudeStream: audioInput.amplitudeStream, @@ -283,10 +284,7 @@ class _LiveAPIDemoState extends ConsumerState { isMuted: audioInput.isPaused, onPressed: _isCallActive ? toggleMuteInput : null, ), - CallButton( - isActive: _isCallActive, - onPressed: toggleCall, - ), + CallButton(isActive: _isCallActive, onPressed: toggleCall), ], ), ], diff --git a/firebase_ai_logic_showcase/lib/demos/multimodal/multimodal_demo.dart b/firebase_ai_logic_showcase/lib/demos/multimodal/multimodal_demo.dart index 7920479..d1f0dfd 100644 --- a/firebase_ai_logic_showcase/lib/demos/multimodal/multimodal_demo.dart +++ b/firebase_ai_logic_showcase/lib/demos/multimodal/multimodal_demo.dart @@ -99,7 +99,6 @@ class _MultimodalDemoState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - const SizedBox(height: 24.0), const SizedBox.square(dimension: AppSpacing.s16), FilePromptInput( promptController: promptController, diff --git a/firebase_ai_logic_showcase/lib/flutter_firebase_ai_demo.dart b/firebase_ai_logic_showcase/lib/flutter_firebase_ai_demo.dart index f8ec269..fc692d2 100644 --- a/firebase_ai_logic_showcase/lib/flutter_firebase_ai_demo.dart +++ b/firebase_ai_logic_showcase/lib/flutter_firebase_ai_demo.dart @@ -60,10 +60,7 @@ class _DemoHomeScreenState extends State { if (constraints.maxWidth < 600) { // Use BottomNavigationBar for smaller screens return Scaffold( - body: IndexedStack( - index: _selectedIndex, - children: _demoPages, - ), + body: IndexedStack(index: _selectedIndex, children: _demoPages), bottomNavigationBar: BottomNavigationBar( items: [ const BottomNavigationBarItem( @@ -81,9 +78,7 @@ class _DemoHomeScreenState extends State { BottomNavigationBarItem( icon: RichText( text: const TextSpan( - style: TextStyle( - fontSize: 24.0, - ), + style: TextStyle(fontSize: 24.0), text: '🍌', ), ), @@ -117,19 +112,20 @@ class _DemoHomeScreenState extends State { const NavigationRailDestination( padding: EdgeInsets.symmetric(vertical: 8.0), icon: Icon(Icons.photo_library), - label: Text('Multimodal\nInput', textAlign: TextAlign.center), + label: Text('Multimodal', textAlign: TextAlign.center), ), NavigationRailDestination( padding: const EdgeInsets.symmetric(vertical: 8.0), icon: RichText( text: const TextSpan( - style: TextStyle( - fontSize: 24.0, - ), + style: TextStyle(fontSize: 24.0), text: '🍌', ), ), - label: const Text('Nano\nBanana', textAlign: TextAlign.center), + label: const Text( + 'Nano\nBanana', + textAlign: TextAlign.center, + ), ), ], ), @@ -147,4 +143,4 @@ class _DemoHomeScreenState extends State { }, ); } -} \ No newline at end of file +}