embed_flutter 0.1.0
embed_flutter: ^0.1.0 copied to clipboard
A powerful Flutter SDK that provides a powerful voice-enabled AI-agent functionality with real-time widget tree monitoring for screen context fetching and realtime voice communication.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:embed_flutter/embed_flutter.dart';
import 'theme/abc_theme.dart';
import 'listeners/agent_event_listener.dart';
import 'listeners/phone_call_listener.dart';
import 'models/plan.dart';
import 'screens/login_screen.dart';
import 'screens/otp_screen.dart';
import 'screens/home_tab.dart';
import 'screens/plan_tab.dart';
import 'screens/account_tab.dart';
import 'screens/plan_detail_screen.dart';
void main() {
embedInitialize(
'embed_funnel_key',
flowName: 'main',
onResult: (success, error) {
// ignore: avoid_print
print('Embed initialized: success=$success error=$error');
},
);
runApp(const AbcApp());
}
class AbcApp extends StatelessWidget {
const AbcApp({super.key});
@override
Widget build(BuildContext context) {
return EmbedWidget(
showEmbedWidget: true,
debug: true,
embedButtonDelayMs: 100,
groupContinuity: const {'main': EmbedButtonContinuity.keepVisible},
// The FAB is enabled only inside the authenticated area — never on the
// login / OTP screens. Each tab is a real named route, so switching tabs
// and opening a plan's detail both surface to the SDK correctly.
enabledRoutes: const {
'main': ['home', 'account', 'plan_detail'],
},
// Captures agent lifecycle events for the whole app, in one place.
child: AgentEventListener(
// Ends the voice call if a phone call interrupts.
child: PhoneCallListener(
child: MaterialApp(
title: 'Aditya Birla Capital — Demo',
debugShowCheckedModeBanner: false,
theme: AbcTheme.light,
navigatorObservers: [
EmbedNavigatorObserver(
nameExtractor: (route) {
final name = route.settings.name;
// The initial route reports '/' — that's the login screen.
if (name == null || name == '/') return 'login';
return name;
},
),
],
home: const LoginScreen(),
onGenerateRoute: _onGenerateRoute,
),
),
),
);
}
Route<dynamic>? _onGenerateRoute(RouteSettings settings) {
final args = settings.arguments;
switch (settings.name) {
case 'login':
return _fade(const LoginScreen(), settings);
case 'otp':
return MaterialPageRoute(
builder: (_) => OtpScreen(phone: args as String? ?? ''),
settings: settings,
);
// The three tabs switch instantly (no page slide) so the bar feels like
// a native bottom navigation rather than a push.
case 'home':
return _instant(HomeTab(phone: args as String? ?? ''), settings);
case 'plan':
return _instant(PlanTab(phone: args as String? ?? ''), settings);
case 'account':
return _instant(AccountTab(phone: args as String? ?? ''), settings);
case 'plan_detail':
return MaterialPageRoute(
builder: (_) => PlanDetailScreen(plan: args as Plan),
settings: settings,
);
default:
return null;
}
}
/// Zero-duration transition — used for bottom-nav tab switches.
PageRoute _instant(Widget child, RouteSettings settings) {
return PageRouteBuilder(
settings: settings,
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
pageBuilder: (_, __, ___) => child,
);
}
PageRoute _fade(Widget child, RouteSettings settings) {
return PageRouteBuilder(
settings: settings,
transitionDuration: const Duration(milliseconds: 200),
pageBuilder: (_, __, ___) => child,
transitionsBuilder: (_, anim, __, c) =>
FadeTransition(opacity: anim, child: c),
);
}
}