cello_sdk 0.0.1
cello_sdk: ^0.0.1 copied to clipboard
Flutter plugin wrapper for the Cello iOS and Android SDKs.
example/lib/main.dart
import 'dart:async';
import 'package:cello_sdk/cello_sdk.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const CelloExampleApp());
}
class CelloExampleApp extends StatelessWidget {
const CelloExampleApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: CelloExampleHome());
}
}
class CelloExampleHome extends StatefulWidget {
const CelloExampleHome({super.key});
@override
State<CelloExampleHome> createState() => _CelloExampleHomeState();
}
class _CelloExampleHomeState extends State<CelloExampleHome> {
final _productIdController = TextEditingController(text: 'dev.cello.so');
final _tokenController = TextEditingController();
final _environmentController = TextEditingController(text: 'sandbox');
final _languageController = TextEditingController(text: 'en');
final _themeModeController = TextEditingController(text: 'system');
final _firstNameController = TextEditingController();
final _lastNameController = TextEditingController();
final _emailController = TextEditingController();
final List<String> _logs = <String>[];
StreamSubscription<CelloTokenEvent>? _tokenSubscription;
CelloConfiguration? _configuration;
Map<String, String> _activeUcc = <String, String>{};
Map<String, dynamic> _campaignConfig = <String, dynamic>{};
bool _initializing = false;
@override
void initState() {
super.initState();
_tokenSubscription = Cello.tokenEvents.listen((event) {
setState(() {
_logs.add('[${event.timestamp.toIso8601String()}] ${event.type.name}');
});
});
}
@override
void dispose() {
_tokenSubscription?.cancel();
_productIdController.dispose();
_tokenController.dispose();
_environmentController.dispose();
_languageController.dispose();
_themeModeController.dispose();
_firstNameController.dispose();
_lastNameController.dispose();
_emailController.dispose();
super.dispose();
}
Future<void> _initialize() async {
FocusScope.of(context).unfocus();
if (_tokenController.text.isEmpty || _productIdController.text.isEmpty) {
_log('Provide productId and token before initializing.');
return;
}
setState(() {
_initializing = true;
});
try {
final options = CelloInitializeOptions(
productId: _productIdController.text.trim(),
token: _tokenController.text.trim(),
environment: _environmentController.text.trim().isEmpty
? null
: _environmentController.text.trim(),
language: _languageController.text.trim().isEmpty
? null
: _languageController.text.trim(),
themeMode: _themeModeController.text.trim().isEmpty
? null
: _themeModeController.text.trim(),
userDetails: _buildUserDetails(),
);
final configuration = await Cello.initialize(options);
setState(() {
_configuration = configuration;
});
_log('Cello initialized.');
await Cello.showFab();
} catch (error) {
_log('Initialization failed: $error');
} finally {
setState(() {
_initializing = false;
});
}
}
Future<void> _updateToken() async {
if (_tokenController.text.isEmpty) {
_log('Enter a token to update.');
return;
}
try {
await Cello.updateToken(_tokenController.text.trim());
_log('Token updated.');
} catch (error) {
_log('Failed to update token: $error');
}
}
Future<void> _changeLanguage() async {
if (_languageController.text.isEmpty) {
_log('Enter a language code.');
return;
}
try {
await Cello.changeLanguage(_languageController.text.trim());
_log('Language changed.');
} catch (error) {
_log('Failed to change language: $error');
}
}
Future<void> _setThemeMode() async {
if (_themeModeController.text.isEmpty) {
_log('Enter a theme mode (light, dark, or system).');
return;
}
try {
await Cello.setThemeMode(_themeModeController.text.trim());
_log('Theme mode set to ${_themeModeController.text.trim()}.');
} catch (error) {
_log('Failed to set theme mode: $error');
}
}
Future<void> _fetchActiveUcc() async {
try {
final response = await Cello.getActiveUcc();
setState(() {
_activeUcc = response;
});
_log('Fetched active UCC (${response.length} keys).');
} catch (error) {
_log('Failed to fetch active UCC: $error');
}
}
Future<void> _fetchCampaignConfig() async {
try {
final response = await Cello.getCampaignConfig();
setState(() {
_campaignConfig = response;
});
_log('Fetched campaign config (${response.length} keys).');
} catch (error) {
_log('Failed to fetch campaign config: $error');
}
}
Future<void> _shutdown() async {
try {
await Cello.shutdown();
_log('Cello shutdown complete.');
setState(() {
_configuration = null;
});
} catch (error) {
_log('Failed to shutdown: $error');
}
}
ProductUserDetails? _buildUserDetails() {
if (_firstNameController.text.isEmpty &&
_lastNameController.text.isEmpty &&
_emailController.text.isEmpty) {
return null;
}
return ProductUserDetails(
firstName: _firstNameController.text.trim().isEmpty
? null
: _firstNameController.text.trim(),
lastName: _lastNameController.text.trim().isEmpty
? null
: _lastNameController.text.trim(),
email: _emailController.text.trim().isEmpty
? null
: _emailController.text.trim(),
);
}
void _log(String message) {
setState(() {
_logs.add(message);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Cello Flutter Example'),
actions: [
IconButton(
onPressed: () {
setState(() {
_logs.clear();
});
},
icon: const Icon(Icons.delete_outline),
tooltip: 'Clear logs',
),
],
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16),
child: ListView(
children: [
_sectionTitle('Credentials'),
_textField('Product ID', _productIdController),
_textField('Token', _tokenController),
_textField('Environment (optional)', _environmentController),
_textField('Language (optional)', _languageController),
_textField('Theme Mode (optional)', _themeModeController),
const SizedBox(height: 8),
_sectionTitle('Product User (optional)'),
_textField('First name', _firstNameController),
_textField('Last name', _lastNameController),
_textField(
'Email',
_emailController,
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: 16),
Wrap(
spacing: 12,
runSpacing: 12,
children: [
ElevatedButton(
onPressed: _initializing ? null : _initialize,
child: Text(
_initializing ? 'Initializing…' : 'Initialize & Show FAB',
),
),
ElevatedButton(
onPressed: Cello.isInitialized
? () => Cello.hideFab()
: null,
child: const Text('Hide FAB'),
),
ElevatedButton(
onPressed: Cello.isInitialized
? () => Cello.openWidget()
: null,
child: const Text('Open Widget'),
),
ElevatedButton(
onPressed: Cello.isInitialized
? () => Cello.hideWidget()
: null,
child: const Text('Hide Widget'),
),
ElevatedButton(
onPressed: Cello.isInitialized ? _updateToken : null,
child: const Text('Update Token'),
),
ElevatedButton(
onPressed: Cello.isInitialized ? _changeLanguage : null,
child: const Text('Change Language'),
),
ElevatedButton(
onPressed: Cello.isInitialized ? _setThemeMode : null,
child: const Text('Set Theme Mode'),
),
ElevatedButton(
onPressed: Cello.isInitialized ? _fetchActiveUcc : null,
child: const Text('Get Active UCC'),
),
ElevatedButton(
onPressed: Cello.isInitialized
? _fetchCampaignConfig
: null,
child: const Text('Get Campaign Config'),
),
ElevatedButton(
onPressed: Cello.isInitialized ? _shutdown : null,
child: const Text('Shutdown'),
),
],
),
const SizedBox(height: 24),
_sectionTitle('Latest Configuration'),
Text(
_configuration?.rawResponse?.toString() ?? 'Not initialized',
),
const SizedBox(height: 16),
_sectionTitle('Active UCC'),
Text(
_activeUcc.isEmpty ? 'Not available' : _activeUcc.toString(),
),
const SizedBox(height: 16),
_sectionTitle('Campaign Config'),
Text(
_campaignConfig.isEmpty
? 'Not available'
: _campaignConfig.toString(),
),
const SizedBox(height: 16),
_sectionTitle('Token Events'),
SizedBox(
height: 160,
child: DecoratedBox(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade400),
borderRadius: BorderRadius.circular(8),
),
child: ListView.builder(
itemCount: _logs.length,
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 4,
),
child: Text(_logs[_logs.length - index - 1]),
),
),
),
),
],
),
),
),
);
}
Widget _sectionTitle(String title) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text(
title,
style: Theme.of(
context,
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
),
);
}
Widget _textField(
String label,
TextEditingController controller, {
TextInputType keyboardType = TextInputType.text,
}) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: TextField(
controller: controller,
keyboardType: keyboardType,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: label,
),
),
);
}
}