layou_user_avatar
A customizable Flutter package for user avatar management with Firebase, Riverpod, image optimization, and caching.
Features
- Upload and delete user avatars
- Automatic WebP conversion for optimal file size (25-35% smaller than PNG/JPEG)
- Image resizing with aspect ratio preservation
- Local and memory caching with configurable TTL
- Customizable widgets for display, upload, and deletion
- Riverpod integration for state management
- Firebase Storage integration (with extensible storage provider interface)
- Configurable storage paths
- Progress callbacks and error handling
- Cache busting support
- Native WebP support on Android and iOS
Installation
Add this to your package's pubspec.yaml file:
dependencies:
layou_user_avatar: ^0.1.0
Quick Start
1. Configure the package at app startup
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:layou_user_avatar/layou_user_avatar.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:firebase_auth/firebase_auth.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
ProviderScope(
overrides: [
avatarConfigProvider.overrideWithValue(
AvatarConfig(
storageProvider: FirebaseStorageProvider(FirebaseStorage.instance),
localCacheProvider: HiveCacheProvider(),
identityProvider: FirebaseIdentityProvider(FirebaseAuth.instance),
imageConverter: WebPImageConverter(),
pathBuilder: (userId) => 'avatars/$userId/avatar.webp',
cacheTtl: Duration(hours: 24),
webpQuality: 85,
maxImageSize: 512,
),
),
],
child: MyApp(),
),
);
}
2. Display and edit current user's avatar
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:layou_user_avatar/layou_user_avatar.dart';
class ProfileScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(title: Text('Profile')),
body: Center(
child: AvatarEditor(
size: 120,
onUploadSuccess: (url) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Avatar uploaded!')),
);
},
onUploadError: (error) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Upload failed: $error')),
);
},
onProgress: (progress) {
print('Upload progress: ${(progress * 100).toStringAsFixed(0)}%');
},
),
),
);
}
}
3. Display external user avatar (read-only)
class UserListItem extends ConsumerWidget {
final String userId;
final String userName;
const UserListItem({
required this.userId,
required this.userName,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final avatarAsync = ref.watch(externalUserAvatarProvider(userId));
return ListTile(
leading: avatarAsync.when(
data: (url) => AvatarDisplay(
avatarUrl: url,
userId: userId,
size: 48,
),
loading: () => CircularProgressIndicator(),
error: (err, stack) => Icon(Icons.error),
),
title: Text(userName),
);
}
}
Widgets
AvatarEditor
All-in-one widget combining avatar display, upload, and delete functionality.
AvatarEditor(
size: 120,
showUploadButton: true,
showDeleteButton: true,
onUploadSuccess: (url) => print('Uploaded: $url'),
onUploadError: (error) => print('Error: $error'),
onDeleteSuccess: () => print('Deleted'),
onProgress: (progress) => print('Progress: $progress'),
)
AvatarDisplay
Read-only avatar display with placeholder support.
AvatarDisplay(
avatarUrl: 'https://example.com/avatar.webp',
userId: 'user123',
size: 64,
enableCaching: true,
onError: () => print('Failed to load avatar'),
)
AvatarUploadButton
Standalone upload button with image picker.
AvatarUploadButton(
currentAvatarUrl: currentUrl,
onUploadSuccess: (url) => print('Uploaded: $url'),
onUploadError: (error) => print('Error: $error'),
onProgress: (progress) => print('Progress: $progress'),
showProgress: true,
)
AvatarDeleteButton
Standalone delete button with optional confirmation dialog.
AvatarDeleteButton(
onDeleteSuccess: () => print('Deleted'),
onDeleteError: (error) => print('Error: $error'),
confirmDelete: true,
)
Configuration Options
AvatarConfig
AvatarConfig(
// Required
storageProvider: StorageProvider, // Cloud storage implementation
identityProvider: IdentityProvider, // User identity provider
imageConverter: ImageConverter, // Image conversion implementation
// Optional
localCacheProvider: LocalCacheProvider?, // Local cache (null = no cache)
pathBuilder: String Function(String userId), // Custom path builder
cacheTtl: Duration?, // Cache expiration (null = no expiry)
enableCacheBusting: bool, // Add timestamp to URLs
webpQuality: int, // WebP quality (0-100, default: 80)
maxImageSize: int?, // Max size in pixels (null = no limit)
placeholderAssetPath: String?, // Custom placeholder asset
customLoader: Widget?, // Custom loading widget
)
Extensibility
The package is designed to be storage-agnostic. You can implement custom providers:
Custom Storage Provider
class MyStorageProvider implements StorageProvider {
@override
Future<String> uploadFile(String path, File file, {String? contentType}) {
// Your implementation
}
@override
Future<String> getDownloadUrl(String path) {
// Your implementation
}
@override
Future<void> deleteFile(String path) {
// Your implementation
}
@override
Future<bool> fileExists(String path) {
// Your implementation
}
@override
Stream<double> getUploadProgress(String path) {
// Your implementation
}
}
License
MIT License - see LICENSE file for details.
Libraries
- layou_user_avatar
- A customizable Flutter package for user avatar management.