appero_flutter 0.1.1
appero_flutter: ^0.1.1 copied to clipboard
Flutter plugin for Appero in-app feedback collection SDK
example/lib/main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:appero_flutter/appero.dart';
/// Example analytics delegate implementation
/// This demonstrates how to track Appero feedback interactions in your analytics service
class MyAnalyticsDelegate implements ApperoAnalyticsDelegate {
@override
void onRatingSelected(int rating) {
debugPrint('📊 Analytics: Rating selected - $rating');
// TODO: Send to your analytics service (e.g., Firebase Analytics, Mixpanel, etc.)
// Example:
// FirebaseAnalytics.instance.logEvent(
// name: 'appero_rating_selected',
// parameters: {'rating': rating},
// );
}
@override
void onFeedbackSubmitted(int rating, String? feedback) {
debugPrint('📊 Analytics: Feedback submitted - Rating: $rating, Feedback: ${feedback ?? '(none)'}');
// TODO: Send to your analytics service
// Example:
// FirebaseAnalytics.instance.logEvent(
// name: 'appero_feedback_submitted',
// parameters: {
// 'rating': rating,
// 'has_feedback': feedback != null,
// 'feedback_length': feedback?.length ?? 0,
// },
// );
}
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Appero SDK
// TODO: Replace with your actual API key
await Appero.instance.initialize(
apiKey: 'your_api_key',
userId: 'example_user_123',
debug: kDebugMode
);
// Set up analytics delegate to track feedback interactions
Appero.instance.setAnalyticsDelegate(MyAnalyticsDelegate());
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Appero SDK Example',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const ApperoExamplePage(),
);
}
}
class ApperoExamplePage extends StatefulWidget {
const ApperoExamplePage({super.key});
@override
State<ApperoExamplePage> createState() => _ApperoExamplePageState();
}
class _ApperoExamplePageState extends State<ApperoExamplePage> {
int _selectedTheme = 0; // 0: System, 1: Theme 1, 2: Theme 2
Future<void> _logExperience(ExperienceRating rating, String details) async {
try {
await Appero.instance.log(rating: rating, context: details);
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $e')),
);
}
}
}
Future<void> _showFeedbackPrompt() async {
try {
await Appero.instance.showFeedbackPrompt();
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $e')),
);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[50],
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Title
const Text(
'Appero SDK Demo',
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: Colors.black,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 36),
// Theme selector
const Text(
'Appero UI theme:',
style: TextStyle(
fontSize: 18,
color: Colors.black87,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
_buildThemeSelector(),
const SizedBox(height: 36),
// Feedback buttons
_buildFeedbackButton(
'Very Positive',
Icons.thumb_up,
const Color(0xFFB8E6B8),
const Color(0xFF2196F3),
ExperienceRating.strongPositive,
),
const SizedBox(height: 12),
_buildFeedbackButton(
'Positive',
Icons.thumb_up,
const Color(0xFFD4F1D4),
const Color(0xFF2196F3),
ExperienceRating.positive,
),
const SizedBox(height: 12),
_buildFeedbackButton(
'Neutral',
Icons.thumbs_up_down,
const Color(0xFFFFF4DC),
const Color(0xFF2196F3),
ExperienceRating.neutral,
),
const SizedBox(height: 12),
_buildFeedbackButton(
'Negative',
Icons.thumb_down,
const Color(0xFFFFE0E0),
const Color(0xFF2196F3),
ExperienceRating.negative,
),
const SizedBox(height: 12),
_buildFeedbackButton(
'Very Negative',
Icons.thumb_down,
const Color(0xFFFFCCCC),
const Color(0xFF2196F3),
ExperienceRating.strongNegative,
),
const SizedBox(height: 48),
// Manually trigger feedback button
_buildManualTriggerButton(),
],
),
),
),
);
}
Widget _buildThemeSelector() {
return Container(
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(12),
),
padding: const EdgeInsets.all(4),
child: Row(
children: [
_buildThemeOption('System', 0),
_buildThemeOption('Theme 1', 1),
_buildThemeOption('Theme 2', 2),
],
),
);
}
Widget _buildThemeOption(String label, int index) {
final isSelected = _selectedTheme == index;
return Expanded(
child: GestureDetector(
onTap: () async {
setState(() {
_selectedTheme = index;
});
// Apply theme to SDK
ApperoTheme? theme;
switch (index) {
case 0:
theme = null; // System default
break;
case 1:
theme = customTheme1;
break;
case 2:
theme = customTheme2;
break;
}
try {
await Appero.instance.setTheme(theme);
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to set theme: $e')),
);
}
}
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12),
decoration: BoxDecoration(
color: isSelected ? Colors.white : Colors.transparent,
borderRadius: BorderRadius.circular(8),
),
child: Text(
label,
style: TextStyle(
fontSize: 16,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
color: isSelected ? Colors.black : Colors.grey[600],
),
textAlign: TextAlign.center,
),
),
),
);
}
Widget _buildFeedbackButton(
String label,
IconData icon,
Color backgroundColor,
Color iconColor,
ExperienceRating rating,
) {
return Container(
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(16),
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () => _logExperience(rating, 'Flutter SDK example - $label'),
borderRadius: BorderRadius.circular(16),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 24),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
color: iconColor,
size: 28,
),
const SizedBox(width: 12),
Text(
label,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: iconColor,
),
),
],
),
),
),
),
);
}
Widget _buildManualTriggerButton() {
return Container(
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(16),
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: _showFeedbackPrompt,
borderRadius: BorderRadius.circular(16),
child: const Padding(
padding: EdgeInsets.symmetric(vertical: 20),
child: Text(
'Manually Trigger Feedback',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Color(0xFF2196F3),
),
textAlign: TextAlign.center,
),
),
),
),
);
}
}