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
30 changes: 11 additions & 19 deletions firebase_ai_logic_showcase/lib/demos/live_api/live_api_demo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import 'utilities/utilities.dart';
import 'firebaseai_live_api_service.dart';

class LiveAPIDemo extends ConsumerStatefulWidget {
const LiveAPIDemo({super.key, this.isSelected = false});
final bool isSelected;
const LiveAPIDemo({super.key});

@override
ConsumerState<LiveAPIDemo> createState() => _LiveAPIDemoState();
Expand All @@ -45,9 +44,7 @@ class _LiveAPIDemoState extends ConsumerState<LiveAPIDemo> {
late final VideoInput _videoInput = VideoInput();

// Initialization flags.
bool _audioIsInitialized = false;
bool _videoIsInitialized = false;
static bool _hasBeenSelected = false;

// UI State flags.
bool _isConnecting = false; // True when setting up the Gemini session.
Expand All @@ -66,24 +63,19 @@ class _LiveAPIDemoState extends ConsumerState<LiveAPIDemo> {
@override
void didUpdateWidget(LiveAPIDemo oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.isSelected != oldWidget.isSelected) {
_checkAndInitializeIO();
}
_checkAndInitializeIO();
}

Future<void> _checkAndInitializeIO() async {
if (widget.isSelected && !_hasBeenSelected) {
_hasBeenSelected = true;
await _initializeAudio();
await _initializeVideo();
_liveApiService = LiveApiService(
audioOutput: _audioOutput,
ref: ref, // Pass the ref to the service
onImageLoadingChange: _onImageLoadingChange,
onImageGenerated: _onImageGenerated,
onError: _showErrorSnackBar,
);
}
await _initializeAudio();
await _initializeVideo();
_liveApiService = LiveApiService(
audioOutput: _audioOutput,
ref: ref, // Pass the ref to the service
onImageLoadingChange: _onImageLoadingChange,
onImageGenerated: _onImageGenerated,
onError: _showErrorSnackBar,
);
}

@override
Expand Down
66 changes: 34 additions & 32 deletions firebase_ai_logic_showcase/lib/flutter_firebase_ai_demo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ class DemoHomeScreen extends StatefulWidget {

class _DemoHomeScreenState extends State<DemoHomeScreen> {
int _selectedIndex = 0;
final List<({Widget icon, String label, Widget? selectedIcon})> destinations =
[
(icon: const Icon(Icons.chat), label: 'Chat', selectedIcon: null),
(
icon: const Icon(Icons.video_chat),
label: 'Live API',
selectedIcon: null,
),
(
icon: const Icon(Icons.photo_library),
label: 'Multimodal',
selectedIcon: null,
),
(
icon: RichText(
text: const TextSpan(style: TextStyle(fontSize: 24.0), text: '🍌'),
),
label: 'Nano Banana',
selectedIcon: null,
),
];

void _onItemTapped(int index) {
setState(() {
Expand All @@ -36,35 +57,12 @@ class _DemoHomeScreenState extends State<DemoHomeScreen> {

@override
Widget build(BuildContext context) {
final List<Widget> demoPages = <Widget>[
const ChatDemo(),
LiveAPIDemo(isSelected: _selectedIndex == 1),
const MultimodalDemo(),
ChatDemoNano(isSelected: _selectedIndex == 3),
];

final List<({Widget icon, String label, Widget? selectedIcon})> destinations = [
(icon: const Icon(Icons.chat), label: 'Chat', selectedIcon: null),
(icon: const Icon(Icons.video_chat), label: 'Live API', selectedIcon: null),
(icon: const Icon(Icons.photo_library), label: 'Multimodal', selectedIcon: null),
(
icon: RichText(
text: const TextSpan(
style: TextStyle(fontSize: 24.0),
text: '🍌',
),
),
label: 'Nano Banana',
selectedIcon: null
),
];

return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) {
// Use BottomNavigationBar for smaller screens
return Scaffold(
body: IndexedStack(index: _selectedIndex, children: demoPages),
body: demoPages[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: destinations
Expand Down Expand Up @@ -94,20 +92,17 @@ class _DemoHomeScreenState extends State<DemoHomeScreen> {
(e) => NavigationRailDestination(
padding: const EdgeInsets.symmetric(vertical: 8.0),
icon: e.icon,
label: Text(e.label.replaceAll(' ', '\n'),
textAlign: TextAlign.center),
label: Text(
e.label.replaceAll(' ', '\n'),
textAlign: TextAlign.center,
),
selectedIcon: e.selectedIcon,
),
)
.toList(),
),
const VerticalDivider(thickness: 1, width: 1),
Expanded(
child: IndexedStack(
index: _selectedIndex,
children: demoPages,
),
),
Expanded(child: demoPages[_selectedIndex]),
],
),
);
Expand All @@ -116,3 +111,10 @@ class _DemoHomeScreenState extends State<DemoHomeScreen> {
);
}
}

final List<Widget> demoPages = <Widget>[
const ChatDemo(),
LiveAPIDemo(),
const MultimodalDemo(),
ChatDemoNano(),
];