pichaflow_flutter 0.1.3
pichaflow_flutter: ^0.1.3 copied to clipboard
PichaFlow Flutter integration package. Provides high-performance UI upload widgets with dark mode support, progress indicators, and secure edge handshakes.
import 'package:flutter/material.dart';
import 'package:pichaflow_flutter/pichaflow_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'PichaFlow Flutter Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const PichaFlowExampleScreen(),
);
}
}
class PichaFlowExampleScreen extends StatefulWidget {
const PichaFlowExampleScreen({super.key});
@override
State<PichaFlowExampleScreen> createState() => _PichaFlowExampleScreenState();
}
class _PichaFlowExampleScreenState extends State<PichaFlowExampleScreen> {
// Initialize PichaFlowClient instance
late final PichaFlowClient _client;
final TextEditingController _descriptionController = TextEditingController();
final List<UploadResponse> _uploadedImages = [];
bool _isDeleting = false;
@override
void initState() {
super.initState();
_client = PichaFlowClient(
PichaFlowConfig(
apiKey: 'your_api_key_here',
baseUrl: 'http://localhost:8789',
uploadUrl: 'http://localhost:8789',
fetchUrl: 'http://localhost:8789',
),
);
}
@override
void dispose() {
_descriptionController.dispose();
super.dispose();
}
Future<void> _deleteAsset(String id) async {
setState(() {
_isDeleting = true;
});
try {
final res = await _client.deleteAsset(id);
final bool isSuccess = res['success'] == true;
if (isSuccess) {
setState(() {
_uploadedImages.removeWhere((img) => img.id == id);
});
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Image deleted successfully')),
);
}
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Delete failed: $e')),
);
}
} finally {
if (mounted) {
setState(() {
_isDeleting = false;
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('PichaFlow Flutter Upload Example'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// 1. Optional Description Input Field
TextField(
controller: _descriptionController,
decoration: const InputDecoration(
labelText: 'Image Description (Alt Text)',
hintText: 'Enter alt text for your uploaded image',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
// 2. PichaFlowUploadWidget Component
Card(
elevation: 2,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: PichaFlowUploadWidget(
client: _client,
multiple: false,
tags: const ['flutter_example'],
directory: 'examples/flutter',
onSuccess: (response) {
setState(() {
_uploadedImages.add(response);
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Upload successful: ${response.id}')),
);
},
onError: (error) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Upload error: $error')),
);
},
),
),
),
const SizedBox(height: 24),
// 3. Uploaded Images List Header
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Uploaded Images (${_uploadedImages.length})',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
if (_isDeleting)
const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
),
],
),
const SizedBox(height: 12),
// 4. Uploaded Images List View
if (_uploadedImages.isEmpty)
const Padding(
padding: EdgeInsets.symmetric(vertical: 24.0),
child: Center(
child: Text(
'No images uploaded yet.',
style: TextStyle(color: Colors.grey),
),
),
)
else
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: _uploadedImages.length,
separatorBuilder: (context, index) => const SizedBox(height: 8),
itemBuilder: (context, index) {
final image = _uploadedImages[index];
return Card(
clipBehavior: Clip.antiAlias,
child: ListTile(
leading: Image.network(
image.url,
width: 50,
height: 50,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) =>
const Icon(Icons.broken_image, size: 50),
),
title: Text(
image.alt.isNotEmpty ? image.alt : 'No description',
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(
'ID: ${image.id}',
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
trailing: IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () => _deleteAsset(image.id),
tooltip: 'Delete image',
),
),
);
},
),
],
),
),
);
}
}