diff --git a/lib/app/home/views/home_screen.dart b/lib/app/home/views/home_screen.dart index 6909905..74705ef 100644 --- a/lib/app/home/views/home_screen.dart +++ b/lib/app/home/views/home_screen.dart @@ -1,3 +1,4 @@ +import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -108,7 +109,8 @@ class _HomeScreenState extends ConsumerState { Widget buildPetListTile(PetModel pet) { return ListTile( leading: CircleAvatar( - child: Icon(Icons.pets, semanticLabel: 'Pet Icon', color: Colors.white), + backgroundImage: pet.imageUrl != null ? FileImage(File(pet.imageUrl!)) : null, + child: pet.imageUrl == null ? const Icon(Icons.pets, semanticLabel: 'Pet Icon', color: Colors.white) : null, ), title: Text(pet.name), subtitle: Text(getPetSubTitle(pet)), diff --git a/lib/app/pet/controller/all_pets_controller.dart b/lib/app/pet/controller/all_pets_controller.dart index 744f9a4..82e52e3 100644 --- a/lib/app/pet/controller/all_pets_controller.dart +++ b/lib/app/pet/controller/all_pets_controller.dart @@ -18,8 +18,6 @@ class AllPetsController extends _$AllPetsController { ); } - - Future save(PetModel pet) async { if (pet.petId == null) { final newPet = await _databaseService.createPet( @@ -41,6 +39,7 @@ class AllPetsController extends _$AllPetsController { pet.microchipNumber, pet.microchipCompany, pet.microchipNotes, + pet.imageUrl, ); return newPet == null ? null : PetMapper.mapToModel(newPet); @@ -66,6 +65,7 @@ class AllPetsController extends _$AllPetsController { pet.microchipNumber, pet.microchipCompany, pet.microchipNotes, + pet.imageUrl, ); return pet; } diff --git a/lib/app/pet/controller/all_pets_controller.g.dart b/lib/app/pet/controller/all_pets_controller.g.dart index 92da593..a7b937f 100644 --- a/lib/app/pet/controller/all_pets_controller.g.dart +++ b/lib/app/pet/controller/all_pets_controller.g.dart @@ -6,7 +6,7 @@ part of 'all_pets_controller.dart'; // RiverpodGenerator // ************************************************************************** -String _$allPetsControllerHash() => r'1c5bcc82fa2df75a5814fd264da8f4296d27a7db'; +String _$allPetsControllerHash() => r'51164797a5b90ec654da82efb14c176746bb9c20'; /// See also [AllPetsController]. @ProviderFor(AllPetsController) diff --git a/lib/app/pet/models/pet_model.dart b/lib/app/pet/models/pet_model.dart index cb5ccb8..144e2d9 100644 --- a/lib/app/pet/models/pet_model.dart +++ b/lib/app/pet/models/pet_model.dart @@ -32,6 +32,7 @@ abstract class PetModel with _$PetModel { String? microchipNotes, String? microchipNumber, String? microchipCompany, + String? imageUrl, }) = _PetModel; factory PetModel.fromJson(Map json) => diff --git a/lib/app/pet/models/pet_model.freezed.dart b/lib/app/pet/models/pet_model.freezed.dart index 80c2b05..b90aa6f 100644 --- a/lib/app/pet/models/pet_model.freezed.dart +++ b/lib/app/pet/models/pet_model.freezed.dart @@ -16,7 +16,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$PetModel implements DiagnosticableTreeMixin { - int? get petId; String get name; String get breed; String get colour; PetSex get petSex; DateTime? get dob; bool get dobEstimate; String? get diet; String? get notes; String? get history; bool get isNeutered; DateTime? get neuterDate; PetStatus get status; DateTime get statusDate; int get speciesId; bool get isMicrochipped; DateTime? get microchipDate; String? get microchipNotes; String? get microchipNumber; String? get microchipCompany; + int? get petId; String get name; String get breed; String get colour; PetSex get petSex; DateTime? get dob; bool get dobEstimate; String? get diet; String? get notes; String? get history; bool get isNeutered; DateTime? get neuterDate; PetStatus get status; DateTime get statusDate; int get speciesId; bool get isMicrochipped; DateTime? get microchipDate; String? get microchipNotes; String? get microchipNumber; String? get microchipCompany; String? get imageUrl; /// Create a copy of PetModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -30,21 +30,21 @@ $PetModelCopyWith get copyWith => _$PetModelCopyWithImpl(thi void debugFillProperties(DiagnosticPropertiesBuilder properties) { properties ..add(DiagnosticsProperty('type', 'PetModel')) - ..add(DiagnosticsProperty('petId', petId))..add(DiagnosticsProperty('name', name))..add(DiagnosticsProperty('breed', breed))..add(DiagnosticsProperty('colour', colour))..add(DiagnosticsProperty('petSex', petSex))..add(DiagnosticsProperty('dob', dob))..add(DiagnosticsProperty('dobEstimate', dobEstimate))..add(DiagnosticsProperty('diet', diet))..add(DiagnosticsProperty('notes', notes))..add(DiagnosticsProperty('history', history))..add(DiagnosticsProperty('isNeutered', isNeutered))..add(DiagnosticsProperty('neuterDate', neuterDate))..add(DiagnosticsProperty('status', status))..add(DiagnosticsProperty('statusDate', statusDate))..add(DiagnosticsProperty('speciesId', speciesId))..add(DiagnosticsProperty('isMicrochipped', isMicrochipped))..add(DiagnosticsProperty('microchipDate', microchipDate))..add(DiagnosticsProperty('microchipNotes', microchipNotes))..add(DiagnosticsProperty('microchipNumber', microchipNumber))..add(DiagnosticsProperty('microchipCompany', microchipCompany)); + ..add(DiagnosticsProperty('petId', petId))..add(DiagnosticsProperty('name', name))..add(DiagnosticsProperty('breed', breed))..add(DiagnosticsProperty('colour', colour))..add(DiagnosticsProperty('petSex', petSex))..add(DiagnosticsProperty('dob', dob))..add(DiagnosticsProperty('dobEstimate', dobEstimate))..add(DiagnosticsProperty('diet', diet))..add(DiagnosticsProperty('notes', notes))..add(DiagnosticsProperty('history', history))..add(DiagnosticsProperty('isNeutered', isNeutered))..add(DiagnosticsProperty('neuterDate', neuterDate))..add(DiagnosticsProperty('status', status))..add(DiagnosticsProperty('statusDate', statusDate))..add(DiagnosticsProperty('speciesId', speciesId))..add(DiagnosticsProperty('isMicrochipped', isMicrochipped))..add(DiagnosticsProperty('microchipDate', microchipDate))..add(DiagnosticsProperty('microchipNotes', microchipNotes))..add(DiagnosticsProperty('microchipNumber', microchipNumber))..add(DiagnosticsProperty('microchipCompany', microchipCompany))..add(DiagnosticsProperty('imageUrl', imageUrl)); } @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is PetModel&&(identical(other.petId, petId) || other.petId == petId)&&(identical(other.name, name) || other.name == name)&&(identical(other.breed, breed) || other.breed == breed)&&(identical(other.colour, colour) || other.colour == colour)&&(identical(other.petSex, petSex) || other.petSex == petSex)&&(identical(other.dob, dob) || other.dob == dob)&&(identical(other.dobEstimate, dobEstimate) || other.dobEstimate == dobEstimate)&&(identical(other.diet, diet) || other.diet == diet)&&(identical(other.notes, notes) || other.notes == notes)&&(identical(other.history, history) || other.history == history)&&(identical(other.isNeutered, isNeutered) || other.isNeutered == isNeutered)&&(identical(other.neuterDate, neuterDate) || other.neuterDate == neuterDate)&&(identical(other.status, status) || other.status == status)&&(identical(other.statusDate, statusDate) || other.statusDate == statusDate)&&(identical(other.speciesId, speciesId) || other.speciesId == speciesId)&&(identical(other.isMicrochipped, isMicrochipped) || other.isMicrochipped == isMicrochipped)&&(identical(other.microchipDate, microchipDate) || other.microchipDate == microchipDate)&&(identical(other.microchipNotes, microchipNotes) || other.microchipNotes == microchipNotes)&&(identical(other.microchipNumber, microchipNumber) || other.microchipNumber == microchipNumber)&&(identical(other.microchipCompany, microchipCompany) || other.microchipCompany == microchipCompany)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is PetModel&&(identical(other.petId, petId) || other.petId == petId)&&(identical(other.name, name) || other.name == name)&&(identical(other.breed, breed) || other.breed == breed)&&(identical(other.colour, colour) || other.colour == colour)&&(identical(other.petSex, petSex) || other.petSex == petSex)&&(identical(other.dob, dob) || other.dob == dob)&&(identical(other.dobEstimate, dobEstimate) || other.dobEstimate == dobEstimate)&&(identical(other.diet, diet) || other.diet == diet)&&(identical(other.notes, notes) || other.notes == notes)&&(identical(other.history, history) || other.history == history)&&(identical(other.isNeutered, isNeutered) || other.isNeutered == isNeutered)&&(identical(other.neuterDate, neuterDate) || other.neuterDate == neuterDate)&&(identical(other.status, status) || other.status == status)&&(identical(other.statusDate, statusDate) || other.statusDate == statusDate)&&(identical(other.speciesId, speciesId) || other.speciesId == speciesId)&&(identical(other.isMicrochipped, isMicrochipped) || other.isMicrochipped == isMicrochipped)&&(identical(other.microchipDate, microchipDate) || other.microchipDate == microchipDate)&&(identical(other.microchipNotes, microchipNotes) || other.microchipNotes == microchipNotes)&&(identical(other.microchipNumber, microchipNumber) || other.microchipNumber == microchipNumber)&&(identical(other.microchipCompany, microchipCompany) || other.microchipCompany == microchipCompany)&&(identical(other.imageUrl, imageUrl) || other.imageUrl == imageUrl)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hashAll([runtimeType,petId,name,breed,colour,petSex,dob,dobEstimate,diet,notes,history,isNeutered,neuterDate,status,statusDate,speciesId,isMicrochipped,microchipDate,microchipNotes,microchipNumber,microchipCompany]); +int get hashCode => Object.hashAll([runtimeType,petId,name,breed,colour,petSex,dob,dobEstimate,diet,notes,history,isNeutered,neuterDate,status,statusDate,speciesId,isMicrochipped,microchipDate,microchipNotes,microchipNumber,microchipCompany,imageUrl]); @override String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) { - return 'PetModel(petId: $petId, name: $name, breed: $breed, colour: $colour, petSex: $petSex, dob: $dob, dobEstimate: $dobEstimate, diet: $diet, notes: $notes, history: $history, isNeutered: $isNeutered, neuterDate: $neuterDate, status: $status, statusDate: $statusDate, speciesId: $speciesId, isMicrochipped: $isMicrochipped, microchipDate: $microchipDate, microchipNotes: $microchipNotes, microchipNumber: $microchipNumber, microchipCompany: $microchipCompany)'; + return 'PetModel(petId: $petId, name: $name, breed: $breed, colour: $colour, petSex: $petSex, dob: $dob, dobEstimate: $dobEstimate, diet: $diet, notes: $notes, history: $history, isNeutered: $isNeutered, neuterDate: $neuterDate, status: $status, statusDate: $statusDate, speciesId: $speciesId, isMicrochipped: $isMicrochipped, microchipDate: $microchipDate, microchipNotes: $microchipNotes, microchipNumber: $microchipNumber, microchipCompany: $microchipCompany, imageUrl: $imageUrl)'; } @@ -55,7 +55,7 @@ abstract mixin class $PetModelCopyWith<$Res> { factory $PetModelCopyWith(PetModel value, $Res Function(PetModel) _then) = _$PetModelCopyWithImpl; @useResult $Res call({ - int? petId, String name, String breed, String colour, PetSex petSex, DateTime? dob, bool dobEstimate, String? diet, String? notes, String? history, bool isNeutered, DateTime? neuterDate, PetStatus status, DateTime statusDate, int speciesId, bool isMicrochipped, DateTime? microchipDate, String? microchipNotes, String? microchipNumber, String? microchipCompany + int? petId, String name, String breed, String colour, PetSex petSex, DateTime? dob, bool dobEstimate, String? diet, String? notes, String? history, bool isNeutered, DateTime? neuterDate, PetStatus status, DateTime statusDate, int speciesId, bool isMicrochipped, DateTime? microchipDate, String? microchipNotes, String? microchipNumber, String? microchipCompany, String? imageUrl }); @@ -72,7 +72,7 @@ class _$PetModelCopyWithImpl<$Res> /// Create a copy of PetModel /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? petId = freezed,Object? name = null,Object? breed = null,Object? colour = null,Object? petSex = null,Object? dob = freezed,Object? dobEstimate = null,Object? diet = freezed,Object? notes = freezed,Object? history = freezed,Object? isNeutered = null,Object? neuterDate = freezed,Object? status = null,Object? statusDate = null,Object? speciesId = null,Object? isMicrochipped = null,Object? microchipDate = freezed,Object? microchipNotes = freezed,Object? microchipNumber = freezed,Object? microchipCompany = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? petId = freezed,Object? name = null,Object? breed = null,Object? colour = null,Object? petSex = null,Object? dob = freezed,Object? dobEstimate = null,Object? diet = freezed,Object? notes = freezed,Object? history = freezed,Object? isNeutered = null,Object? neuterDate = freezed,Object? status = null,Object? statusDate = null,Object? speciesId = null,Object? isMicrochipped = null,Object? microchipDate = freezed,Object? microchipNotes = freezed,Object? microchipNumber = freezed,Object? microchipCompany = freezed,Object? imageUrl = freezed,}) { return _then(_self.copyWith( petId: freezed == petId ? _self.petId : petId // ignore: cast_nullable_to_non_nullable as int?,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable @@ -94,6 +94,7 @@ as bool,microchipDate: freezed == microchipDate ? _self.microchipDate : microchi as DateTime?,microchipNotes: freezed == microchipNotes ? _self.microchipNotes : microchipNotes // ignore: cast_nullable_to_non_nullable as String?,microchipNumber: freezed == microchipNumber ? _self.microchipNumber : microchipNumber // ignore: cast_nullable_to_non_nullable as String?,microchipCompany: freezed == microchipCompany ? _self.microchipCompany : microchipCompany // ignore: cast_nullable_to_non_nullable +as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable as String?, )); } @@ -105,7 +106,7 @@ as String?, @JsonSerializable() class _PetModel extends PetModel with DiagnosticableTreeMixin { - const _PetModel({this.petId, required this.name, required this.breed, required this.colour, required this.petSex, this.dob, required this.dobEstimate, this.diet, this.notes, this.history, required this.isNeutered, required this.neuterDate, required this.status, required this.statusDate, required this.speciesId, required this.isMicrochipped, this.microchipDate, this.microchipNotes, this.microchipNumber, this.microchipCompany}): super._(); + const _PetModel({this.petId, required this.name, required this.breed, required this.colour, required this.petSex, this.dob, required this.dobEstimate, this.diet, this.notes, this.history, required this.isNeutered, required this.neuterDate, required this.status, required this.statusDate, required this.speciesId, required this.isMicrochipped, this.microchipDate, this.microchipNotes, this.microchipNumber, this.microchipCompany, this.imageUrl}): super._(); factory _PetModel.fromJson(Map json) => _$PetModelFromJson(json); @override final int? petId; @@ -128,6 +129,7 @@ class _PetModel extends PetModel with DiagnosticableTreeMixin { @override final String? microchipNotes; @override final String? microchipNumber; @override final String? microchipCompany; +@override final String? imageUrl; /// Create a copy of PetModel /// with the given fields replaced by the non-null parameter values. @@ -143,21 +145,21 @@ Map toJson() { void debugFillProperties(DiagnosticPropertiesBuilder properties) { properties ..add(DiagnosticsProperty('type', 'PetModel')) - ..add(DiagnosticsProperty('petId', petId))..add(DiagnosticsProperty('name', name))..add(DiagnosticsProperty('breed', breed))..add(DiagnosticsProperty('colour', colour))..add(DiagnosticsProperty('petSex', petSex))..add(DiagnosticsProperty('dob', dob))..add(DiagnosticsProperty('dobEstimate', dobEstimate))..add(DiagnosticsProperty('diet', diet))..add(DiagnosticsProperty('notes', notes))..add(DiagnosticsProperty('history', history))..add(DiagnosticsProperty('isNeutered', isNeutered))..add(DiagnosticsProperty('neuterDate', neuterDate))..add(DiagnosticsProperty('status', status))..add(DiagnosticsProperty('statusDate', statusDate))..add(DiagnosticsProperty('speciesId', speciesId))..add(DiagnosticsProperty('isMicrochipped', isMicrochipped))..add(DiagnosticsProperty('microchipDate', microchipDate))..add(DiagnosticsProperty('microchipNotes', microchipNotes))..add(DiagnosticsProperty('microchipNumber', microchipNumber))..add(DiagnosticsProperty('microchipCompany', microchipCompany)); + ..add(DiagnosticsProperty('petId', petId))..add(DiagnosticsProperty('name', name))..add(DiagnosticsProperty('breed', breed))..add(DiagnosticsProperty('colour', colour))..add(DiagnosticsProperty('petSex', petSex))..add(DiagnosticsProperty('dob', dob))..add(DiagnosticsProperty('dobEstimate', dobEstimate))..add(DiagnosticsProperty('diet', diet))..add(DiagnosticsProperty('notes', notes))..add(DiagnosticsProperty('history', history))..add(DiagnosticsProperty('isNeutered', isNeutered))..add(DiagnosticsProperty('neuterDate', neuterDate))..add(DiagnosticsProperty('status', status))..add(DiagnosticsProperty('statusDate', statusDate))..add(DiagnosticsProperty('speciesId', speciesId))..add(DiagnosticsProperty('isMicrochipped', isMicrochipped))..add(DiagnosticsProperty('microchipDate', microchipDate))..add(DiagnosticsProperty('microchipNotes', microchipNotes))..add(DiagnosticsProperty('microchipNumber', microchipNumber))..add(DiagnosticsProperty('microchipCompany', microchipCompany))..add(DiagnosticsProperty('imageUrl', imageUrl)); } @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _PetModel&&(identical(other.petId, petId) || other.petId == petId)&&(identical(other.name, name) || other.name == name)&&(identical(other.breed, breed) || other.breed == breed)&&(identical(other.colour, colour) || other.colour == colour)&&(identical(other.petSex, petSex) || other.petSex == petSex)&&(identical(other.dob, dob) || other.dob == dob)&&(identical(other.dobEstimate, dobEstimate) || other.dobEstimate == dobEstimate)&&(identical(other.diet, diet) || other.diet == diet)&&(identical(other.notes, notes) || other.notes == notes)&&(identical(other.history, history) || other.history == history)&&(identical(other.isNeutered, isNeutered) || other.isNeutered == isNeutered)&&(identical(other.neuterDate, neuterDate) || other.neuterDate == neuterDate)&&(identical(other.status, status) || other.status == status)&&(identical(other.statusDate, statusDate) || other.statusDate == statusDate)&&(identical(other.speciesId, speciesId) || other.speciesId == speciesId)&&(identical(other.isMicrochipped, isMicrochipped) || other.isMicrochipped == isMicrochipped)&&(identical(other.microchipDate, microchipDate) || other.microchipDate == microchipDate)&&(identical(other.microchipNotes, microchipNotes) || other.microchipNotes == microchipNotes)&&(identical(other.microchipNumber, microchipNumber) || other.microchipNumber == microchipNumber)&&(identical(other.microchipCompany, microchipCompany) || other.microchipCompany == microchipCompany)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _PetModel&&(identical(other.petId, petId) || other.petId == petId)&&(identical(other.name, name) || other.name == name)&&(identical(other.breed, breed) || other.breed == breed)&&(identical(other.colour, colour) || other.colour == colour)&&(identical(other.petSex, petSex) || other.petSex == petSex)&&(identical(other.dob, dob) || other.dob == dob)&&(identical(other.dobEstimate, dobEstimate) || other.dobEstimate == dobEstimate)&&(identical(other.diet, diet) || other.diet == diet)&&(identical(other.notes, notes) || other.notes == notes)&&(identical(other.history, history) || other.history == history)&&(identical(other.isNeutered, isNeutered) || other.isNeutered == isNeutered)&&(identical(other.neuterDate, neuterDate) || other.neuterDate == neuterDate)&&(identical(other.status, status) || other.status == status)&&(identical(other.statusDate, statusDate) || other.statusDate == statusDate)&&(identical(other.speciesId, speciesId) || other.speciesId == speciesId)&&(identical(other.isMicrochipped, isMicrochipped) || other.isMicrochipped == isMicrochipped)&&(identical(other.microchipDate, microchipDate) || other.microchipDate == microchipDate)&&(identical(other.microchipNotes, microchipNotes) || other.microchipNotes == microchipNotes)&&(identical(other.microchipNumber, microchipNumber) || other.microchipNumber == microchipNumber)&&(identical(other.microchipCompany, microchipCompany) || other.microchipCompany == microchipCompany)&&(identical(other.imageUrl, imageUrl) || other.imageUrl == imageUrl)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hashAll([runtimeType,petId,name,breed,colour,petSex,dob,dobEstimate,diet,notes,history,isNeutered,neuterDate,status,statusDate,speciesId,isMicrochipped,microchipDate,microchipNotes,microchipNumber,microchipCompany]); +int get hashCode => Object.hashAll([runtimeType,petId,name,breed,colour,petSex,dob,dobEstimate,diet,notes,history,isNeutered,neuterDate,status,statusDate,speciesId,isMicrochipped,microchipDate,microchipNotes,microchipNumber,microchipCompany,imageUrl]); @override String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) { - return 'PetModel(petId: $petId, name: $name, breed: $breed, colour: $colour, petSex: $petSex, dob: $dob, dobEstimate: $dobEstimate, diet: $diet, notes: $notes, history: $history, isNeutered: $isNeutered, neuterDate: $neuterDate, status: $status, statusDate: $statusDate, speciesId: $speciesId, isMicrochipped: $isMicrochipped, microchipDate: $microchipDate, microchipNotes: $microchipNotes, microchipNumber: $microchipNumber, microchipCompany: $microchipCompany)'; + return 'PetModel(petId: $petId, name: $name, breed: $breed, colour: $colour, petSex: $petSex, dob: $dob, dobEstimate: $dobEstimate, diet: $diet, notes: $notes, history: $history, isNeutered: $isNeutered, neuterDate: $neuterDate, status: $status, statusDate: $statusDate, speciesId: $speciesId, isMicrochipped: $isMicrochipped, microchipDate: $microchipDate, microchipNotes: $microchipNotes, microchipNumber: $microchipNumber, microchipCompany: $microchipCompany, imageUrl: $imageUrl)'; } @@ -168,7 +170,7 @@ abstract mixin class _$PetModelCopyWith<$Res> implements $PetModelCopyWith<$Res> factory _$PetModelCopyWith(_PetModel value, $Res Function(_PetModel) _then) = __$PetModelCopyWithImpl; @override @useResult $Res call({ - int? petId, String name, String breed, String colour, PetSex petSex, DateTime? dob, bool dobEstimate, String? diet, String? notes, String? history, bool isNeutered, DateTime? neuterDate, PetStatus status, DateTime statusDate, int speciesId, bool isMicrochipped, DateTime? microchipDate, String? microchipNotes, String? microchipNumber, String? microchipCompany + int? petId, String name, String breed, String colour, PetSex petSex, DateTime? dob, bool dobEstimate, String? diet, String? notes, String? history, bool isNeutered, DateTime? neuterDate, PetStatus status, DateTime statusDate, int speciesId, bool isMicrochipped, DateTime? microchipDate, String? microchipNotes, String? microchipNumber, String? microchipCompany, String? imageUrl }); @@ -185,7 +187,7 @@ class __$PetModelCopyWithImpl<$Res> /// Create a copy of PetModel /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? petId = freezed,Object? name = null,Object? breed = null,Object? colour = null,Object? petSex = null,Object? dob = freezed,Object? dobEstimate = null,Object? diet = freezed,Object? notes = freezed,Object? history = freezed,Object? isNeutered = null,Object? neuterDate = freezed,Object? status = null,Object? statusDate = null,Object? speciesId = null,Object? isMicrochipped = null,Object? microchipDate = freezed,Object? microchipNotes = freezed,Object? microchipNumber = freezed,Object? microchipCompany = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? petId = freezed,Object? name = null,Object? breed = null,Object? colour = null,Object? petSex = null,Object? dob = freezed,Object? dobEstimate = null,Object? diet = freezed,Object? notes = freezed,Object? history = freezed,Object? isNeutered = null,Object? neuterDate = freezed,Object? status = null,Object? statusDate = null,Object? speciesId = null,Object? isMicrochipped = null,Object? microchipDate = freezed,Object? microchipNotes = freezed,Object? microchipNumber = freezed,Object? microchipCompany = freezed,Object? imageUrl = freezed,}) { return _then(_PetModel( petId: freezed == petId ? _self.petId : petId // ignore: cast_nullable_to_non_nullable as int?,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable @@ -207,6 +209,7 @@ as bool,microchipDate: freezed == microchipDate ? _self.microchipDate : microchi as DateTime?,microchipNotes: freezed == microchipNotes ? _self.microchipNotes : microchipNotes // ignore: cast_nullable_to_non_nullable as String?,microchipNumber: freezed == microchipNumber ? _self.microchipNumber : microchipNumber // ignore: cast_nullable_to_non_nullable as String?,microchipCompany: freezed == microchipCompany ? _self.microchipCompany : microchipCompany // ignore: cast_nullable_to_non_nullable +as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable as String?, )); } diff --git a/lib/app/pet/models/pet_model.g.dart b/lib/app/pet/models/pet_model.g.dart index 3e5413e..596e918 100644 --- a/lib/app/pet/models/pet_model.g.dart +++ b/lib/app/pet/models/pet_model.g.dart @@ -31,6 +31,7 @@ _PetModel _$PetModelFromJson(Map json) => _PetModel( microchipNotes: json['microchipNotes'] as String?, microchipNumber: json['microchipNumber'] as String?, microchipCompany: json['microchipCompany'] as String?, + imageUrl: json['imageUrl'] as String?, ); Map _$PetModelToJson(_PetModel instance) => { @@ -54,6 +55,7 @@ Map _$PetModelToJson(_PetModel instance) => { 'microchipNotes': instance.microchipNotes, 'microchipNumber': instance.microchipNumber, 'microchipCompany': instance.microchipCompany, + 'imageUrl': instance.imageUrl, }; const _$PetSexEnumMap = { diff --git a/lib/app/pet/views/edit_pet_screen.dart b/lib/app/pet/views/edit_pet_screen.dart index 2da5d5a..962c6af 100644 --- a/lib/app/pet/views/edit_pet_screen.dart +++ b/lib/app/pet/views/edit_pet_screen.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:petjournal/app/pet/controller/all_pets_controller.dart'; import 'package:petjournal/app/pet/views/widgets/pet_sex_dropdown.dart'; @@ -6,6 +8,7 @@ import 'package:petjournal/app/species/views/widgets/species_dropdown.dart'; import 'package:petjournal/data/lookups/species_lookup.dart'; import 'package:petjournal/extensions/material_colors.dart'; import 'package:flutter/material.dart'; +import 'package:petjournal/helpers/image_service.dart'; import 'package:petjournal/widgets/date_field.dart'; import 'package:go_router/go_router.dart'; import 'package:petjournal/route_config.dart'; @@ -71,6 +74,8 @@ class _EditPetScreenState extends ConsumerState { SpeciesModel? _selectedSpecies; // Nullable until selected bool _isMicrochipped = false; DateTime? _microchipDate; + String? _imageUrl; + bool _imageChanged = false; @override void initState() { @@ -95,7 +100,6 @@ class _EditPetScreenState extends ConsumerState { _status = widget.pet?.status ?? PetStatus.active; _selectedSpecies = SpeciesLookup().getSpecies(widget.pet?.speciesId ?? 0); - //) _isMicrochipped = widget.pet?.isMicrochipped ?? false; _microchipDate = widget.pet?.microchipDate; _microchipNotesController = TextEditingController( @@ -107,6 +111,7 @@ class _EditPetScreenState extends ConsumerState { _microchipCompanyController = TextEditingController( text: widget.pet?.microchipCompany ?? '', ); + _imageUrl = widget.pet?.imageUrl; } @override @@ -195,6 +200,45 @@ class _EditPetScreenState extends ConsumerState { child: SingleChildScrollView( child: Column( children: [ + CircleAvatar( + radius: 75, + backgroundImage: _imageUrl != null + ? FileImage(File(_imageUrl!)) + : null, + child: _imageUrl == null + ? const Icon( + Icons.pets, + semanticLabel: 'Pet Icon', + color: Colors.white, + size: 75, + ) + : null, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (_imageUrl == null) + TextButton.icon( + onPressed: _pickImage, + label: Text('Add picture'), + icon: const Icon(Icons.camera_alt), + ), + if (_imageUrl != null) + TextButton.icon( + onPressed: _pickImage, + label: Text('Change'), + icon: const Icon(Icons.edit), + ), + if (_imageUrl != null) + TextButton.icon( + label: Text('Remove'), + icon: const Icon(Icons.delete), + onPressed: _flagImageForRemoving, + ), + ], + ), + const SizedBox(height: 12), + _buildSectionHeader('Basic Information'), TextFormField( key: EditPetScreen.petNameKey, @@ -526,6 +570,19 @@ class _EditPetScreenState extends ConsumerState { } Future _saveData() async { + // If the image has been changed, save the image to the app directory + String? fullImageUrl; + if (_imageChanged) { + if (_imageUrl == null) { + await _removeImage(); + fullImageUrl = null; + } else { + fullImageUrl = await _saveImage(); + } + } else { + fullImageUrl = _imageUrl; + } + // Construct the Pet object final PetModel petData = PetModel( petId: widget.pet?.petId, @@ -562,6 +619,7 @@ class _EditPetScreenState extends ConsumerState { _isMicrochipped && _microchipCompanyController.text.isNotEmpty ? _microchipCompanyController.text : null, + imageUrl: fullImageUrl, ); final controller = ref.read(allPetsControllerProvider.notifier); @@ -666,4 +724,36 @@ class _EditPetScreenState extends ConsumerState { } } } + + Future _pickImage() async { + final imageService = ImageService(); + final image = await imageService.pickImage(); + if (image != null) { + setState(() { + _imageUrl = image.path; + _imageChanged = true; + _unsavedChanges = true; + }); + } + } + + Future _flagImageForRemoving() async { + setState(() { + _imageUrl = null; + _imageChanged = true; + _unsavedChanges = true; + }); + } + + Future _removeImage() async { + if (widget.pet == null || widget.pet!.imageUrl == null) return; + + final imageService = ImageService(); + await imageService.deleteImage(widget.pet!.imageUrl!); + } + + Future _saveImage() async { + final imageService = ImageService(); + return await imageService.saveImage(_imageUrl!); + } } diff --git a/lib/app/pet/views/view_pet_screen.dart b/lib/app/pet/views/view_pet_screen.dart index f3ea9db..f1e235e 100644 --- a/lib/app/pet/views/view_pet_screen.dart +++ b/lib/app/pet/views/view_pet_screen.dart @@ -1,3 +1,4 @@ +import 'dart:io'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:petjournal/app/pet/controller/pet_controller.dart'; @@ -54,21 +55,32 @@ class _ViewPetScreenState extends ConsumerState { }, ), ], - bottom: const TabBar( - tabs: [ - Tab(icon: Icon(Icons.info), text: 'General'), - Tab(icon: Icon(Icons.medical_services), text: 'Health'), - Tab(icon: Icon(Icons.balance), text: 'Weight'), - Tab(icon: Icon(Icons.content_paste), text: 'Journal'), - ], - ), ), - body: TabBarView( + body: Column( children: [ - _buildGeneralInfoTab(pet), - _buildPetMedsAndVaccinationInfoTab(pet), - _buildPetWeightInfoTab(pet), - _buildPetJournalTab(pet), + if (pet.imageUrl != null) + CircleAvatar( + radius: 75, + backgroundImage: FileImage(File(pet.imageUrl!)), + ), + const TabBar( + tabs: [ + Tab(icon: Icon(Icons.info), text: 'General'), + Tab(icon: Icon(Icons.medical_services), text: 'Health'), + Tab(icon: Icon(Icons.balance), text: 'Weight'), + Tab(icon: Icon(Icons.content_paste), text: 'Journal'), + ], + ), + Expanded( + child: TabBarView( + children: [ + _buildGeneralInfoTab(pet), + _buildPetMedsAndVaccinationInfoTab(pet), + _buildPetWeightInfoTab(pet), + _buildPetJournalTab(pet), + ], + ), + ), ], ), floatingActionButton: ExpandableFab( diff --git a/lib/data/database/database_service.dart b/lib/data/database/database_service.dart index bbacc8d..4a665be 100644 --- a/lib/data/database/database_service.dart +++ b/lib/data/database/database_service.dart @@ -105,6 +105,7 @@ class DatabaseService extends _$DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) { return into(pets).insertReturningOrNull( PetsCompanion.insert( @@ -131,6 +132,7 @@ class DatabaseService extends _$DatabaseService { microchipNotes: Value(microchipNotes), microchipNumber: Value(microchipNumber), microchipCompany: Value(microchipCompany), + imageUrl: Value(imageUrl), ), ); } @@ -157,6 +159,7 @@ class DatabaseService extends _$DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) { return (update(pets)..where((p) => p.petId.equals(id))).write( PetsCompanion.insert( @@ -183,6 +186,7 @@ class DatabaseService extends _$DatabaseService { microchipNotes: Value(microchipNotes), microchipNumber: Value(microchipNumber), microchipCompany: Value(microchipCompany), + imageUrl: Value(imageUrl), ), ); } @@ -891,6 +895,7 @@ class DatabaseService extends _$DatabaseService { 'microchip number', 'microchip company', 'microchip notes', + null, ); await createPet( @@ -912,6 +917,7 @@ class DatabaseService extends _$DatabaseService { 'microchip number', 'microchip company', 'microchip notes', + null, ); await createPet( @@ -933,6 +939,7 @@ class DatabaseService extends _$DatabaseService { null, null, null, + null, ); } diff --git a/lib/data/database/database_service.g.dart b/lib/data/database/database_service.g.dart index 53918a9..b5c7070 100644 --- a/lib/data/database/database_service.g.dart +++ b/lib/data/database/database_service.g.dart @@ -493,6 +493,17 @@ class $PetsTable extends Pets with TableInfo<$PetsTable, Pet> { type: DriftSqlType.string, requiredDuringInsert: false, ); + static const VerificationMeta _imageUrlMeta = const VerificationMeta( + 'imageUrl', + ); + @override + late final GeneratedColumn imageUrl = GeneratedColumn( + 'image_url', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); @override List get $columns => [ petId, @@ -515,6 +526,7 @@ class $PetsTable extends Pets with TableInfo<$PetsTable, Pet> { microchipNotes, microchipNumber, microchipCompany, + imageUrl, ]; @override String get aliasedName => _alias ?? actualTableName; @@ -674,6 +686,12 @@ class $PetsTable extends Pets with TableInfo<$PetsTable, Pet> { ), ); } + if (data.containsKey('image_url')) { + context.handle( + _imageUrlMeta, + imageUrl.isAcceptableOrUnknown(data['image_url']!, _imageUrlMeta), + ); + } return context; } @@ -763,6 +781,10 @@ class $PetsTable extends Pets with TableInfo<$PetsTable, Pet> { DriftSqlType.string, data['${effectivePrefix}microchip_company'], ), + imageUrl: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}image_url'], + ), ); } @@ -793,6 +815,7 @@ class Pet extends DataClass implements Insertable { final String? microchipNotes; final String? microchipNumber; final String? microchipCompany; + final String? imageUrl; const Pet({ required this.petId, required this.name, @@ -814,6 +837,7 @@ class Pet extends DataClass implements Insertable { this.microchipNotes, this.microchipNumber, this.microchipCompany, + this.imageUrl, }); @override Map toColumns(bool nullToAbsent) { @@ -858,6 +882,9 @@ class Pet extends DataClass implements Insertable { if (!nullToAbsent || microchipCompany != null) { map['microchip_company'] = Variable(microchipCompany); } + if (!nullToAbsent || imageUrl != null) { + map['image_url'] = Variable(imageUrl); + } return map; } @@ -899,6 +926,9 @@ class Pet extends DataClass implements Insertable { microchipCompany: microchipCompany == null && nullToAbsent ? const Value.absent() : Value(microchipCompany), + imageUrl: imageUrl == null && nullToAbsent + ? const Value.absent() + : Value(imageUrl), ); } @@ -928,6 +958,7 @@ class Pet extends DataClass implements Insertable { microchipNotes: serializer.fromJson(json['microchipNotes']), microchipNumber: serializer.fromJson(json['microchipNumber']), microchipCompany: serializer.fromJson(json['microchipCompany']), + imageUrl: serializer.fromJson(json['imageUrl']), ); } @override @@ -954,6 +985,7 @@ class Pet extends DataClass implements Insertable { 'microchipNotes': serializer.toJson(microchipNotes), 'microchipNumber': serializer.toJson(microchipNumber), 'microchipCompany': serializer.toJson(microchipCompany), + 'imageUrl': serializer.toJson(imageUrl), }; } @@ -978,6 +1010,7 @@ class Pet extends DataClass implements Insertable { Value microchipNotes = const Value.absent(), Value microchipNumber = const Value.absent(), Value microchipCompany = const Value.absent(), + Value imageUrl = const Value.absent(), }) => Pet( petId: petId ?? this.petId, name: name ?? this.name, @@ -1009,6 +1042,7 @@ class Pet extends DataClass implements Insertable { microchipCompany: microchipCompany.present ? microchipCompany.value : this.microchipCompany, + imageUrl: imageUrl.present ? imageUrl.value : this.imageUrl, ); Pet copyWithCompanion(PetsCompanion data) { return Pet( @@ -1050,6 +1084,7 @@ class Pet extends DataClass implements Insertable { microchipCompany: data.microchipCompany.present ? data.microchipCompany.value : this.microchipCompany, + imageUrl: data.imageUrl.present ? data.imageUrl.value : this.imageUrl, ); } @@ -1075,13 +1110,14 @@ class Pet extends DataClass implements Insertable { ..write('microchipDate: $microchipDate, ') ..write('microchipNotes: $microchipNotes, ') ..write('microchipNumber: $microchipNumber, ') - ..write('microchipCompany: $microchipCompany') + ..write('microchipCompany: $microchipCompany, ') + ..write('imageUrl: $imageUrl') ..write(')')) .toString(); } @override - int get hashCode => Object.hash( + int get hashCode => Object.hashAll([ petId, name, speciesId, @@ -1102,7 +1138,8 @@ class Pet extends DataClass implements Insertable { microchipNotes, microchipNumber, microchipCompany, - ); + imageUrl, + ]); @override bool operator ==(Object other) => identical(this, other) || @@ -1126,7 +1163,8 @@ class Pet extends DataClass implements Insertable { other.microchipDate == this.microchipDate && other.microchipNotes == this.microchipNotes && other.microchipNumber == this.microchipNumber && - other.microchipCompany == this.microchipCompany); + other.microchipCompany == this.microchipCompany && + other.imageUrl == this.imageUrl); } class PetsCompanion extends UpdateCompanion { @@ -1150,6 +1188,7 @@ class PetsCompanion extends UpdateCompanion { final Value microchipNotes; final Value microchipNumber; final Value microchipCompany; + final Value imageUrl; const PetsCompanion({ this.petId = const Value.absent(), this.name = const Value.absent(), @@ -1171,6 +1210,7 @@ class PetsCompanion extends UpdateCompanion { this.microchipNotes = const Value.absent(), this.microchipNumber = const Value.absent(), this.microchipCompany = const Value.absent(), + this.imageUrl = const Value.absent(), }); PetsCompanion.insert({ this.petId = const Value.absent(), @@ -1193,6 +1233,7 @@ class PetsCompanion extends UpdateCompanion { this.microchipNotes = const Value.absent(), this.microchipNumber = const Value.absent(), this.microchipCompany = const Value.absent(), + this.imageUrl = const Value.absent(), }) : name = Value(name), speciesId = Value(speciesId), breed = Value(breed), @@ -1218,6 +1259,7 @@ class PetsCompanion extends UpdateCompanion { Expression? microchipNotes, Expression? microchipNumber, Expression? microchipCompany, + Expression? imageUrl, }) { return RawValuesInsertable({ if (petId != null) 'pet_id': petId, @@ -1240,6 +1282,7 @@ class PetsCompanion extends UpdateCompanion { if (microchipNotes != null) 'microchip_notes': microchipNotes, if (microchipNumber != null) 'microchip_number': microchipNumber, if (microchipCompany != null) 'microchip_company': microchipCompany, + if (imageUrl != null) 'image_url': imageUrl, }); } @@ -1264,6 +1307,7 @@ class PetsCompanion extends UpdateCompanion { Value? microchipNotes, Value? microchipNumber, Value? microchipCompany, + Value? imageUrl, }) { return PetsCompanion( petId: petId ?? this.petId, @@ -1286,6 +1330,7 @@ class PetsCompanion extends UpdateCompanion { microchipNotes: microchipNotes ?? this.microchipNotes, microchipNumber: microchipNumber ?? this.microchipNumber, microchipCompany: microchipCompany ?? this.microchipCompany, + imageUrl: imageUrl ?? this.imageUrl, ); } @@ -1352,6 +1397,9 @@ class PetsCompanion extends UpdateCompanion { if (microchipCompany.present) { map['microchip_company'] = Variable(microchipCompany.value); } + if (imageUrl.present) { + map['image_url'] = Variable(imageUrl.value); + } return map; } @@ -1377,7 +1425,8 @@ class PetsCompanion extends UpdateCompanion { ..write('microchipDate: $microchipDate, ') ..write('microchipNotes: $microchipNotes, ') ..write('microchipNumber: $microchipNumber, ') - ..write('microchipCompany: $microchipCompany') + ..write('microchipCompany: $microchipCompany, ') + ..write('imageUrl: $imageUrl') ..write(')')) .toString(); } @@ -4554,6 +4603,7 @@ typedef $$PetsTableCreateCompanionBuilder = Value microchipNotes, Value microchipNumber, Value microchipCompany, + Value imageUrl, }); typedef $$PetsTableUpdateCompanionBuilder = PetsCompanion Function({ @@ -4577,6 +4627,7 @@ typedef $$PetsTableUpdateCompanionBuilder = Value microchipNotes, Value microchipNumber, Value microchipCompany, + Value imageUrl, }); final class $$PetsTableReferences @@ -4789,6 +4840,11 @@ class $$PetsTableFilterComposer builder: (column) => ColumnFilters(column), ); + ColumnFilters get imageUrl => $composableBuilder( + column: $table.imageUrl, + builder: (column) => ColumnFilters(column), + ); + $$SpeciesTypesTableFilterComposer get speciesId { final $$SpeciesTypesTableFilterComposer composer = $composerBuilder( composer: this, @@ -5017,6 +5073,11 @@ class $$PetsTableOrderingComposer builder: (column) => ColumnOrderings(column), ); + ColumnOrderings get imageUrl => $composableBuilder( + column: $table.imageUrl, + builder: (column) => ColumnOrderings(column), + ); + $$SpeciesTypesTableOrderingComposer get speciesId { final $$SpeciesTypesTableOrderingComposer composer = $composerBuilder( composer: this, @@ -5125,6 +5186,9 @@ class $$PetsTableAnnotationComposer builder: (column) => column, ); + GeneratedColumn get imageUrl => + $composableBuilder(column: $table.imageUrl, builder: (column) => column); + $$SpeciesTypesTableAnnotationComposer get speciesId { final $$SpeciesTypesTableAnnotationComposer composer = $composerBuilder( composer: this, @@ -5304,6 +5368,7 @@ class $$PetsTableTableManager Value microchipNotes = const Value.absent(), Value microchipNumber = const Value.absent(), Value microchipCompany = const Value.absent(), + Value imageUrl = const Value.absent(), }) => PetsCompanion( petId: petId, name: name, @@ -5325,6 +5390,7 @@ class $$PetsTableTableManager microchipNotes: microchipNotes, microchipNumber: microchipNumber, microchipCompany: microchipCompany, + imageUrl: imageUrl, ), createCompanionCallback: ({ @@ -5348,6 +5414,7 @@ class $$PetsTableTableManager Value microchipNotes = const Value.absent(), Value microchipNumber = const Value.absent(), Value microchipCompany = const Value.absent(), + Value imageUrl = const Value.absent(), }) => PetsCompanion.insert( petId: petId, name: name, @@ -5369,6 +5436,7 @@ class $$PetsTableTableManager microchipNotes: microchipNotes, microchipNumber: microchipNumber, microchipCompany: microchipCompany, + imageUrl: imageUrl, ), withReferenceMapper: (p0) => p0 .map( diff --git a/lib/data/database/tables/pet.dart b/lib/data/database/tables/pet.dart index 3a06a53..370138d 100644 --- a/lib/data/database/tables/pet.dart +++ b/lib/data/database/tables/pet.dart @@ -38,4 +38,5 @@ class Pets extends Table { TextColumn get microchipNotes => text().nullable()(); TextColumn get microchipNumber => text().nullable()(); TextColumn get microchipCompany => text().nullable()(); + TextColumn get imageUrl => text().nullable()(); } diff --git a/lib/data/mapper/pet_mapper.dart b/lib/data/mapper/pet_mapper.dart index 4513eea..8ca19ce 100644 --- a/lib/data/mapper/pet_mapper.dart +++ b/lib/data/mapper/pet_mapper.dart @@ -26,6 +26,7 @@ class PetMapper { microchipNotes: pet.microchipNotes, microchipNumber: pet.microchipNumber, microchipCompany: pet.microchipCompany, + imageUrl: pet.imageUrl, ); } diff --git a/lib/helpers/image_service.dart b/lib/helpers/image_service.dart new file mode 100644 index 0000000..ed3ccc4 --- /dev/null +++ b/lib/helpers/image_service.dart @@ -0,0 +1,43 @@ +import 'dart:io'; +import 'package:image_picker/image_picker.dart'; +import 'package:path_provider/path_provider.dart'; + +/// Service to help manage image selection +class ImageService { + final ImagePicker _picker = ImagePicker(); + + Future pickImage() async { + final XFile? pickedFile = await _picker.pickImage( + source: ImageSource.gallery, + ); + + if (pickedFile != null) { + return File(pickedFile.path); + } + + return null; + } + + Future saveImage(String imagePath) async { + final File imageFile = File(imagePath); + if (!(await imageFile.exists())) { + return ''; + } + + final Directory appDir = await getApplicationDocumentsDirectory(); + final String fileName = imageFile.path.split('/').last; + final String savedImagePath = + '${appDir.path}/${DateTime.now().toIso8601String()}_$fileName'; + await imageFile.copy(savedImagePath); + + return savedImagePath; + } + + Future deleteImage(String imagePath) async { + final File imageFile = File(imagePath); + + if (await imageFile.exists()) { + await imageFile.delete(); + } + } +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 4c0025f..9f99dda 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,10 +6,14 @@ #include "generated_plugin_registrant.h" +#include #include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index ad279a8..3ff88a3 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux sqlite3_flutter_libs url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 89a0e38..6eb4aa2 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,12 +5,14 @@ import FlutterMacOS import Foundation +import file_selector_macos import package_info_plus import path_provider_foundation import sqlite3_flutter_libs import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) diff --git a/pubspec.lock b/pubspec.lock index dcc73a0..830620c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -201,6 +201,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.14.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: transitive description: @@ -313,6 +321,38 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "8c9250b2bd2d8d4268e39c82543bacbaca0fda7d29e0728c3c4bbb7c820fd711" + url: "https://pub.dev" + source: hosted + version: "0.9.4+3" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" + url: "https://pub.dev" + source: hosted + version: "0.9.3+4" fixnum: dependency: transitive description: @@ -350,6 +390,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.7+1" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e + url: "https://pub.dev" + source: hosted + version: "2.0.28" flutter_riverpod: dependency: "direct main" description: @@ -448,6 +496,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "6fae381e6af2bbe0365a5e4ce1db3959462fa0c4d234facf070746024bb80c8d" + url: "https://pub.dev" + source: hosted + version: "0.8.12+24" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100" + url: "https://pub.dev" + source: hosted + version: "0.8.12+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0" + url: "https://pub.dev" + source: hosted + version: "2.10.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" intl: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 9eb05c7..7d11fee 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: package_info_plus: ^8.3.0 freezed_annotation: ^3.0.0 json_annotation: ^4.9.0 + image_picker: ^1.1.2 dev_dependencies: flutter_test: diff --git a/test/app/home/views/home_screen_test.mocks.dart b/test/app/home/views/home_screen_test.mocks.dart index 063ca0c..58f4527 100644 --- a/test/app/home/views/home_screen_test.mocks.dart +++ b/test/app/home/views/home_screen_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/home/views/welcome_screen_test.mocks.dart b/test/app/home/views/welcome_screen_test.mocks.dart index 524cadb..a4ac3e1 100644 --- a/test/app/home/views/welcome_screen_test.mocks.dart +++ b/test/app/home/views/welcome_screen_test.mocks.dart @@ -522,6 +522,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -543,6 +544,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -570,6 +572,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -593,6 +596,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/controllers/all_pets_controller_test.dart b/test/app/pet/controllers/all_pets_controller_test.dart index f989559..e5fc06e 100644 --- a/test/app/pet/controllers/all_pets_controller_test.dart +++ b/test/app/pet/controllers/all_pets_controller_test.dart @@ -271,6 +271,7 @@ void main() { neuterDate: null, status: PetStatus.active.dataValue, statusDate: DateTime.now(), + imageUrl: '/files/images/pet_pic.png', ); final initialPetModel = PetModel( @@ -290,6 +291,7 @@ void main() { status: PetStatus.fromDataValue(initialPet.status), statusDate: initialPet.statusDate, isMicrochipped: false, + imageUrl: initialPet.imageUrl, ); when( @@ -315,6 +317,7 @@ void main() { initialPetModel.microchipNumber, initialPetModel.microchipCompany, initialPetModel.microchipNotes, + initialPetModel.imageUrl, ), ).thenAnswer((_) => Future.value(initialPet)); @@ -352,6 +355,7 @@ void main() { initialPetModel.microchipNumber, initialPetModel.microchipCompany, initialPetModel.microchipNotes, + initialPetModel.imageUrl, ), ).called(1); @@ -379,6 +383,7 @@ void main() { neuterDate: null, status: PetStatus.active.dataValue, statusDate: DateTime.now(), + imageUrl: '/files/images/pet_pic.png', ); final initialPetModel = PetModel( @@ -398,6 +403,7 @@ void main() { status: PetStatus.fromDataValue(initialPet.status), statusDate: initialPet.statusDate, isMicrochipped: false, + imageUrl: initialPet.imageUrl, ); when( @@ -425,6 +431,7 @@ void main() { initialPetModel.microchipNumber, initialPetModel.microchipCompany, initialPetModel.microchipNotes, + initialPetModel.imageUrl, ), ).thenAnswer((_) => Future.value(1)); @@ -464,6 +471,7 @@ void main() { initialPetModel.microchipNumber, initialPetModel.microchipCompany, initialPetModel.microchipNotes, + initialPetModel.imageUrl, ), ).called(1); diff --git a/test/app/pet/controllers/all_pets_controller_test.mocks.dart b/test/app/pet/controllers/all_pets_controller_test.mocks.dart index 989abcb..fcaba04 100644 --- a/test/app/pet/controllers/all_pets_controller_test.mocks.dart +++ b/test/app/pet/controllers/all_pets_controller_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/controllers/journal_controller_test.mocks.dart b/test/app/pet/controllers/journal_controller_test.mocks.dart index ad0ce79..bdedba9 100644 --- a/test/app/pet/controllers/journal_controller_test.mocks.dart +++ b/test/app/pet/controllers/journal_controller_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/controllers/pet_controller_test.mocks.dart b/test/app/pet/controllers/pet_controller_test.mocks.dart index 62a41ce..10ae94b 100644 --- a/test/app/pet/controllers/pet_controller_test.mocks.dart +++ b/test/app/pet/controllers/pet_controller_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/controllers/pet_meds_controller_test.mocks.dart b/test/app/pet/controllers/pet_meds_controller_test.mocks.dart index 62cf6ac..70a4831 100644 --- a/test/app/pet/controllers/pet_meds_controller_test.mocks.dart +++ b/test/app/pet/controllers/pet_meds_controller_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/controllers/pet_microchips_controller_test.mocks.dart b/test/app/pet/controllers/pet_microchips_controller_test.mocks.dart index 8bd0f3b..fc8f847 100644 --- a/test/app/pet/controllers/pet_microchips_controller_test.mocks.dart +++ b/test/app/pet/controllers/pet_microchips_controller_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/controllers/pet_vaccinations_controller_test.mocks.dart b/test/app/pet/controllers/pet_vaccinations_controller_test.mocks.dart index 68acf0d..56cfbcf 100644 --- a/test/app/pet/controllers/pet_vaccinations_controller_test.mocks.dart +++ b/test/app/pet/controllers/pet_vaccinations_controller_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/controllers/pet_weights_controller_test.mocks.dart b/test/app/pet/controllers/pet_weights_controller_test.mocks.dart index 661fd7f..0dabff2 100644 --- a/test/app/pet/controllers/pet_weights_controller_test.mocks.dart +++ b/test/app/pet/controllers/pet_weights_controller_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/views/edit_journal_screen_test.mocks.dart b/test/app/pet/views/edit_journal_screen_test.mocks.dart index e2fc8d6..37cac8c 100644 --- a/test/app/pet/views/edit_journal_screen_test.mocks.dart +++ b/test/app/pet/views/edit_journal_screen_test.mocks.dart @@ -522,6 +522,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -543,6 +544,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -570,6 +572,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -593,6 +596,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/views/edit_pet_med_screen_test.mocks.dart b/test/app/pet/views/edit_pet_med_screen_test.mocks.dart index 6e5eb0a..6689c3f 100644 --- a/test/app/pet/views/edit_pet_med_screen_test.mocks.dart +++ b/test/app/pet/views/edit_pet_med_screen_test.mocks.dart @@ -522,6 +522,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -543,6 +544,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -570,6 +572,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -593,6 +596,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/views/edit_pet_screen_test.dart b/test/app/pet/views/edit_pet_screen_test.dart index 610dc95..9c2c074 100644 --- a/test/app/pet/views/edit_pet_screen_test.dart +++ b/test/app/pet/views/edit_pet_screen_test.dart @@ -184,6 +184,7 @@ void main() { any, any, any, + any, ), ).thenAnswer((_) async => null); // Act @@ -193,29 +194,68 @@ void main() { await tester.enterText(find.byKey(EditPetScreen.petNameKey), 'Buddy'); await tester.pumpAndSettle(); + final scrollableFinder = find.byType(Scrollable).last; + // Select species - await tester.tap(find.byKey(EditPetScreen.petSpeciesKey)); + final speciesWidget = find.byKey(EditPetScreen.petSpeciesKey); + await tester.scrollUntilVisible( + speciesWidget, + 10, + scrollable: scrollableFinder, + ); + await tester.tap(speciesWidget); await tester.pumpAndSettle(); await tester.tap(find.text('Dog').last); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(EditPetScreen.petBreedKey), 'Beagle'); + final breedWidget = find.byKey(EditPetScreen.petBreedKey); + await tester.scrollUntilVisible( + breedWidget, + 10, + scrollable: scrollableFinder, + ); + await tester.enterText(breedWidget, 'Beagle'); await tester.pumpAndSettle(); - await tester.enterText(find.byKey(EditPetScreen.petColourKey), 'Brown'); + + final colourWidget = find.byKey(EditPetScreen.petColourKey); + await tester.scrollUntilVisible( + colourWidget, + 10, + scrollable: scrollableFinder, + ); + await tester.enterText(colourWidget, 'Brown'); await tester.pumpAndSettle(); // Select sex - await tester.tap(find.byKey(EditPetScreen.petSexKey)); + final petSexWidget = find.byKey(EditPetScreen.petSexKey); + await tester.scrollUntilVisible( + petSexWidget, + 10, + scrollable: scrollableFinder, + ); + await tester.tap(petSexWidget); await tester.pumpAndSettle(); await tester.tap(find.text('male').last); await tester.pumpAndSettle(); // Select status - await tester.tap(find.byKey(EditPetScreen.petStatusKey)); + final petStatusWidget = find.byKey(EditPetScreen.petStatusKey); + await tester.scrollUntilVisible( + petStatusWidget, + 10, + scrollable: scrollableFinder, + ); + await tester.tap(petStatusWidget); await tester.pumpAndSettle(); await tester.tap(find.text('Active').last); await tester.pumpAndSettle(); // Save - await tester.tap(find.text('Save')); + final saveButtonWidget = find.text('Save'); + await tester.scrollUntilVisible( + saveButtonWidget, + 10, + scrollable: scrollableFinder, + ); + await tester.tap(saveButtonWidget); await tester.pumpAndSettle(); // Assert verify( @@ -238,6 +278,7 @@ void main() { any, any, any, + any, ), ).called(1); }); diff --git a/test/app/pet/views/edit_pet_screen_test.mocks.dart b/test/app/pet/views/edit_pet_screen_test.mocks.dart index ea07311..3c2ca02 100644 --- a/test/app/pet/views/edit_pet_screen_test.mocks.dart +++ b/test/app/pet/views/edit_pet_screen_test.mocks.dart @@ -522,6 +522,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -543,6 +544,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -570,6 +572,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -593,6 +596,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/views/edit_pet_vaccination_screen_test.mocks.dart b/test/app/pet/views/edit_pet_vaccination_screen_test.mocks.dart index 8e108b9..85e79be 100644 --- a/test/app/pet/views/edit_pet_vaccination_screen_test.mocks.dart +++ b/test/app/pet/views/edit_pet_vaccination_screen_test.mocks.dart @@ -522,6 +522,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -543,6 +544,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -570,6 +572,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -593,6 +596,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/pet/views/edit_pet_weight_screen_test.mocks.dart b/test/app/pet/views/edit_pet_weight_screen_test.mocks.dart index 0787b95..2c4a143 100644 --- a/test/app/pet/views/edit_pet_weight_screen_test.mocks.dart +++ b/test/app/pet/views/edit_pet_weight_screen_test.mocks.dart @@ -522,6 +522,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -543,6 +544,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -570,6 +572,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -593,6 +596,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/settings/controllers/settings_controller_test.mocks.dart b/test/app/settings/controllers/settings_controller_test.mocks.dart index 0e3e04b..b2a7cdb 100644 --- a/test/app/settings/controllers/settings_controller_test.mocks.dart +++ b/test/app/settings/controllers/settings_controller_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/settings/views/settings_screen_test.mocks.dart b/test/app/settings/views/settings_screen_test.mocks.dart index fe703ae..c0c8e0b 100644 --- a/test/app/settings/views/settings_screen_test.mocks.dart +++ b/test/app/settings/views/settings_screen_test.mocks.dart @@ -522,6 +522,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -543,6 +544,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -570,6 +572,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -593,6 +596,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/app/species/views/widgets/species_dropdown_test.mocks.dart b/test/app/species/views/widgets/species_dropdown_test.mocks.dart index 3b8aed7..d3b6073 100644 --- a/test/app/species/views/widgets/species_dropdown_test.mocks.dart +++ b/test/app/species/views/widgets/species_dropdown_test.mocks.dart @@ -478,6 +478,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#createPet, [ @@ -499,6 +500,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future<_i3.Pet?>.value(), ) @@ -526,6 +528,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { String? microchipNumber, String? microchipCompany, String? microchipNotes, + String? imageUrl, ) => (super.noSuchMethod( Invocation.method(#updatePet, [ @@ -549,6 +552,7 @@ class MockDatabaseService extends _i1.Mock implements _i3.DatabaseService { microchipNumber, microchipCompany, microchipNotes, + imageUrl, ]), returnValue: _i5.Future.value(0), ) diff --git a/test/data/database/database_service_journal_entry_details_test.dart b/test/data/database/database_service_journal_entry_details_test.dart index eaf55b8..eb14045 100644 --- a/test/data/database/database_service_journal_entry_details_test.dart +++ b/test/data/database/database_service_journal_entry_details_test.dart @@ -40,6 +40,7 @@ void main() { null, null, null, + null ); pet2 = await database.createPet( @@ -62,6 +63,7 @@ void main() { null, null, null, + null ); }); diff --git a/test/data/database/database_service_journal_entry_test.dart b/test/data/database/database_service_journal_entry_test.dart index d814495..43e7834 100644 --- a/test/data/database/database_service_journal_entry_test.dart +++ b/test/data/database/database_service_journal_entry_test.dart @@ -36,6 +36,7 @@ void main() { null, null, null, + null, ); }); @@ -100,6 +101,7 @@ void main() { null, null, null, + null, ); expect(pet2, match.isNotNull); diff --git a/test/data/database/database_service_pet_med_test.dart b/test/data/database/database_service_pet_med_test.dart index e2c83c9..14c0d3f 100644 --- a/test/data/database/database_service_pet_med_test.dart +++ b/test/data/database/database_service_pet_med_test.dart @@ -36,6 +36,7 @@ void main() { null, null, null, + null, ); }); diff --git a/test/data/database/database_service_pet_test.dart b/test/data/database/database_service_pet_test.dart index d6fb21e..af138ae 100644 --- a/test/data/database/database_service_pet_test.dart +++ b/test/data/database/database_service_pet_test.dart @@ -38,6 +38,7 @@ void main() { final testMicrochipNumber = '12345'; final testMicrochipNotes = 'Test notes'; final testMicrochipCompany = 'Test company'; + final testImageUrl = 'https://example.com/image.jpg'; final pet = await database.createPet( testName, @@ -58,6 +59,7 @@ void main() { testMicrochipNumber, testMicrochipCompany, testMicrochipNotes, + testImageUrl, ); expect(pet, match.isNotNull); @@ -79,6 +81,7 @@ void main() { expect(pet?.microchipNumber, equals(testMicrochipNumber)); expect(pet?.microchipCompany, equals(testMicrochipCompany)); expect(pet?.microchipNotes, equals(testMicrochipNotes)); + expect(pet?.imageUrl, equals(testImageUrl)); }); test('create pet with minimal required fields', () async { @@ -101,6 +104,7 @@ void main() { null, null, null, + null, ); expect(pet, match.isNotNull); @@ -122,6 +126,7 @@ void main() { expect(pet?.microchipNumber, match.isNull); expect(pet?.microchipCompany, match.isNull); expect(pet?.microchipNotes, match.isNull); + expect(pet?.imageUrl, match.isNull); }); test('get pet by id returns correct pet', () async { @@ -145,6 +150,7 @@ void main() { null, null, null, + null, ); expect(createdPet, match.isNotNull); @@ -185,6 +191,7 @@ void main() { null, null, null, + null, ); await database.createPet( @@ -206,6 +213,7 @@ void main() { null, null, null, + null, ); // Get all pets and verify @@ -235,6 +243,7 @@ void main() { null, null, null, + null, ); expect(pet, match.isNotNull); @@ -267,6 +276,7 @@ void main() { '12345', 'New Microchip Company', 'New Microchip Notes', + 'https://example.com/image.jpg', ); expect(updatedCount, equals(1)); @@ -290,6 +300,7 @@ void main() { expect(updatedPet?.microchipNumber, equals('12345')); expect(updatedPet?.microchipCompany, equals('New Microchip Company')); expect(updatedPet?.microchipNotes, equals('New Microchip Notes')); + expect(updatedPet?.imageUrl, equals('https://example.com/image.jpg')); }); test('update non-existent pet returns zero', () async { @@ -315,6 +326,7 @@ void main() { null, null, null, + null, ); expect(updateCount, equals(0)); @@ -341,6 +353,7 @@ void main() { null, null, null, + null, ); expect(pet, match.isNotNull); @@ -381,6 +394,7 @@ void main() { null, null, null, + null, ); expect(pet, match.isNotNull); @@ -412,6 +426,7 @@ void main() { '12345', 'New Microchip Company', 'New Microchip Notes', + 'https://example.com/image.jpg', ); // Verify the stream emits the updated pet @@ -419,6 +434,7 @@ void main() { expect(updatedPet?.name, equals('Luna Updated')); expect(updatedPet?.breed, equals('Poodle')); expect(updatedPet?.microchipNumber, equals('12345')); + expect(updatedPet?.imageUrl, equals('https://example.com/image.jpg')); }); }); } diff --git a/test/data/database/database_service_pet_vaccination_test.dart b/test/data/database/database_service_pet_vaccination_test.dart index 4e1648a..45c8fc7 100644 --- a/test/data/database/database_service_pet_vaccination_test.dart +++ b/test/data/database/database_service_pet_vaccination_test.dart @@ -36,6 +36,7 @@ void main() { null, null, null, + null, ); }); diff --git a/test/data/database/database_service_pet_weight_test.dart b/test/data/database/database_service_pet_weight_test.dart index 422f81d..9668dde 100644 --- a/test/data/database/database_service_pet_weight_test.dart +++ b/test/data/database/database_service_pet_weight_test.dart @@ -37,6 +37,7 @@ void main() { null, null, null, + null, ); }); diff --git a/test/data/database/database_service_species_type_test.dart b/test/data/database/database_service_species_type_test.dart index 35aabe9..30c62f6 100644 --- a/test/data/database/database_service_species_type_test.dart +++ b/test/data/database/database_service_species_type_test.dart @@ -270,6 +270,7 @@ void main() { null, null, null, + null, ); // Attempt to delete the species type should throw an exception diff --git a/test/data/mapper/pet_mapper_test.dart b/test/data/mapper/pet_mapper_test.dart index 3f6889d..b7018fd 100644 --- a/test/data/mapper/pet_mapper_test.dart +++ b/test/data/mapper/pet_mapper_test.dart @@ -31,6 +31,7 @@ void main() { microchipNotes: 'Healthy', microchipNumber: '123456789', microchipCompany: 'PetSafe', + imageUrl: 'path/to/image.jpg', ); // Act @@ -57,6 +58,7 @@ void main() { expect(model.microchipNotes, equals('Healthy')); expect(model.microchipNumber, equals('123456789')); expect(model.microchipCompany, equals('PetSafe')); + expect(model.imageUrl, equals('path/to/image.jpg')); }); test('mapToModel should handle null optional fields', () { @@ -82,6 +84,7 @@ void main() { microchipNotes: null, microchipNumber: null, microchipCompany: null, + imageUrl: null, ); // Act @@ -100,6 +103,7 @@ void main() { expect(model.microchipNotes, match.isNull); expect(model.microchipNumber, match.isNull); expect(model.microchipCompany, match.isNull); + expect(model.imageUrl, match.isNull); }); test('mapToModelList should correctly map a list of Pets to PetModels', () { @@ -126,6 +130,7 @@ void main() { microchipNotes: null, microchipNumber: null, microchipCompany: null, + imageUrl: null, ), Pet( petId: 2, @@ -148,6 +153,7 @@ void main() { microchipNotes: 'Healthy', microchipNumber: '123456789', microchipCompany: 'PetSafe', + imageUrl: 'path/to/image.jpg', ), ]; @@ -159,9 +165,11 @@ void main() { expect(models[0].name, equals('Rex')); expect(models[0].breed, equals('German Shepherd')); expect(models[0].isMicrochipped, match.isFalse); + expect(models[0].imageUrl, match.isNull); expect(models[1].name, equals('Luna')); expect(models[1].breed, equals('Labrador')); expect(models[1].isMicrochipped, match.isTrue); + expect(models[1].imageUrl, equals('path/to/image.jpg')); }); test('mapToModelList should return empty list for empty input', () { diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 76d5285..b874386 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,10 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 22aeaae..1ef42a8 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows sqlite3_flutter_libs url_launcher_windows )