datasapien_sdk 0.33.0
datasapien_sdk: ^0.33.0 copied to clipboard
Flutter plugin wrapper for DataSapien iOS and Android SDKs
example/lib/main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:datasapien_sdk/datasapien_sdk.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'models.dart';
import 'services/backup_service_actions.dart';
import 'services/medata_service_actions.dart';
import 'services/audience_service_actions.dart';
import 'services/managed_api_service_actions.dart';
import 'services/journey_service_actions.dart';
import 'services/intelligence_service_actions.dart';
import 'widgets/action_section.dart';
import 'widgets/service_input_forms.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await dotenv.load(fileName: '.env');
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp>
with
BackupServiceActions,
MeDataServiceActions,
AudienceServiceActions,
ManagedApiServiceActions,
JourneyServiceActions,
IntelligenceServiceActions {
String _status = 'Not initialized';
String? _resultPreview;
String? _errorMessage;
bool _isInitialized = false;
bool _isLoading = false;
SelectedService _selectedService = SelectedService.backup;
@override
void dispose() {
disposeMeDataControllers();
disposeAudienceControllers();
disposeManagedApiControllers();
disposeJourneyControllers();
disposeIntelligenceControllers();
super.dispose();
}
@override
void setRunning(String action) {
setState(() {
_status = 'Running $action...';
_errorMessage = null;
});
}
@override
void setSuccess(String action, Object? result) {
String? preview;
if (result != null) {
try {
const encoder = JsonEncoder.withIndent(' ');
preview = encoder.convert(result);
} catch (_) {
preview = result.toString();
}
if (preview.length > 800) {
preview = '${preview.substring(0, 800)}...';
}
}
setState(() {
_status = '$action succeeded';
_resultPreview = preview;
});
}
@override
void setError(String action, Object e, StackTrace stackTrace) {
final errorMsg = '$e\n\nStack trace:\n$stackTrace';
debugPrint('❌ $action Error: $e');
debugPrint('Stack trace: $stackTrace');
setState(() {
_status = '$action failed';
_errorMessage = errorMsg;
});
}
@override
bool ensureInitialized(String actionName) {
if (_isInitialized) return true;
const errorMsg = 'SDK must be initialized first';
debugPrint('❌ $actionName Error: $errorMsg');
setState(() {
_errorMessage = errorMsg;
});
return false;
}
Future<void> _initializeSdk() async {
if (_isLoading) return;
setState(() {
_isLoading = true;
_errorMessage = null;
_status = 'Initializing...';
});
try {
String envRequired(String key) {
final value = dotenv.env[key];
if (value == null || value.trim().isEmpty) {
throw Exception(
'Missing $key in sdk/example/.env.\n'
'Copy sdk/example/.env.example to sdk/example/.env and fill in values.',
);
}
return value.trim();
}
final config = DataSapienConfig.builder()
.setAuth(
authUrl: envRequired('DATASAPIEN_AUTH_URL'),
authClientId: envRequired('DATASAPIEN_CLIENT_ID'),
authClientSecret: envRequired('DATASAPIEN_CLIENT_SECRET'),
authScope: envRequired('DATASAPIEN_SCOPE'),
)
.setHostUrl(envRequired('DATASAPIEN_HOST_URL'))
.setMediaUrl(envRequired('DATASAPIEN_MEDIA_URL'))
.setMainColor('#F37102')
.setDebug(true)
.build();
await DataSapien.initialize(config);
setState(() {
_status = 'Initialized';
});
setState(() {
_status = 'Setting up...';
});
await DataSapien.setup();
setState(() {
_status = 'Ready';
_isInitialized = true;
_isLoading = false;
});
} catch (e, stackTrace) {
setState(() {
_status = 'Error';
_errorMessage = '${e.toString()}\n\nStack trace:\n$stackTrace';
_isLoading = false;
});
}
}
List<ActionItem> _currentActions() {
switch (_selectedService) {
case SelectedService.backup:
return backupActions();
case SelectedService.meData:
return meDataActions();
case SelectedService.audience:
return audienceActions();
case SelectedService.managedApi:
return managedApiActions();
case SelectedService.journey:
return journeyActions();
case SelectedService.intelligence:
return intelligenceActions();
case SelectedService.other:
return const [];
}
}
String _getServiceTitle() {
switch (_selectedService) {
case SelectedService.backup:
return 'BackupService Actions';
case SelectedService.meData:
return 'MeDataService Actions';
case SelectedService.audience:
return 'AudienceService Actions';
case SelectedService.managedApi:
return 'ManagedAPIService Actions';
case SelectedService.journey:
return 'JourneyService Actions';
case SelectedService.intelligence:
return 'IntelligenceService Actions';
case SelectedService.other:
return 'Other Service Actions';
}
}
Widget? _getServiceInputForm() {
switch (_selectedService) {
case SelectedService.meData:
return MeDataInputForm(
nameController: meDataNameController,
categoryController: meDataCategoryController,
valuesJsonController: meDataValuesJsonController,
collectNamesController: meDataCollectNamesController,
);
case SelectedService.audience:
return AudienceInputForm(
segmentNameController: audienceSegmentNameController,
);
case SelectedService.managedApi:
return ManagedApiInputForm(
nameController: managedApiNameController,
);
case SelectedService.journey:
return JourneyInputForm(
nameController: journeyNameController,
dataJsonController: journeyDataJsonController,
);
case SelectedService.intelligence:
return IntelligenceInputForm(
modelNameController: intelligenceModelNameController,
modelKeyController: intelligenceModelKeyController,
promptController: intelligencePromptController,
ruleNameController: intelligenceRuleNameController,
);
default:
return null;
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('DataSapien SDK Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// SDK Status Card
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'SDK Status',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(_status),
const SizedBox(height: 12),
if (!_isInitialized)
ElevatedButton(
onPressed: _isLoading ? null : _initializeSdk,
child: Text(
_isLoading ? 'Initializing...' : 'Initialize SDK',
),
),
],
),
),
),
const SizedBox(height: 12),
// Service Selector
Row(
children: [
const Text(
'Selected service:',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(width: 8),
DropdownButton<SelectedService>(
value: _selectedService,
onChanged: (value) {
if (value == null) return;
setState(() {
_selectedService = value;
});
},
items: const [
DropdownMenuItem(
value: SelectedService.backup,
child: Text('BackupService'),
),
DropdownMenuItem(
value: SelectedService.meData,
child: Text('MeDataService'),
),
DropdownMenuItem(
value: SelectedService.audience,
child: Text('AudienceService'),
),
DropdownMenuItem(
value: SelectedService.managedApi,
child: Text('ManagedAPIService'),
),
DropdownMenuItem(
value: SelectedService.journey,
child: Text('JourneyService'),
),
DropdownMenuItem(
value: SelectedService.intelligence,
child: Text('IntelligenceService'),
),
DropdownMenuItem(
value: SelectedService.other,
child: Text('Other (placeholder)'),
),
],
),
],
),
if (!_isInitialized)
const Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 8.0),
child: Text(
'Initialize SDK first to enable service actions.',
style: TextStyle(fontSize: 12, color: Colors.black54),
),
),
const SizedBox(height: 8),
// Service Actions Section
ActionSection(
title: _getServiceTitle(),
actions: _currentActions(),
isInitialized: _isInitialized,
extraControls: _getServiceInputForm(),
),
// Download Progress Indicator
if (downloadProgress != null) ...[
const SizedBox(height: 12),
Card(
color: Colors.blue.shade50,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Download Progress: ${(downloadProgress! * 100).toStringAsFixed(1)}%',
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
LinearProgressIndicator(value: downloadProgress),
],
),
),
),
],
// Streaming Text Display
if (streamingText != null) ...[
const SizedBox(height: 12),
Card(
color: Colors.green.shade50,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Streaming Response',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
streamingText!,
style: const TextStyle(fontSize: 12),
),
],
),
),
),
],
// Error Display
if (_errorMessage != null) ...[
const SizedBox(height: 12),
Card(
color: Colors.red.shade50,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Error',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
const SizedBox(height: 8),
Text(
_errorMessage!,
style: const TextStyle(
fontSize: 12,
color: Colors.red,
),
),
],
),
),
),
],
// Result Preview
if (_resultPreview != null) ...[
const SizedBox(height: 12),
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Last result',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
_resultPreview!,
style: const TextStyle(fontSize: 12),
),
],
),
),
),
],
// Backup JSON Display
if (backupJson != null) ...[
const SizedBox(height: 12),
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Backup JSON (first 200 chars)',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
backupJson!.length > 200
? '${backupJson!.substring(0, 200)}...'
: backupJson!,
style: const TextStyle(fontSize: 12),
),
],
),
),
),
],
],
),
),
),
),
);
}
}