From d76f03733311da65728403125704d47287246e72 Mon Sep 17 00:00:00 2001 From: Frederik Benoist Date: Thu, 20 Apr 2023 21:50:07 +0200 Subject: [PATCH] Updates for photo model --- lib/db/box_photo.dart | 39 +++-- lib/model/photo_model.dart | 4 +- lib/model/visite_model.dart | 76 ++++++---- lib/network/api_provider.dart | 8 +- lib/objectbox-model.json | 53 +++---- lib/objectbox.dart | 70 +++++++-- lib/objectbox.g.dart | 136 +++++++---------- lib/service/shared_prefs.dart | 14 ++ lib/ui/home/photo_detail.dart | 165 ++++++++++++--------- lib/ui/home/photo_list.dart | 37 ++--- lib/ui/home/photo_tag.dart | 268 ++++++++++++++++++++++++++++++++++ lib/ui/home/tab_home.dart | 70 ++++++--- pubspec.lock | 74 ++++++---- pubspec.yaml | 12 +- 14 files changed, 715 insertions(+), 311 deletions(-) create mode 100644 lib/ui/home/photo_tag.dart diff --git a/lib/db/box_photo.dart b/lib/db/box_photo.dart index 0ab3a82..5b24a28 100644 --- a/lib/db/box_photo.dart +++ b/lib/db/box_photo.dart @@ -10,7 +10,6 @@ class Photo { @Id() int id = 0; - int id_photo; int id_visite; int id_photo_typologie; String image; @@ -19,10 +18,7 @@ class Photo { int id_photo_mp4; int photo_privee; int photo_principale; - String photo_tag1; - String photo_tag2; - String photo_tag3; - String photo_tag4; + String tags; int uploaded; Photo( @@ -31,20 +27,43 @@ class Photo { required this.id_photo_typologie, required this.image, required this.image_name, - this.id_photo = 0, this.id_photo_mp4 = 0, this.photo_privee = 0, this.photo_principale = 0, - this.photo_tag1 = '', - this.photo_tag2 = '', - this.photo_tag3 = '', - this.photo_tag4 = '', + this.tags = '', DateTime? date_photo, this.uploaded = 0}) : date_photo = date_photo ?? DateTime.now(); String get dateFormat => DateFormat('dd.MM.yyyy hh:mm:ss').format(date_photo); + Photo copyWith({ + int? id, + int? id_visite, + int? id_photo_typologie, + String? image, + String? image_name, + DateTime? date_photo, + int? id_photo_mp4, + int? photo_privee, + int? photo_principale, + String? tags, + int? uploaded, + }) { + return Photo( + id: id ?? this.id, + id_visite: id_visite ?? this.id_visite, + id_photo_typologie: id_photo_typologie ?? this.id_photo_typologie, + image: image ?? this.image, + image_name: image_name ?? this.image_name, + date_photo: date_photo ?? this.date_photo, + id_photo_mp4: id_photo_mp4 ?? this.id_photo_mp4, + photo_privee: photo_privee ?? this.photo_privee, + photo_principale: photo_principale ?? this.photo_principale, + tags: tags ?? this.tags, + uploaded: uploaded ?? this.uploaded, + ); + } /* Photo.fromJson(Map json) : id_visite = json['id_visite'], diff --git a/lib/model/photo_model.dart b/lib/model/photo_model.dart index 4fd477e..80b06cb 100644 --- a/lib/model/photo_model.dart +++ b/lib/model/photo_model.dart @@ -1,11 +1,13 @@ class PhotoModel { + late int id; late int id_visite; late int id_photo_typologie; late String image; late String image_name; PhotoModel( - {required this.id_visite, + {required this.id, + required this.id_visite, required this.id_photo_typologie, required this.image, required this.image_name}); diff --git a/lib/model/visite_model.dart b/lib/model/visite_model.dart index 9821ccc..1ae3425 100644 --- a/lib/model/visite_model.dart +++ b/lib/model/visite_model.dart @@ -1,44 +1,56 @@ -import 'package:mobdr/config/constant.dart'; +import 'package:mobdr/main.dart'; class VisiteModel { late int id; late String name; - late double price; + late int photo; + late String date; late String image; + late String type_visite; + late double price; late double rating; late int review; late int sale; late int stock; late String location; - late int photo; - late String date; - VisiteModel( - {required this.id, - required this.name, - required this.price, - required this.photo, - required this.image, - required this.rating, - required this.review, - required this.sale, - required this.stock, - required this.location, - required this.date}); + VisiteModel({ + required this.id, + required this.name, + required this.photo, + required this.date, + required this.image, + required this.type_visite, + required this.price, + required this.rating, + required this.review, + required this.sale, + required this.stock, + required this.location, + }); + + static Future> getAllVisites() async { + // Retrieve all visits from the database using the getAllVisites() method + final visites = await objectbox.getAllVisites(); + + // Map each retrieved visit to VisiteModel + final visiteModels = visites + .map((visite) => VisiteModel( + id: visite.id, + name: visite.title, + photo: 1, + date: visite.date_visite.toString(), + image: visite.url_photo_principale, + type_visite: visite.type_visite, + price: 0, + rating: 0, + review: 0, + sale: 0, + stock: 10, + location: "")) + .toList(); + + // Return the list of VisiteModel + return visiteModels; + } } - -List visiteData = [ - VisiteModel( - id: 1, - name: "Villeneuve d'asc ONE-STEP", - price: 62, - photo: 1, - image: - 'https://mp4.ikksgroup.com/photos/1/0/1/8/4/4/101844-thumbnail.JPG', - rating: 5, - review: 42, - sale: 4, - stock: 5, - location: "Villeneuve d'asc", - date: 'Dimanche 26/02/2023 14:00') -]; diff --git a/lib/network/api_provider.dart b/lib/network/api_provider.dart index 24049a7..bb0785d 100644 --- a/lib/network/api_provider.dart +++ b/lib/network/api_provider.dart @@ -256,7 +256,7 @@ class ApiProvider { ApiConstants.externalEndpoint + ApiConstants.restEndpoint + '/mobDR/visite/calendrier', - {"id_utilisateur": 6, "start": 20230101, "end": 20230131}); + {"id_utilisateur": 6, "start": 20230101, "end": 20230501}); /// get "Visite tags" list response2 = await getCrud( @@ -274,6 +274,9 @@ class ApiProvider { } if (response2.statusCode == STATUS_OK) { + // remove all objects + objectbox.visiteTagBox.removeAll(); + /// fill box "visiteTag" objectbox.addVisiteTags(response2.data['tags']); } @@ -302,6 +305,9 @@ class ApiProvider { null); if (response.statusCode == STATUS_OK) { + // remove all objects + objectbox.photoTypologyBox.removeAll(); + /// fill box "Photo typologies" objectbox.addPhotoTypologies(response.data['typologies']); } diff --git a/lib/objectbox-model.json b/lib/objectbox-model.json index 779ca10..d6ef092 100644 --- a/lib/objectbox-model.json +++ b/lib/objectbox-model.json @@ -195,7 +195,7 @@ }, { "id": "7:8290500625256822711", - "lastPropertyId": "11:3119168728902810585", + "lastPropertyId": "13:1900114397693432703", "name": "Visite", "properties": [ { @@ -243,6 +243,11 @@ "id": "11:3119168728902810585", "name": "date_visite", "type": 10 + }, + { + "id": "13:1900114397693432703", + "name": "url_photo_principale", + "type": 9 } ], "relations": [] @@ -283,7 +288,7 @@ }, { "id": "9:6788844671665652158", - "lastPropertyId": "16:539065583624712715", + "lastPropertyId": "17:7248999677905103482", "name": "Photo", "properties": [ { @@ -292,11 +297,6 @@ "type": 6, "flags": 1 }, - { - "id": "2:7877546811840884522", - "name": "id_photo", - "type": 6 - }, { "id": "3:1374846727562410311", "name": "id_visite", @@ -327,26 +327,6 @@ "name": "photo_principale", "type": 6 }, - { - "id": "10:2757780641715705310", - "name": "photo_tag1", - "type": 9 - }, - { - "id": "11:6494338359539955476", - "name": "photo_tag2", - "type": 9 - }, - { - "id": "12:5293139139799032553", - "name": "photo_tag3", - "type": 9 - }, - { - "id": "13:2141346538986140281", - "name": "photo_tag4", - "type": 9 - }, { "id": "14:4568092734700892012", "name": "uploaded", @@ -361,6 +341,11 @@ "id": "16:539065583624712715", "name": "image_name", "type": 9 + }, + { + "id": "17:7248999677905103482", + "name": "tags", + "type": 9 } ], "relations": [] @@ -396,7 +381,7 @@ } ], "lastEntityId": "10:2779194860339140505", - "lastIndexId": "0:0", + "lastIndexId": "1:7907819717055295102", "lastRelationId": "0:0", "lastSequenceId": "0:0", "modelVersion": 5, @@ -404,14 +389,22 @@ "retiredEntityUids": [ 7401686910042688313 ], - "retiredIndexUids": [], + "retiredIndexUids": [ + 7907819717055295102 + ], "retiredPropertyUids": [ 402019719780433349, 2876428622751679696, 6435857490868115471, 4582947574501853036, 103801570610300983, - 1940661113633121688 + 1940661113633121688, + 2757780641715705310, + 6494338359539955476, + 5293139139799032553, + 2141346538986140281, + 7877546811840884522, + 3784190804330297742 ], "retiredRelationUids": [], "version": 1 diff --git a/lib/objectbox.dart b/lib/objectbox.dart index 35e5657..e5c7b44 100644 --- a/lib/objectbox.dart +++ b/lib/objectbox.dart @@ -66,7 +66,7 @@ class ObjectBox { userBox.removeAll(); etabBox.removeAll(); concurrentBox.removeAll(); - visiteBox.removeAll(); + //visiteBox.removeAll(); //visiteTagBox.removeAll(); //photoBox.removeAll(); //photoTypologyBox.removeAll(); @@ -240,7 +240,7 @@ class ObjectBox { /// VISITE ------------------------------------------------------------------ /// - Stream> getVisites() { + Stream> getVisitesStream() { // Query for all visites, sorted by their date. // https://docs.objectbox.io/queries final builder = @@ -253,12 +253,23 @@ class ObjectBox { .map((query) => query.find()); } + List getAllVisites() { + // Query for all visites, sorted by their date. + final builder = visiteBox + .query() + .order(Visite_.date_visite, flags: Order.descending) + .build(); + // Execute the query and return the result. + return builder.find(); + } + // A function that converts a response body list into a List. List parseVisites(List responseDataList) { final parsed = responseDataList.cast>(); return parsed.map((json) => Visite.fromJson(json)).toList(); } + // TODO : Enregistre urlphotoprincipale sur le disque pour l'avoir en cache ? Future addVisites(List _listVisites) => store.runInTransactionAsync( TxMode.write, _addVisitesInTx, parseVisites(_listVisites)); @@ -277,7 +288,8 @@ class ObjectBox { int _id_distrib_visite, int _id_etab, int _abandon, - String _end) => + String _end, + String _url_photo_principale) => store.runInTransactionAsync( TxMode.write, _addVisiteInTx, @@ -289,7 +301,8 @@ class ObjectBox { allDay: _allDay, id_distrib_visite: _id_distrib_visite, id_etab: _id_etab, - abandon: _abandon)); + abandon: _abandon, + url_photo_principale: _url_photo_principale)); static void _addVisiteInTx(Store store, _Visite) { store.box().put(_Visite); @@ -299,10 +312,11 @@ class ObjectBox { return visiteBox.count(); } - /// VISITE TAG --------------------------------------------------------------- + //TODO changer en PHOTO TAG / mettre dans l'ordre CRUD + /// PHOTO TAG --------------------------------------------------------------- /// - // A function that converts a response body list into a List. + // converts a response body list into a List. List parseVisiteTags(List responseDataList) { final parsed = responseDataList.cast>(); return parsed.map((json) => VisiteTag.fromJson(json)).toList(); @@ -316,6 +330,7 @@ class ObjectBox { store.box().putMany(_VisiteTags); } + /// save new tag for a distributor / langage Future addVisiteTag( int _id_visite_tag, int _id_distrib, @@ -336,23 +351,38 @@ class ObjectBox { store.box().put(_VisiteTag); } - List getVisiteTagsLabels() { + List getVisiteTagsLabels(int distribId, String langage) { final query = visiteTagBox - .query(VisiteTag_.langage.equals('fr')) - .order(VisiteTag_.libelle) + .query(VisiteTag_.id_distrib.equals(distribId) & + VisiteTag_.langage.equals(langage)) + //.order(VisiteTag_.libelle) .build(); - final visiteTags = query.find(); - return visiteTags.map((VisiteTag) => VisiteTag.libelle).toList(); + PropertyQuery pq = query.property(VisiteTag_.libelle); + pq.distinct = true; + pq.caseSensitive = false; + return pq.find(); } int getVisiteTagCount() { return visiteTagBox.count(); } + Future putPhotoTags(int photoId, List tags) async { + final photo = photoBox.get(photoId); + + if (photo != null) { + final updatedPhoto = photo.copyWith(tags: tags.join(",")); + await photoBox.putAsync(updatedPhoto); + } + } + /// PHOTO -------------------------------------------------------------------- /// - void addPhotos(List _listPhotos) { - store.box().putManyAsync(_listPhotos); + /// + + Future> addPhotos(List photos) async { + final addedPhotos = await photoBox.putAndGetManyAsync(photos); + return addedPhotos; } Future addPhoto(int id_visite, int id_photo_typologie, String image, @@ -372,7 +402,7 @@ class ObjectBox { store.box().put(_Photo); } - List getPhotos2() { + List getAllPhotos() { // Query for all photos, sorted by their date. // https://docs.objectbox.io/queries final query = photoBox @@ -382,6 +412,18 @@ class ObjectBox { return query.find(); } + /// Retrieves a Photo object from the ObjectBox database with the specified ID. + /// + /// Parameters: + /// id_photo: The ID of the photo to retrieve. + /// + /// Returns: + /// A Photo object, or null if no object is found. + Photo? getPhotoById(int id_photo) { + final photo = photoBox.get(id_photo); + return photo; + } + Stream> getPhotos() { // Query for all photos, sorted by their date. // https://docs.objectbox.io/queries diff --git a/lib/objectbox.g.dart b/lib/objectbox.g.dart index 8f775b0..51a7dd0 100644 --- a/lib/objectbox.g.dart +++ b/lib/objectbox.g.dart @@ -220,7 +220,7 @@ final _entities = [ ModelEntity( id: const IdUid(7, 8290500625256822711), name: 'Visite', - lastPropertyId: const IdUid(11, 3119168728902810585), + lastPropertyId: const IdUid(13, 1900114397693432703), flags: 0, properties: [ ModelProperty( @@ -267,6 +267,11 @@ final _entities = [ id: const IdUid(11, 3119168728902810585), name: 'date_visite', type: 10, + flags: 0), + ModelProperty( + id: const IdUid(13, 1900114397693432703), + name: 'url_photo_principale', + type: 9, flags: 0) ], relations: [], @@ -308,7 +313,7 @@ final _entities = [ ModelEntity( id: const IdUid(9, 6788844671665652158), name: 'Photo', - lastPropertyId: const IdUid(16, 539065583624712715), + lastPropertyId: const IdUid(17, 7248999677905103482), flags: 0, properties: [ ModelProperty( @@ -316,11 +321,6 @@ final _entities = [ name: 'id', type: 6, flags: 1), - ModelProperty( - id: const IdUid(2, 7877546811840884522), - name: 'id_photo', - type: 6, - flags: 0), ModelProperty( id: const IdUid(3, 1374846727562410311), name: 'id_visite', @@ -351,26 +351,6 @@ final _entities = [ name: 'photo_principale', type: 6, flags: 0), - ModelProperty( - id: const IdUid(10, 2757780641715705310), - name: 'photo_tag1', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(11, 6494338359539955476), - name: 'photo_tag2', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(12, 5293139139799032553), - name: 'photo_tag3', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(13, 2141346538986140281), - name: 'photo_tag4', - type: 9, - flags: 0), ModelProperty( id: const IdUid(14, 4568092734700892012), name: 'uploaded', @@ -385,6 +365,11 @@ final _entities = [ id: const IdUid(16, 539065583624712715), name: 'image_name', type: 9, + flags: 0), + ModelProperty( + id: const IdUid(17, 7248999677905103482), + name: 'tags', + type: 9, flags: 0) ], relations: [], @@ -441,18 +426,24 @@ ModelDefinition getObjectBoxModel() { final model = ModelInfo( entities: _entities, lastEntityId: const IdUid(10, 2779194860339140505), - lastIndexId: const IdUid(0, 0), + lastIndexId: const IdUid(1, 7907819717055295102), lastRelationId: const IdUid(0, 0), lastSequenceId: const IdUid(0, 0), retiredEntityUids: const [7401686910042688313], - retiredIndexUids: const [], + retiredIndexUids: const [7907819717055295102], retiredPropertyUids: const [ 402019719780433349, 2876428622751679696, 6435857490868115471, 4582947574501853036, 103801570610300983, - 1940661113633121688 + 1940661113633121688, + 2757780641715705310, + 6494338359539955476, + 5293139139799032553, + 2141346538986140281, + 7877546811840884522, + 3784190804330297742 ], retiredRelationUids: const [], modelVersion: 5, @@ -676,7 +667,9 @@ ModelDefinition getObjectBoxModel() { objectToFB: (Visite object, fb.Builder fbb) { final type_visiteOffset = fbb.writeString(object.type_visite); final titleOffset = fbb.writeString(object.title); - fbb.startTable(12); + final url_photo_principaleOffset = + fbb.writeString(object.url_photo_principale); + fbb.startTable(14); fbb.addInt64(0, object.id); fbb.addInt64(1, object.id_visite); fbb.addOffset(2, type_visiteOffset); @@ -686,6 +679,7 @@ ModelDefinition getObjectBoxModel() { fbb.addInt64(7, object.id_etab); fbb.addInt64(8, object.abandon); fbb.addInt64(10, object.date_visite.millisecondsSinceEpoch); + fbb.addOffset(12, url_photo_principaleOffset); fbb.finish(fbb.endTable()); return object.id; }, @@ -710,7 +704,10 @@ ModelDefinition getObjectBoxModel() { id_etab: const fb.Int64Reader().vTableGet(buffer, rootOffset, 18, 0), abandon: - const fb.Int64Reader().vTableGet(buffer, rootOffset, 20, 0)); + const fb.Int64Reader().vTableGet(buffer, rootOffset, 20, 0), + url_photo_principale: + const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 28, '')); return object; }), @@ -760,28 +757,21 @@ ModelDefinition getObjectBoxModel() { object.id = id; }, objectToFB: (Photo object, fb.Builder fbb) { - final photo_tag1Offset = fbb.writeString(object.photo_tag1); - final photo_tag2Offset = fbb.writeString(object.photo_tag2); - final photo_tag3Offset = fbb.writeString(object.photo_tag3); - final photo_tag4Offset = fbb.writeString(object.photo_tag4); final imageOffset = fbb.writeString(object.image); final image_nameOffset = fbb.writeString(object.image_name); - fbb.startTable(17); + final tagsOffset = fbb.writeString(object.tags); + fbb.startTable(18); fbb.addInt64(0, object.id); - fbb.addInt64(1, object.id_photo); fbb.addInt64(2, object.id_visite); fbb.addInt64(3, object.id_photo_typologie); fbb.addInt64(5, object.date_photo.millisecondsSinceEpoch); fbb.addInt64(6, object.id_photo_mp4); fbb.addInt64(7, object.photo_privee); fbb.addInt64(8, object.photo_principale); - fbb.addOffset(9, photo_tag1Offset); - fbb.addOffset(10, photo_tag2Offset); - fbb.addOffset(11, photo_tag3Offset); - fbb.addOffset(12, photo_tag4Offset); fbb.addInt64(13, object.uploaded); fbb.addOffset(14, imageOffset); fbb.addOffset(15, image_nameOffset); + fbb.addOffset(16, tagsOffset); fbb.finish(fbb.endTable()); return object.id; }, @@ -799,23 +789,18 @@ ModelDefinition getObjectBoxModel() { .vTableGet(buffer, rootOffset, 32, ''), image_name: const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 34, ''), - id_photo: - const fb.Int64Reader().vTableGet(buffer, rootOffset, 6, 0), id_photo_mp4: const fb.Int64Reader().vTableGet(buffer, rootOffset, 16, 0), photo_privee: const fb.Int64Reader().vTableGet(buffer, rootOffset, 18, 0), photo_principale: const fb.Int64Reader().vTableGet(buffer, rootOffset, 20, 0), - photo_tag1: const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 22, ''), - photo_tag2: const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 24, ''), - photo_tag3: - const fb.StringReader(asciiOptimization: true).vTableGet(buffer, rootOffset, 26, ''), - photo_tag4: const fb.StringReader(asciiOptimization: true).vTableGet(buffer, rootOffset, 28, ''), - date_photo: DateTime.fromMillisecondsSinceEpoch(const fb.Int64Reader().vTableGet(buffer, rootOffset, 14, 0)), - uploaded: const fb.Int64Reader().vTableGet(buffer, rootOffset, 30, 0)); + tags: const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 36, ''), + date_photo: DateTime.fromMillisecondsSinceEpoch( + const fb.Int64Reader().vTableGet(buffer, rootOffset, 14, 0)), + uploaded: + const fb.Int64Reader().vTableGet(buffer, rootOffset, 30, 0)); return object; }), @@ -1001,6 +986,10 @@ class Visite_ { /// see [Visite.date_visite] static final date_visite = QueryIntegerProperty(_entities[5].properties[8]); + + /// see [Visite.url_photo_principale] + static final url_photo_principale = + QueryStringProperty(_entities[5].properties[9]); } /// [VisiteTag] entity fields to define ObjectBox queries. @@ -1030,60 +1019,43 @@ class Photo_ { /// see [Photo.id] static final id = QueryIntegerProperty(_entities[7].properties[0]); - /// see [Photo.id_photo] - static final id_photo = - QueryIntegerProperty(_entities[7].properties[1]); - /// see [Photo.id_visite] static final id_visite = - QueryIntegerProperty(_entities[7].properties[2]); + QueryIntegerProperty(_entities[7].properties[1]); /// see [Photo.id_photo_typologie] static final id_photo_typologie = - QueryIntegerProperty(_entities[7].properties[3]); + QueryIntegerProperty(_entities[7].properties[2]); /// see [Photo.date_photo] static final date_photo = - QueryIntegerProperty(_entities[7].properties[4]); + QueryIntegerProperty(_entities[7].properties[3]); /// see [Photo.id_photo_mp4] static final id_photo_mp4 = - QueryIntegerProperty(_entities[7].properties[5]); + QueryIntegerProperty(_entities[7].properties[4]); /// see [Photo.photo_privee] static final photo_privee = - QueryIntegerProperty(_entities[7].properties[6]); + QueryIntegerProperty(_entities[7].properties[5]); /// see [Photo.photo_principale] static final photo_principale = - QueryIntegerProperty(_entities[7].properties[7]); - - /// see [Photo.photo_tag1] - static final photo_tag1 = - QueryStringProperty(_entities[7].properties[8]); - - /// see [Photo.photo_tag2] - static final photo_tag2 = - QueryStringProperty(_entities[7].properties[9]); - - /// see [Photo.photo_tag3] - static final photo_tag3 = - QueryStringProperty(_entities[7].properties[10]); - - /// see [Photo.photo_tag4] - static final photo_tag4 = - QueryStringProperty(_entities[7].properties[11]); + QueryIntegerProperty(_entities[7].properties[6]); /// see [Photo.uploaded] static final uploaded = - QueryIntegerProperty(_entities[7].properties[12]); + QueryIntegerProperty(_entities[7].properties[7]); /// see [Photo.image] - static final image = QueryStringProperty(_entities[7].properties[13]); + static final image = QueryStringProperty(_entities[7].properties[8]); /// see [Photo.image_name] static final image_name = - QueryStringProperty(_entities[7].properties[14]); + QueryStringProperty(_entities[7].properties[9]); + + /// see [Photo.tags] + static final tags = QueryStringProperty(_entities[7].properties[10]); } /// [PhotoTypology] entity fields to define ObjectBox queries. diff --git a/lib/service/shared_prefs.dart b/lib/service/shared_prefs.dart index 8a2fe52..a48a33c 100644 --- a/lib/service/shared_prefs.dart +++ b/lib/service/shared_prefs.dart @@ -88,4 +88,18 @@ class SharedPrefs { set photo(String value) { _sharedPrefs.setString('key_photo', value); } + + /// get/set id_distrib + int get id_distrib => _sharedPrefs.getInt('key_id_distrib') ?? 0; + + set id_distrib(int value) { + _sharedPrefs.setInt('key_id_distrib', value); + } + + /// get/set id_visite + int get id_visite => _sharedPrefs.getInt('key_id_visite') ?? 0; + + set id_visite(int value) { + _sharedPrefs.setInt('key_id_visite', value); + } } diff --git a/lib/ui/home/photo_detail.dart b/lib/ui/home/photo_detail.dart index ca58909..32b8ac2 100644 --- a/lib/ui/home/photo_detail.dart +++ b/lib/ui/home/photo_detail.dart @@ -1,8 +1,8 @@ import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:filter_list/filter_list.dart'; import 'package:mobdr/config/constant.dart'; import 'package:mobdr/config/global_style.dart'; @@ -10,14 +10,20 @@ import 'package:mobdr/main.dart'; import 'package:mobdr/ui/general/chat_us.dart'; import 'package:mobdr/ui/general/notification.dart'; import 'package:mobdr/ui/home/product_category.dart'; +import 'package:mobdr/ui/home/photo_tag.dart'; import 'package:mobdr/ui/home/search.dart'; import 'package:mobdr/ui/reusable/reusable_widget.dart'; import 'package:mobdr/ui/shopping_cart/tab_shopping_cart.dart'; import 'package:mobdr/ui/reusable/global_function.dart'; +import 'package:mobdr/db/box_photo.dart'; + class PhotoDetailPage extends StatefulWidget { + // variables corresponding to the data parameters + final int id; final String name; final String image; + final String tags; final double price; final int photo; final double rating; @@ -25,10 +31,13 @@ class PhotoDetailPage extends StatefulWidget { final int sale; final String date; + // Requiring data parameters const PhotoDetailPage( {Key? key, + this.id = 0, this.name = '', this.image = '', + this.tags = '', this.price = 24, this.photo = 1, this.rating = 4, @@ -46,8 +55,11 @@ class _PhotoDetailPageState extends State { final _globalFunction = GlobalFunction(); final _reusableWidget = ReusableWidget(); + bool _isLoading = true; + String _errorMessage = ''; + // Typology list - List _typologyList = objectbox.getPhotoTypologiesLabels(); + late List _typologyList = []; int _typologyIndex = 0; List _chickenParts = []; @@ -56,13 +68,20 @@ class _PhotoDetailPageState extends State { // shopping cart count int _shoppingCartCount = 3; - // tag(s) list - final List tagsList = objectbox.getVisiteTagsLabels(); - List selectedTagsList = []; + late String tags = ""; + late List tagList = []; + + late Photo _photo; @override void initState() { super.initState(); + + loadData(widget.id).then((_) { + setState(() { + _isLoading = false; + }); + }); } @override @@ -72,6 +91,24 @@ class _PhotoDetailPageState extends State { @override Widget build(BuildContext context) { + if (_isLoading) { + return Center(child: CircularProgressIndicator()); + } else if (_errorMessage.isNotEmpty) { + return Center( + child: AlertDialog( + title: Text("Erreur"), + content: Text("La photo est introuvable"), + actions: [ + TextButton( + child: Text("OK"), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ), + ); + } return Scaffold( appBar: AppBar( iconTheme: IconThemeData( @@ -150,7 +187,7 @@ class _PhotoDetailPageState extends State { //_createProductSlider(), _buildPhotoTypology(), _buildPhotoVisibility(), - _buildPhotoTag(), + _buildPhotoTag(context), SizedBox(height: 16) ], ), @@ -302,6 +339,7 @@ class _PhotoDetailPageState extends State { ); } + // TODO changer chicken Widget _checboxChicken({value = 'breast', primaryText = 'Chicken Breast'}) { return GestureDetector( behavior: HitTestBehavior.translucent, @@ -379,74 +417,69 @@ class _PhotoDetailPageState extends State { ); } - Widget _buildPhotoTag() { - return Container( + Widget _buildPhotoTag(BuildContext context) { + return GestureDetector( + onTap: () async { + // Navigation to the PhotoTagPage + final newTags = await Navigator.push>( + context, + MaterialPageRoute( + builder: (context) => + PhotoTagPage(photoId: this._photo.id, currentTags: tagList), + ), + ); + + // Checking changes made to tags + if (newTags != null && !listEquals(tagList, newTags)) { + setState(() { + tagList = newTags; + }); + } + }, + child: Container( margin: EdgeInsets.only(top: 12), padding: EdgeInsets.all(16), color: Colors.white, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Tags sélectionnés:"), - SizedBox(height: 8), - selectedTagsList.isEmpty - ? Text("Aucun tag sélectionné.") - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: tagsList.map((tag) => Text("- $tag")).toList(), - ), - SizedBox(height: 16), - ElevatedButton( - onPressed: () => _openTagSelectionDialog(), - child: Text("Modifier"), + Row( + children: [ + Text('Tags', style: GlobalStyle.sectionTitle), + ], + ), + Wrap( + spacing: 8.0, + runSpacing: 8.0, + alignment: WrapAlignment.start, + children: tagList.map((tag) { + return Chip( + label: Text(tag), + backgroundColor: Colors.grey[300], + ); + }).toList(), ), ], - )); - } - - Future _openTagSelectionDialog() async { - await FilterListDialog.display( - context, - hideSelectedTextCount: true, - themeData: FilterListThemeData(context), - headlineText: 'Select Users', - height: 500, - listData: tagsList, - selectedListData: selectedTagsList, - choiceChipLabel: (item) => item, - validateSelectedItem: (list, val) => list!.contains(val), - controlButtons: [ControlButtonType.All, ControlButtonType.Reset], - onItemSearch: (user, query) { - /// When search query change in search bar then this method will be called - /// - /// Check if items contains query - return user.toLowerCase().contains(query.toLowerCase()); - }, - - onApplyButtonClick: (list) { - setState(() { - selectedTagsList = list!; - }); - Navigator.pop(context); - }, - - /// uncomment below code to create custom choice chip - /* - choiceChipBuilder: (context, item, isSelected) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), - decoration: BoxDecoration( - border: Border.all( - color: isSelected! ? Colors.blue[300]! : Colors.grey[300]!, - )), - child: Text( - item, - style: TextStyle( - color: isSelected ? Colors.blue[300] : Colors.grey[500]), - ), - ); - },*/ + ), + ), ); } + + /// data initialization on loading. + Future loadData(int photoId) async { + try { + // photo typologies initialization + _typologyList = objectbox.getPhotoTypologiesLabels(); + + // get photo object + _photo = objectbox.getPhotoById(photoId)!; + + // photo tag initialization + tags = _photo.tags; + tagList = tags.isEmpty ? [] : tags.split(","); + } catch (e) { + // set errorMessage for debug + _errorMessage = 'Error loading photo: $e'; + } + } } diff --git a/lib/ui/home/photo_list.dart b/lib/ui/home/photo_list.dart index c3a4816..9292ebf 100644 --- a/lib/ui/home/photo_list.dart +++ b/lib/ui/home/photo_list.dart @@ -14,7 +14,6 @@ import 'package:mobdr/config/constant.dart'; import 'package:mobdr/main.dart'; import 'package:mobdr/ui/reusable/global_widget.dart'; import 'package:mobdr/ui/home/photo_camera.dart'; -import 'package:mobdr/model/photo_model.dart'; import 'package:mobdr/db/box_photo.dart'; import 'package:mobdr/ui/home/photo_detail.dart'; @@ -37,7 +36,7 @@ class _PhotoListPageState extends State { // initialize photos files list final List photoFiles = []; - List _photoData = []; + List _photoData = []; Color _color1 = Color(0xff777777); Color _color2 = Color(0xFF515151); @@ -57,13 +56,7 @@ class _PhotoListPageState extends State { } void _loadData() { - for (Photo myPhoto in objectbox.getPhotos2()) { - _photoData.add(PhotoModel( - id_visite: myPhoto.id_visite, - id_photo_typologie: myPhoto.id_photo_typologie, - image: myPhoto.image, - image_name: myPhoto.image_name)); - } + _photoData = objectbox.getAllPhotos(); } @override @@ -114,8 +107,7 @@ class _PhotoListPageState extends State { floatingActionButton: fabCart(context)); } - Widget _buildPhotolistCard( - PhotoModel photoData, boxImageSize, animation, index) { + Widget _buildPhotolistCard(Photo photoData, boxImageSize, animation, index) { return SizeTransition( sizeFactor: animation, child: Container( @@ -136,6 +128,7 @@ class _PhotoListPageState extends State { context, MaterialPageRoute( builder: (context) => PhotoDetailPage( + id: _photoData[index].id, name: 'visiteData.name', image: _photoData[index].image, price: 0, @@ -144,6 +137,12 @@ class _PhotoListPageState extends State { review: 0, sale: 0, date: ''))); + + // todo if qq chose à changé + // ne raffraichir que le widget en cours == + setState(() { + _listKey = GlobalKey(); + }); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, @@ -414,32 +413,24 @@ class _PhotoListPageState extends State { void savePhotos() async { if (photoFiles.length > 0) { final List _listPhotos = []; - final List _listPhotosModel = []; for (var myTmpPhoto in photoFiles) { /// move jpg file to photo directory final myPhoto = await moveFileFromTempToPhotosDir(myTmpPhoto); - /// database + /// to insert into database _listPhotos.add(Photo( id_visite: 0, id_photo_typologie: 0, image: myPhoto.path, image_name: myPhoto.path.split('/').last)); - - /// widget - _listPhotosModel.add(PhotoModel( - id_visite: 0, - id_photo_typologie: 0, - image: myPhoto.path, - image_name: myPhoto.path.split('/').last)); } /// insert photo(s) in database (async) - objectbox.addPhotos(_listPhotos); + final addedPhotos = await objectbox.addPhotos(_listPhotos); - /// insert photo(s) in widget - _photoData.insertAll(0, _listPhotosModel); + /// insert photo(s) in widget at the beginning (0) + _photoData.insertAll(0, addedPhotos); /// refresh widget setState(() { diff --git a/lib/ui/home/photo_tag.dart b/lib/ui/home/photo_tag.dart new file mode 100644 index 0000000..dad5b75 --- /dev/null +++ b/lib/ui/home/photo_tag.dart @@ -0,0 +1,268 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'package:mobdr/main.dart'; +import 'package:mobdr/config/global_style.dart'; + +import 'package:super_tag_editor/tag_editor.dart'; +import 'package:super_tag_editor/widgets/rich_text_widget.dart'; + +class PhotoTagPage extends StatefulWidget { + // variables corresponding to the data parameters + final int photoId; + final List currentTags; + + // Requiring data parameters + const PhotoTagPage( + {Key? key, required this.photoId, required this.currentTags}) + : super(key: key); + + @override + _PhotoTagPageState createState() => _PhotoTagPageState(); +} + +class _PhotoTagPageState extends State { + final GlobalKey _formKey = GlobalKey(); + + late List allTagsList = []; + late List _selectedTags = []; + bool isLoading = true; + + final FocusNode _focusNode = FocusNode(); + final TextEditingController _textEditingController = TextEditingController(); + bool focusTagEnabled = false; + + _onDelete(index) { + setState(() { + _selectedTags.removeAt(index); + }); + } + + @override + void initState() { + super.initState(); + + loadData().then((_) { + setState(() { + isLoading = false; + }); + }); + } + + @override + Widget build(BuildContext context) { + if (isLoading) { + return Center(child: CircularProgressIndicator()); + } + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + iconTheme: IconThemeData( + color: GlobalStyle.appBarIconThemeColor, + ), + elevation: GlobalStyle.appBarElevation, + title: Text( + 'Edit tags ...', + style: GlobalStyle.appBarTitle, + ), + backgroundColor: GlobalStyle.appBarBackgroundColor, + systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle), + body: Center( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: ListView( + children: [ + TagEditor( + length: _selectedTags.length, + controller: _textEditingController, + focusNode: _focusNode, + delimiters: [',', ' '], + hasAddButton: true, + resetTextOnSubmitted: true, + // This is set to grey just to illustrate the `textStyle` prop + textStyle: const TextStyle(color: Colors.grey), + onSubmitted: (outstandingValue) { + setState(() { + _selectedTags.add(outstandingValue); + }); + }, + inputDecoration: const InputDecoration( + border: InputBorder.none, + hintText: 'Enter tag ...', + ), + onTagChanged: (newValue) { + setState(() { + _selectedTags.add(newValue); + }); + }, + tagBuilder: (context, index) => Container( + color: focusTagEnabled && index == _selectedTags.length - 1 + ? Colors.redAccent + : Colors.white, + child: _Chip( + index: index, + label: _selectedTags[index], + onDeleted: _onDelete, + ), + ), + // InputFormatters example, this disallow \ and / + inputFormatters: [ + FilteringTextInputFormatter.deny(RegExp(r'[/\\]')) + ], + useDefaultHighlight: false, + suggestionBuilder: (context, state, data, index, length, + highlight, suggestionValid) { + var borderRadius = + const BorderRadius.all(Radius.circular(20)); + if (index == 0) { + borderRadius = const BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ); + } else if (index == length - 1) { + borderRadius = const BorderRadius.only( + bottomRight: Radius.circular(20), + bottomLeft: Radius.circular(20), + ); + } + return InkWell( + onTap: () { + setState(() { + _selectedTags.add(data); + }); + state.resetTextField(); + state.closeSuggestionBox(); + }, + child: Container( + decoration: highlight + ? BoxDecoration( + color: Theme.of(context).focusColor, + borderRadius: borderRadius) + : null, + padding: const EdgeInsets.all(16), + child: RichTextWidget( + wordSearched: suggestionValid ?? '', + textOrigin: data, + )), + ); + }, + onFocusTagAction: (focused) { + setState(() { + focusTagEnabled = focused; + }); + }, + onDeleteTagAction: () { + if (_selectedTags.isNotEmpty) { + setState(() { + _selectedTags.removeLast(); + }); + } + }, + onSelectOptionAction: (item) { + setState(() { + _selectedTags.add(item); + }); + }, + suggestionsBoxElevation: 10, + findSuggestions: (String query) { + if (query.isNotEmpty) { + var lowercaseQuery = query.toLowerCase(); + var filteredList = allTagsList + .where((tag) => + !_selectedTags.contains(tag) && + (tag.toLowerCase().startsWith(lowercaseQuery) || + tag.toLowerCase().contains(lowercaseQuery))) + .toList(growable: false); + + filteredList.sort((a, b) => a + .toLowerCase() + .indexOf(lowercaseQuery) + .compareTo(b.toLowerCase().indexOf(lowercaseQuery))); + + return filteredList; + } + return []; + }, + ), + const Divider(), + ElevatedButton( + onPressed: () async { + // Save the selected tags to the database //TODO 1,fr === + await saveSelectedTags(_selectedTags, 1, 'fr'); + + Navigator.pop( + context, _selectedTags.map((tag) => tag).toList()); + }, + child: const Text('Save'), + ), + ], + ), + ), + ), + ); + } + + Future loadData() async { + // TODO 1,fr + allTagsList = await objectbox.getVisiteTagsLabels(1, 'fr'); + _selectedTags = List.from(widget.currentTags); + } + + /// Saves the selected tags for a photo to the ObjectBox database. + /// + /// Parameters: + /// tags: The list of tags to save. + /// distribId: The ID of the distribution associated with the photo. + /// langage: The language code for the tags. + /// + /// If the list of tags is empty, the function will exit without saving any tags. + /// Otherwise, any new tags that are not already in the database will be added, + /// and the photo's tags will be saved to the database. + /// + /// Returns: + /// Nothing. + Future saveSelectedTags( + List tags, int distribId, String langage) async { + if (tags.isEmpty) { + return; // exit function without saving tags + } + + // determines if there are any new tags + final newTags = tags.where((tag) => !allTagsList.contains(tag)).toList(); + + for (final tag in newTags) { + // insert new tag in the database + objectbox.addVisiteTag(0, distribId, tag, langage); + } + + // save photo tag in the database + objectbox.putPhotoTags(widget.photoId, tags); + } +} + +class _Chip extends StatelessWidget { + const _Chip({ + required this.label, + required this.onDeleted, + required this.index, + }); + + final String label; + final ValueChanged onDeleted; + final int index; + + @override + Widget build(BuildContext context) { + return Chip( + labelPadding: const EdgeInsets.only(left: 8.0), + label: Text(label), + deleteIcon: const Icon( + Icons.close, + size: 18, + ), + onDeleted: () { + onDeleted(index); + }, + ); + } +} diff --git a/lib/ui/home/tab_home.dart b/lib/ui/home/tab_home.dart index 1827013..ed8d123 100644 --- a/lib/ui/home/tab_home.dart +++ b/lib/ui/home/tab_home.dart @@ -7,6 +7,9 @@ import 'package:mobdr/config/constant.dart'; import 'package:mobdr/cubit/language/language_cubit.dart'; import 'package:mobdr/cubit/language/app_localizations.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + import 'package:mobdr/service/shared_prefs.dart'; import 'package:mobdr/config/global_style.dart'; import 'package:mobdr/model/visite_model.dart'; @@ -16,8 +19,6 @@ import 'package:mobdr/ui/home/photo_typology.dart'; import 'package:mobdr/ui/general/product_detail/product_detail.dart'; import 'package:mobdr/ui/reusable/reusable_widget.dart'; import 'package:mobdr/ui/reusable/cache_image_network.dart'; -import 'package:flutter/material.dart'; -import 'package:shared_preferences/shared_preferences.dart'; class TabHomePage extends StatefulWidget { @override @@ -40,8 +41,15 @@ class _TabHomePageState extends State late LanguageCubit _languageCubit; + bool _isLoading = true; + String _errorMessage = ''; + + late List visiteData = []; + @override void initState() { + super.initState(); + _languageCubit = BlocProvider.of(context); _getLocale().then((val) { @@ -50,7 +58,11 @@ class _TabHomePageState extends State }); }); - super.initState(); + loadData().then((_) { + setState(() { + _isLoading = false; + }); + }); } @override @@ -77,6 +89,13 @@ class _TabHomePageState extends State // if we used AutomaticKeepAliveClientMixin, we must call super.build(context); super.build(context); final double boxImageSize = (MediaQuery.of(context).size.width / 4); + if (_isLoading) { + return Center(child: CircularProgressIndicator()); + } else if (visiteData.isEmpty) { + return Center( + child: Text('Aucune visite trouvée.'), + ); + } return Scaffold( appBar: AppBar( automaticallyImplyLeading: false, @@ -165,6 +184,7 @@ class _TabHomePageState extends State child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Container(height: 8), Text( visiteData.name, style: GlobalStyle.productName @@ -172,39 +192,32 @@ class _TabHomePageState extends State maxLines: 3, overflow: TextOverflow.ellipsis, ), + Container( + margin: EdgeInsets.only(top: 5), + child: Text(visiteData.date, + style: GlobalStyle.productSale), + ), + Container(height: 5), Container( margin: EdgeInsets.only(top: 5), child: Text( visiteData.photo.toString() + ' Photo(s)', style: GlobalStyle.productPrice), ), + Container(height: 5), Container( margin: EdgeInsets.only(top: 5), child: Row( children: [ - Icon(Icons.location_on, - color: SOFT_GREY, size: 12), - Text(' ' + visiteData.location, - style: GlobalStyle.productLocation) + Icon(Icons.store, color: SOFT_GREY, size: 20), + Text(' ' + visiteData.type_visite, + style: GlobalStyle.productName + .copyWith(fontSize: 13), + maxLines: 1, + overflow: TextOverflow.ellipsis) ], ), ), - Container( - margin: EdgeInsets.only(top: 5), - child: Row( - children: [ - _reusableWidget.createRatingBar( - rating: visiteData.rating, size: 12), - Text('(' + visiteData.review.toString() + ')', - style: GlobalStyle.productTotalReview) - ], - ), - ), - Container( - margin: EdgeInsets.only(top: 5), - child: Text(visiteData.date, - style: GlobalStyle.productSale), - ), ], ), ) @@ -282,4 +295,15 @@ class _TabHomePageState extends State ), ); } + + // data initialization on loading. + Future loadData() async { + try { + // visite initialisation + visiteData = await VisiteModel.getAllVisites(); + } catch (e) { + // set errorMessage for debug + _errorMessage = 'Error loading visites : $e'; + } + } } diff --git a/pubspec.lock b/pubspec.lock index b5de166..7e1f7a8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -289,14 +289,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.4" + debounce_throttle: + dependency: transitive + description: + name: debounce_throttle + sha256: c95cf47afda975fc507794a52040a16756fb2f31ad3027d4e691c41862ff5692 + url: "https://pub.dev" + source: hosted + version: "2.0.0" dio: dependency: "direct main" description: name: dio - sha256: "2644a9e0965a7aa3deb09cb8ce4081db4450c178f472818c8cd34216a3070d7b" + sha256: "0894a098594263fe1caaba3520e3016d8a855caeb010a882273189cca10f11e9" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.1.1" fake_async: dependency: transitive description: @@ -321,14 +329,6 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.4" - filter_list: - dependency: "direct main" - description: - name: filter_list - sha256: "2d80d6d19beb7847c1176e8bf6fe06d302b23eb7d1bf48c231dd730409ff9b4d" - url: "https://pub.dev" - source: hosted - version: "1.0.2" fixnum: dependency: transitive description: @@ -805,6 +805,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + pointer_interceptor: + dependency: transitive + description: + name: pointer_interceptor + sha256: "6aa680b30d96dccef496933d00208ad25f07e047f644dc98ce03ec6141633a9a" + url: "https://pub.dev" + source: hosted + version: "0.9.3+4" pointycastle: dependency: transitive description: @@ -873,58 +881,58 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: ee6257848f822b8481691f20c3e6d2bfee2e9eccb2a3d249907fcfb198c55b41 + sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b" url: "https://pub.dev" source: hosted - version: "2.0.18" + version: "2.1.0" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: a51a4f9375097f94df1c6e0a49c0374440d31ab026b59d58a7e7660675879db4 + sha256: "7fa90471a6875d26ad78c7e4a675874b2043874586891128dc5899662c97db46" url: "https://pub.dev" source: hosted - version: "2.0.16" + version: "2.1.2" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "6b84fdf06b32bb336f972d373cd38b63734f3461ba56ac2ba01b56d052796259" + sha256: "0c1c16c56c9708aa9c361541a6f0e5cc6fc12a3232d866a687a7b7db30032b07" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: d7fb71e6e20cd3dfffcc823a28da3539b392e53ed5fc5c2b90b55fdaa8a7e8fa + sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "824bfd02713e37603b2bdade0842e47d56e7db32b1dcdd1cae533fb88e2913fc" + sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.2.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "6737b757e49ba93de2a233df229d0b6a87728cea1684da828cbc718b65dcf9d7" + sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.0" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: bd014168e8484837c39ef21065b78f305810ceabc1d4f90be6e3b392ce81b46d + sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" shelf: dependency: transitive description: @@ -949,6 +957,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + simple_observable: + dependency: transitive + description: + name: simple_observable + sha256: b392795c48f8b5f301b4c8f73e15f56e38fe70f42278c649d8325e859a783301 + url: "https://pub.dev" + source: hosted + version: "2.0.0" sky_engine: dependency: transitive description: flutter @@ -1018,6 +1034,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + super_tag_editor: + dependency: "direct main" + description: + name: super_tag_editor + sha256: "0888ef22d5a1485baeb628892de449e03af4b6f901ac7f7c9ddd2f44f6199e22" + url: "https://pub.dev" + source: hosted + version: "0.1.1" synchronized: dependency: transitive description: @@ -1179,5 +1203,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=2.19.2 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index d5d2c9e..64b04d0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,7 +31,8 @@ dependencies: flutter: sdk: flutter - dio: 5.0.2 + # https://pub.dev/packages/dio + dio: 5.1.1 objectbox: ^2.0.0 objectbox_flutter_libs: any pin_code_fields: 7.4.0 @@ -55,8 +56,8 @@ dependencies: permission_handler: 10.2.0 image: ^4.0.15 - # https://pub.dev/packages/filter_list/install - filter_list: ^1.0.2 + # https://pub.dev/packages/super_tag_editor + super_tag_editor: ^0.1.1 flutter_cache_manager: ^3.3.0 @@ -66,7 +67,10 @@ dependencies: carousel_slider: 4.2.1 cached_network_image: 3.2.3 get_it: ^7.2.0 - shared_preferences: 2.0.18 + + # https://pub.dev/packages/shared_preferences + shared_preferences: ^2.1.0 + timelines: ^0.1.0 universal_io: 2.2.0 xml: ^6.2.2