Handling of images stored in Firebase storage. Bundled with an extension of Firestore Model to also handle photo
fields.
The FirebasePhoto
references both a thumbnail and a regular image. When a regular image decodes, the image provider
first attempts to decode the large version on devices with high dpi.
Firebase Image references assume the image is stored in your default Firebase storage bucket, in path equal to the FirestoreModel
reference path.
For example a document of the user model below would be referenced in Firestore at users/dbf523y8, so the photo in Storage would be at users/dbf523y8/photo/0/198673a755/reg.
photo/0 points to photo of key 0. Photos have string keys to allow for multiple photos while still easily preserving their positions.
SwitchingFirebaseImage
extends SwitchingImage
to first load a thumbnail, if it's already cached and not the regular photo, then load the regular photo. This allows seamless transitions from list tiles to full pages.
Check models in the Flutter Firestore example app.
@JsonSerializable()
class User extends _User with _$User {
static final collection = FirebaseFirestore.instance.collection('users');
/// Create [User] from json
static User fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
/// Convert [User] to json
Map<String, dynamic> toJson() => _$UserToJson(this);
}
/// [FirestorePhotoModel] observes the fields of [FirestorePhotoImpl], see next example.
abstract class _User extends FirestorePhotoModel<User> with Store {
@o @JsonKey() String name;
@o @JsonKey() String description;
@o @JsonKey(defaultValue: 0) int views = 0;
@o @JsonKey(defaultValue: 0) int followers = 0;
@override @a
void onSnapshot(User x) {
super.onSnapshot(x);
name = x.name;
description = x.description;
views = x.views;
followers = x.followers;
}
}
If you don't intend to decorate the fields as observable or json serializable, just adding FirestorePhotoImpl as a mixin is enough.
Else extend Mixin fields and decorate them like so:
@o @override @JsonKey(defaultValue: <String, FirebasePhoto>{}) @PhotoMapC() Map<String, FirebasePhoto> photos = const <String, FirebasePhoto>{};
@c @override Map<String, FirebasePhotoReference> get media => super.media;
@c @override FirebasePhotoReference get photo => super.photo;
@override @a
void onSnapshot(x) {
photos = x.photos;
}