Updates for photo model

release/mobdr-v0.0.1
Frédérik Benoist 2023-04-20 21:50:07 +02:00
parent ee76c40294
commit d76f037333
14 changed files with 715 additions and 311 deletions

View File

@ -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<String, dynamic> json)
: id_visite = json['id_visite'],

View File

@ -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});

View File

@ -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<List<VisiteModel>> 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<VisiteModel> 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')
];

View File

@ -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']);
}

View File

@ -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

View File

@ -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<List<Visite>> getVisites() {
Stream<List<Visite>> 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<Visite> 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<Visite>.
List<Visite> parseVisites(List responseDataList) {
final parsed = responseDataList.cast<Map<String, dynamic>>();
return parsed.map<Visite>((json) => Visite.fromJson(json)).toList();
}
// TODO : Enregistre urlphotoprincipale sur le disque pour l'avoir en cache ?
Future<void> addVisites(List<dynamic> _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<Visite>().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<VisiteTag>.
// converts a response body list into a List<VisiteTag>.
List<VisiteTag> parseVisiteTags(List responseDataList) {
final parsed = responseDataList.cast<Map<String, dynamic>>();
return parsed.map<VisiteTag>((json) => VisiteTag.fromJson(json)).toList();
@ -316,6 +330,7 @@ class ObjectBox {
store.box<VisiteTag>().putMany(_VisiteTags);
}
/// save new tag for a distributor / langage
Future<void> addVisiteTag(
int _id_visite_tag,
int _id_distrib,
@ -336,23 +351,38 @@ class ObjectBox {
store.box<VisiteTag>().put(_VisiteTag);
}
List<String> getVisiteTagsLabels() {
List<String> 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<String> pq = query.property(VisiteTag_.libelle);
pq.distinct = true;
pq.caseSensitive = false;
return pq.find();
}
int getVisiteTagCount() {
return visiteTagBox.count();
}
Future<void> putPhotoTags(int photoId, List<String> 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<Photo> _listPhotos) {
store.box<Photo>().putManyAsync(_listPhotos);
///
Future<List<Photo>> addPhotos(List<Photo> photos) async {
final addedPhotos = await photoBox.putAndGetManyAsync(photos);
return addedPhotos;
}
Future<void> addPhoto(int id_visite, int id_photo_typologie, String image,
@ -372,7 +402,7 @@ class ObjectBox {
store.box<Photo>().put(_Photo);
}
List<Photo> getPhotos2() {
List<Photo> 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<List<Photo>> getPhotos() {
// Query for all photos, sorted by their date.
// https://docs.objectbox.io/queries

View File

@ -220,7 +220,7 @@ final _entities = <ModelEntity>[
ModelEntity(
id: const IdUid(7, 8290500625256822711),
name: 'Visite',
lastPropertyId: const IdUid(11, 3119168728902810585),
lastPropertyId: const IdUid(13, 1900114397693432703),
flags: 0,
properties: <ModelProperty>[
ModelProperty(
@ -267,6 +267,11 @@ final _entities = <ModelEntity>[
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: <ModelRelation>[],
@ -308,7 +313,7 @@ final _entities = <ModelEntity>[
ModelEntity(
id: const IdUid(9, 6788844671665652158),
name: 'Photo',
lastPropertyId: const IdUid(16, 539065583624712715),
lastPropertyId: const IdUid(17, 7248999677905103482),
flags: 0,
properties: <ModelProperty>[
ModelProperty(
@ -316,11 +321,6 @@ final _entities = <ModelEntity>[
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 = <ModelEntity>[
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 = <ModelEntity>[
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: <ModelRelation>[],
@ -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<Visite>(_entities[5].properties[8]);
/// see [Visite.url_photo_principale]
static final url_photo_principale =
QueryStringProperty<Visite>(_entities[5].properties[9]);
}
/// [VisiteTag] entity fields to define ObjectBox queries.
@ -1030,60 +1019,43 @@ class Photo_ {
/// see [Photo.id]
static final id = QueryIntegerProperty<Photo>(_entities[7].properties[0]);
/// see [Photo.id_photo]
static final id_photo =
QueryIntegerProperty<Photo>(_entities[7].properties[1]);
/// see [Photo.id_visite]
static final id_visite =
QueryIntegerProperty<Photo>(_entities[7].properties[2]);
QueryIntegerProperty<Photo>(_entities[7].properties[1]);
/// see [Photo.id_photo_typologie]
static final id_photo_typologie =
QueryIntegerProperty<Photo>(_entities[7].properties[3]);
QueryIntegerProperty<Photo>(_entities[7].properties[2]);
/// see [Photo.date_photo]
static final date_photo =
QueryIntegerProperty<Photo>(_entities[7].properties[4]);
QueryIntegerProperty<Photo>(_entities[7].properties[3]);
/// see [Photo.id_photo_mp4]
static final id_photo_mp4 =
QueryIntegerProperty<Photo>(_entities[7].properties[5]);
QueryIntegerProperty<Photo>(_entities[7].properties[4]);
/// see [Photo.photo_privee]
static final photo_privee =
QueryIntegerProperty<Photo>(_entities[7].properties[6]);
QueryIntegerProperty<Photo>(_entities[7].properties[5]);
/// see [Photo.photo_principale]
static final photo_principale =
QueryIntegerProperty<Photo>(_entities[7].properties[7]);
/// see [Photo.photo_tag1]
static final photo_tag1 =
QueryStringProperty<Photo>(_entities[7].properties[8]);
/// see [Photo.photo_tag2]
static final photo_tag2 =
QueryStringProperty<Photo>(_entities[7].properties[9]);
/// see [Photo.photo_tag3]
static final photo_tag3 =
QueryStringProperty<Photo>(_entities[7].properties[10]);
/// see [Photo.photo_tag4]
static final photo_tag4 =
QueryStringProperty<Photo>(_entities[7].properties[11]);
QueryIntegerProperty<Photo>(_entities[7].properties[6]);
/// see [Photo.uploaded]
static final uploaded =
QueryIntegerProperty<Photo>(_entities[7].properties[12]);
QueryIntegerProperty<Photo>(_entities[7].properties[7]);
/// see [Photo.image]
static final image = QueryStringProperty<Photo>(_entities[7].properties[13]);
static final image = QueryStringProperty<Photo>(_entities[7].properties[8]);
/// see [Photo.image_name]
static final image_name =
QueryStringProperty<Photo>(_entities[7].properties[14]);
QueryStringProperty<Photo>(_entities[7].properties[9]);
/// see [Photo.tags]
static final tags = QueryStringProperty<Photo>(_entities[7].properties[10]);
}
/// [PhotoTypology] entity fields to define ObjectBox queries.

View File

@ -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);
}
}

View File

@ -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<PhotoDetailPage> {
final _globalFunction = GlobalFunction();
final _reusableWidget = ReusableWidget();
bool _isLoading = true;
String _errorMessage = '';
// Typology list
List<String> _typologyList = objectbox.getPhotoTypologiesLabels();
late List<String> _typologyList = [];
int _typologyIndex = 0;
List<String> _chickenParts = [];
@ -56,13 +68,20 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
// shopping cart count
int _shoppingCartCount = 3;
// tag(s) list
final List<String> tagsList = objectbox.getVisiteTagsLabels();
List<String> selectedTagsList = [];
late String tags = "";
late List<String> 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<PhotoDetailPage> {
@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: <Widget>[
TextButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
);
}
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(
@ -150,7 +187,7 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
//_createProductSlider(),
_buildPhotoTypology(),
_buildPhotoVisibility(),
_buildPhotoTag(),
_buildPhotoTag(context),
SizedBox(height: 16)
],
),
@ -302,6 +339,7 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
);
}
// TODO changer chicken
Widget _checboxChicken({value = 'breast', primaryText = 'Chicken Breast'}) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
@ -379,74 +417,69 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
);
}
Widget _buildPhotoTag() {
return Container(
Widget _buildPhotoTag(BuildContext context) {
return GestureDetector(
onTap: () async {
// Navigation to the PhotoTagPage
final newTags = await Navigator.push<List<String>>(
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<void> _openTagSelectionDialog() async {
await FilterListDialog.display<String>(
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<void> 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';
}
}
}

View File

@ -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<PhotoListPage> {
// initialize photos files list
final List<File> photoFiles = [];
List<PhotoModel> _photoData = [];
List<Photo> _photoData = [];
Color _color1 = Color(0xff777777);
Color _color2 = Color(0xFF515151);
@ -57,13 +56,7 @@ class _PhotoListPageState extends State<PhotoListPage> {
}
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<PhotoListPage> {
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<PhotoListPage> {
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<PhotoListPage> {
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<PhotoListPage> {
void savePhotos() async {
if (photoFiles.length > 0) {
final List<Photo> _listPhotos = [];
final List<PhotoModel> _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(() {

268
lib/ui/home/photo_tag.dart Normal file
View File

@ -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<String> 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<PhotoTagPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
late List<String> allTagsList = [];
late List<String> _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: <Widget>[
TagEditor<String>(
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<void> loadData() async {
// TODO 1,fr
allTagsList = await objectbox.getVisiteTagsLabels(1, 'fr');
_selectedTags = List<String>.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<void> saveSelectedTags(
List<String> 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<int> 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);
},
);
}
}

View File

@ -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<TabHomePage>
late LanguageCubit _languageCubit;
bool _isLoading = true;
String _errorMessage = '';
late List<VisiteModel> visiteData = [];
@override
void initState() {
super.initState();
_languageCubit = BlocProvider.of<LanguageCubit>(context);
_getLocale().then((val) {
@ -50,7 +58,11 @@ class _TabHomePageState extends State<TabHomePage>
});
});
super.initState();
loadData().then((_) {
setState(() {
_isLoading = false;
});
});
}
@override
@ -77,6 +89,13 @@ class _TabHomePageState extends State<TabHomePage>
// 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<TabHomePage>
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(height: 8),
Text(
visiteData.name,
style: GlobalStyle.productName
@ -172,39 +192,32 @@ class _TabHomePageState extends State<TabHomePage>
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<TabHomePage>
),
);
}
// data initialization on loading.
Future<void> loadData() async {
try {
// visite initialisation
visiteData = await VisiteModel.getAllVisites();
} catch (e) {
// set errorMessage for debug
_errorMessage = 'Error loading visites : $e';
}
}
}

View File

@ -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"

View File

@ -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