MIF_E31222656/lib/screens/admin/image_upload_test.dart

297 lines
8.4 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart' as path;
import 'package:supabase_flutter/supabase_flutter.dart';
class ImageUploadTest extends StatefulWidget {
const ImageUploadTest({super.key});
@override
State<ImageUploadTest> createState() => _ImageUploadTestState();
}
class _ImageUploadTestState extends State<ImageUploadTest> {
final _supabase = Supabase.instance.client;
String? _selectedImagePath;
String? _uploadedImageUrl;
bool _isLoading = false;
String _status = '';
List<String> _buckets = [];
String _selectedBucket = '';
@override
void initState() {
super.initState();
_loadBuckets();
}
Future<void> _loadBuckets() async {
setState(() {
_isLoading = true;
_status = 'Loading buckets...';
});
try {
final buckets = await _supabase.storage.listBuckets();
final bucketNames = buckets.map((b) => b.name).toList();
setState(() {
_buckets = bucketNames;
if (bucketNames.isNotEmpty) {
_selectedBucket = bucketNames.first;
}
_status =
'Found ${bucketNames.length} buckets: ${bucketNames.join(', ')}';
});
} catch (e) {
setState(() {
_status = 'Error loading buckets: $e';
});
} finally {
setState(() {
_isLoading = false;
});
}
}
Future<void> _pickImage() async {
try {
setState(() {
_status = 'Selecting image...';
});
final ImagePicker picker = ImagePicker();
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
if (image != null) {
setState(() {
_selectedImagePath = image.path;
_status = 'Image selected: ${path.basename(image.path)}';
});
} else {
setState(() {
_status = 'Image selection canceled';
});
}
} catch (e) {
setState(() {
_status = 'Error picking image: $e';
});
}
}
Future<void> _uploadImage() async {
if (_selectedImagePath == null || _selectedBucket.isEmpty) {
setState(() {
_status = 'No image selected or bucket chosen';
});
return;
}
setState(() {
_isLoading = true;
_status = 'Uploading image to $_selectedBucket...';
});
try {
final file = File(_selectedImagePath!);
if (!await file.exists()) {
setState(() {
_status = 'File does not exist: $_selectedImagePath';
_isLoading = false;
});
return;
}
final fileExtension = path.extension(file.path).toLowerCase();
final fileName =
'test_${DateTime.now().millisecondsSinceEpoch}$fileExtension';
// Read file as bytes
final bytes = await file.readAsBytes();
// Upload to selected bucket
await _supabase.storage
.from(_selectedBucket)
.uploadBinary(
fileName,
bytes,
fileOptions: const FileOptions(contentType: 'image/jpeg'),
);
// Get public URL
final imageUrl = _supabase.storage
.from(_selectedBucket)
.getPublicUrl(fileName);
setState(() {
_uploadedImageUrl = imageUrl;
_status = 'Upload successful to $_selectedBucket bucket';
});
} catch (e) {
setState(() {
_status = 'Upload error: $e';
});
} finally {
setState(() {
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Image Upload Test'),
actions: [
IconButton(icon: const Icon(Icons.refresh), onPressed: _loadBuckets),
],
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Status
Container(
width: double.infinity,
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.grey.shade200,
borderRadius: BorderRadius.circular(8),
),
child: Text(_status),
),
const SizedBox(height: 20),
// Bucket selection
Text(
'Select Bucket:',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
if (_buckets.isEmpty)
const Text('No buckets available')
else
DropdownButton<String>(
value: _selectedBucket,
isExpanded: true,
items:
_buckets.map((bucket) {
return DropdownMenuItem<String>(
value: bucket,
child: Text(bucket),
);
}).toList(),
onChanged: (value) {
if (value != null) {
setState(() {
_selectedBucket = value;
});
}
},
),
const SizedBox(height: 20),
// Image selection
Text('Image:', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: Text(
_selectedImagePath != null
? 'Selected: ${path.basename(_selectedImagePath!)}'
: 'No image selected',
),
),
ElevatedButton.icon(
onPressed: _pickImage,
icon: const Icon(Icons.image),
label: const Text('Select Image'),
),
],
),
if (_selectedImagePath != null) ...[
const SizedBox(height: 16),
const Text('Selected Image Preview:'),
const SizedBox(height: 8),
Container(
height: 150,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(8),
),
child:
kIsWeb
? Image.network(_selectedImagePath!)
: Image.file(File(_selectedImagePath!)),
),
],
const SizedBox(height: 20),
// Upload button
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed:
_isLoading || _selectedImagePath == null
? null
: _uploadImage,
icon:
_isLoading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.cloud_upload),
label: Text(_isLoading ? 'Uploading...' : 'Upload Image'),
),
),
const SizedBox(height: 20),
// Result
if (_uploadedImageUrl != null) ...[
Text(
'Uploaded Image:',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
SelectableText('URL: $_uploadedImageUrl'),
const SizedBox(height: 8),
Container(
width: double.infinity,
height: 200,
decoration: BoxDecoration(
color: Colors.grey.shade200,
borderRadius: BorderRadius.circular(8),
),
child: Image.network(
_uploadedImageUrl!,
fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) {
return Center(child: Text('Error loading image: $error'));
},
),
),
],
],
),
),
);
}
// Helper method to check if running on the web
static bool get kIsWeb {
try {
return identical(0, 0.0);
} catch (e) {
return false;
}
}
}