storifyme_snaps 1.3.3
storifyme_snaps: ^1.3.3 copied to clipboard
StorifyMe Snaps Editor for Flutter that enables UGC content creation right from your mobile app.
example/lib/main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:storifyme_snaps/params.dart';
import 'package:storifyme_snaps/storifyme_snaps_event_listener.dart';
import 'package:storifyme_snaps/storifyme_snaps_plugin.dart';
void main() {
runApp(const SnapsExampleApp());
}
class SnapsExampleApp extends StatelessWidget {
const SnapsExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'StorifyMe Snaps Demo',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF2563EB),
brightness: Brightness.light,
),
scaffoldBackgroundColor: const Color(0xFFF8FAFC),
),
home: const SnapsDemoPage(),
);
}
}
class SnapsDemoPage extends StatefulWidget {
const SnapsDemoPage({super.key});
@override
State<SnapsDemoPage> createState() => _SnapsDemoPageState();
}
class _SnapsDemoPageState extends State<SnapsDemoPage>
with StorifyMeSnapsEventListener {
final _storifyMeSnapsPlugin = StorifyMeSnapsPlugin();
static const _userId = 'storifyme-dev-tester';
static const _accountId = 'xxxxxxx';
static const _apiKey = 'xxxxxxx';
static const _env = 'EU';
String _status = 'Idle';
int? _lastSavedSnapId;
@override
void initState() {
super.initState();
_initPlatformState();
}
Future<void> _initPlatformState() async {
try {
await _storifyMeSnapsPlugin.initPlugin({
Params.API_KEY_ID: _apiKey,
Params.ACCOUNT_ID_KEY: _accountId,
Params.ENVIRONMENT_KEY: _env,
});
_storifyMeSnapsPlugin.setSnapsEventListener(this);
setState(() => _status = 'SDK initialized');
} on PlatformException catch (e) {
setState(() => _status = 'Init failed: ${e.message}');
}
}
void _openNewSnap() {
setState(() => _status = 'Opening new Snap editor…');
_storifyMeSnapsPlugin.openSnaps(
userId: _userId,
snapName: 'New snap from Flutter demo',
tags: const ['flutter', 'demo'],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('StorifyMe Snaps Demo'),
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Colors.white,
elevation: 0,
),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_AccountCard(
accountId: _accountId,
env: _env,
userId: _userId,
status: _status,
lastSavedSnapId: _lastSavedSnapId,
),
const SizedBox(height: 24),
const _SectionHeader(
title: 'Create',
subtitle: 'Open a fresh editor and create a new Snap.',
),
const SizedBox(height: 12),
_PrimaryActionButton(
label: 'Open Snaps Editor',
icon: Icons.add_circle_outline,
onPressed: _openNewSnap,
)
],
),
),
),
);
}
// ---- Snaps SDK event callbacks ----
@override
void onEditorClosed() {
debugPrint('SnapsEditor: onEditorClosed');
setState(() => _status = 'Editor closed');
}
@override
void onEditorLoadFailed() {
debugPrint('SnapsEditor: onEditorLoadFailed');
setState(() => _status = 'Editor failed to load');
}
@override
void onEditorLoaded() {
debugPrint('SnapsEditor: onEditorLoaded');
setState(() => _status = 'Editor loaded');
}
@override
void onSnapSaved(int snapId) {
debugPrint('SnapsEditor: onSnapSaved - $snapId');
setState(() {
_lastSavedSnapId = snapId;
_status = 'Snap saved: #$snapId';
});
}
}
class _AccountCard extends StatelessWidget {
const _AccountCard({
required this.accountId,
required this.env,
required this.userId,
required this.status,
required this.lastSavedSnapId,
});
final String accountId;
final String env;
final String userId;
final String status;
final int? lastSavedSnapId;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xFFE2E8F0)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: env == 'DEV'
? const Color(0xFFFEF3C7)
: const Color(0xFFDCFCE7),
borderRadius: BorderRadius.circular(6),
),
child: Text(
env,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w700,
color: env == 'DEV'
? const Color(0xFFB45309)
: const Color(0xFF166534),
),
),
),
const SizedBox(width: 8),
Expanded(
child: Text(
accountId,
style: const TextStyle(
fontFamily: 'monospace',
fontSize: 12,
color: Color(0xFF475569),
),
overflow: TextOverflow.ellipsis,
),
),
],
),
const SizedBox(height: 12),
_MetaRow(label: 'User', value: userId),
const SizedBox(height: 4),
_MetaRow(label: 'Status', value: status),
if (lastSavedSnapId != null) ...[
const SizedBox(height: 4),
_MetaRow(label: 'Last saved', value: '#$lastSavedSnapId'),
],
],
),
);
}
}
class _MetaRow extends StatelessWidget {
const _MetaRow({required this.label, required this.value});
final String label;
final String value;
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 72,
child: Text(
label,
style: const TextStyle(
fontSize: 12,
color: Color(0xFF94A3B8),
fontWeight: FontWeight.w500,
),
),
),
Expanded(
child: Text(
value,
style: const TextStyle(
fontSize: 13,
color: Color(0xFF0F172A),
),
),
),
],
);
}
}
class _SectionHeader extends StatelessWidget {
const _SectionHeader({required this.title, required this.subtitle});
final String title;
final String subtitle;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w700,
color: Color(0xFF0F172A),
),
),
const SizedBox(height: 4),
Text(
subtitle,
style: const TextStyle(
fontSize: 13,
color: Color(0xFF64748B),
height: 1.4,
),
),
],
);
}
}
class _PrimaryActionButton extends StatelessWidget {
const _PrimaryActionButton({
required this.label,
required this.icon,
required this.onPressed,
});
final String label;
final IconData icon;
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 52,
child: FilledButton.icon(
onPressed: onPressed,
style: FilledButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.primary,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
icon: Icon(icon, size: 20),
label: Text(
label,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
),
),
),
);
}
}