embed_flutter 0.0.2
embed_flutter: ^0.0.2 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';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Embedded Agent',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _currentStep = 0;
final _formKey = GlobalKey<FormState>();
// Form controllers
final _firstNameController = TextEditingController();
final _lastNameController = TextEditingController();
final _emailController = TextEditingController();
final _phoneController = TextEditingController();
final _addressController = TextEditingController();
final _cityController = TextEditingController();
final _zipCodeController = TextEditingController();
final _bioController = TextEditingController();
// Form data
String _selectedGender = 'Prefer not to say';
DateTime? _selectedDate;
List<String> _selectedInterests = [];
bool _acceptTerms = false;
@override
void dispose() {
_firstNameController.dispose();
_lastNameController.dispose();
_emailController.dispose();
_phoneController.dispose();
_addressController.dispose();
_cityController.dispose();
_zipCodeController.dispose();
_bioController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return EmbedWidget(
showEmbedWidget: true,
apiKey: 'key_456',
embedUrl:
'https://embed.revrag.ai', // Optional: custom base URL for API calls
child: Scaffold(
appBar: AppBar(
title: const Text('Embedded Agent SDK Demo'),
backgroundColor: Colors.blue[600],
foregroundColor: Colors.white,
),
body: Stepper(
currentStep: _currentStep,
onStepContinue: () {
if (_currentStep < 3) {
setState(() {
_currentStep++;
});
} else {
_submitForm();
}
},
onStepCancel: () {
if (_currentStep > 0) {
setState(() {
_currentStep--;
});
}
},
steps: [
_buildPersonalInfoStep(),
_buildContactInfoStep(),
_buildAddressStep(),
_buildAdditionalInfoStep(),
],
),
),
);
}
Step _buildPersonalInfoStep() {
return Step(
title: const Text('Personal Information'),
subtitle: const Text('Basic personal details'),
content: Column(
children: [
TextFormField(
controller: _firstNameController,
decoration: const InputDecoration(
labelText: 'First Name',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.person),
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your first name';
}
return null;
},
onChanged: (dynamic value) {
// Notify widget change for real-time monitoring
},
),
const SizedBox(height: 16),
TextFormField(
controller: _lastNameController,
decoration: const InputDecoration(
labelText: 'Last Name',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.person_outline),
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your last name';
}
return null;
},
onChanged: (dynamic value) {},
),
const SizedBox(height: 16),
DropdownButtonFormField<String>(
value: _selectedGender,
decoration: const InputDecoration(
labelText: 'Gender',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.wc),
),
items: ['Male', 'Female', 'Other', 'Prefer not to say']
.map((gender) => DropdownMenuItem(
value: gender,
child: Text(gender),
))
.toList(),
onChanged: (dynamic value) {
setState(() {
_selectedGender = value!;
});
},
),
const SizedBox(height: 16),
InkWell(
onTap: () async {
final date = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1900),
lastDate: DateTime.now(),
);
if (date != null) {
setState(() {
_selectedDate = date;
});
}
},
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(4),
),
child: Row(
children: [
const Icon(Icons.calendar_today),
const SizedBox(width: 8),
Text(
_selectedDate == null
? 'Select Date of Birth'
: 'Date of Birth: ${_selectedDate!.day}/${_selectedDate!.month}/${_selectedDate!.year}',
),
],
),
),
),
],
),
);
}
Step _buildContactInfoStep() {
return Step(
title: const Text('Contact Information'),
subtitle: const Text('How to reach you'),
content: Column(
children: [
TextFormField(
controller: _emailController,
decoration: const InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.email),
),
keyboardType: TextInputType.emailAddress,
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$')
.hasMatch(value)) {
return 'Please enter a valid email';
}
return null;
},
onChanged: (dynamic value) {},
),
const SizedBox(height: 16),
TextFormField(
controller: _phoneController,
decoration: const InputDecoration(
labelText: 'Phone Number',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.phone),
),
keyboardType: TextInputType.phone,
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your phone number';
}
return null;
},
onChanged: (dynamic value) {},
),
],
),
);
}
Step _buildAddressStep() {
return Step(
title: const Text('Address'),
subtitle: const Text('Where you live'),
content: Column(
children: [
TextFormField(
controller: _addressController,
decoration: const InputDecoration(
labelText: 'Street Address',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.home),
),
maxLines: 2,
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your address';
}
return null;
},
onChanged: (dynamic value) {},
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: TextFormField(
controller: _cityController,
decoration: const InputDecoration(
labelText: 'City',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.location_city),
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your city';
}
return null;
},
onChanged: (dynamic value) {},
),
),
const SizedBox(width: 16),
Expanded(
child: TextFormField(
controller: _zipCodeController,
decoration: const InputDecoration(
labelText: 'ZIP Code',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.pin_drop),
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Please enter your ZIP code';
}
return null;
},
onChanged: (dynamic value) {},
),
),
],
),
],
),
);
}
Step _buildAdditionalInfoStep() {
return Step(
title: const Text('Additional Information'),
subtitle: const Text('Tell us more about yourself'),
content: Column(
children: [
TextFormField(
controller: _bioController,
decoration: const InputDecoration(
labelText: 'Bio',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.description),
hintText: 'Tell us about yourself...',
),
maxLines: 3,
onChanged: (dynamic value) {},
),
const SizedBox(height: 16),
const Text('Interests (select all that apply):'),
const SizedBox(height: 8),
Wrap(
spacing: 8,
children: [
'Technology',
'Sports',
'Music',
'Reading',
'Travel',
'Cooking',
'Art',
'Gaming'
].map((interest) {
return FilterChip(
label: Text(interest),
selected: _selectedInterests.contains(interest),
onSelected: (bool selected) {
setState(() {
if (selected) {
_selectedInterests.add(interest);
} else {
_selectedInterests.remove(interest);
}
});
},
);
}).toList(),
),
const SizedBox(height: 16),
Row(
children: [
Checkbox(
value: _acceptTerms,
onChanged: (bool? value) {
setState(() {
_acceptTerms = value ?? false;
});
},
),
const Expanded(
child: Text('I accept the terms and conditions'),
),
],
),
],
),
);
}
void _submitForm() {
if (_formKey.currentState!.validate() && _acceptTerms) {
// Show success dialog
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Success!'),
content: const Text('Your form has been submitted successfully.'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
// Reset form
setState(() {
_currentStep = 0;
_firstNameController.clear();
_lastNameController.clear();
_emailController.clear();
_phoneController.clear();
_addressController.clear();
_cityController.clear();
_zipCodeController.clear();
_bioController.clear();
_selectedGender = 'Prefer not to say';
_selectedDate = null;
_selectedInterests.clear();
_acceptTerms = false;
});
},
child: const Text('OK'),
),
],
),
);
} else if (!_acceptTerms) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please accept the terms and conditions'),
backgroundColor: Colors.red,
),
);
}
}
}