From 210f50bb2205bc4c3400e3274e7e60ff96d013e0 Mon Sep 17 00:00:00 2001 From: Frederik Benoist Date: Sun, 23 Apr 2023 21:09:27 +0200 Subject: [PATCH] global update --- assets/images/simulator.jpeg | Bin 0 -> 90875 bytes ios/Podfile.lock | 30 ++ ios/Runner/Info.plist | 3 + lib/db/box_photo.dart | 16 +- lib/db/box_visite.dart | 8 +- lib/main.dart | 211 +++++++++- lib/model/photo_model.dart | 2 - lib/model/visite_model.dart | 46 +-- lib/objectbox-model.json | 15 +- lib/objectbox.dart | 85 +++- lib/objectbox.g.dart | 41 +- lib/service/shared_prefs.dart | 21 + lib/ui/home/photo_typology.dart | 102 ----- lib/ui/home/tab_home.dart | 204 ++++------ .../{photo_tag.dart => visit_photo_tag.dart} | 45 ++- lib/ui/home/visit_photo_typology.dart | 166 ++++++++ ...st.dart => visit_photo_typology_list.dart} | 378 +++++++++++------- ...dart => visite_photo_typology_detail.dart} | 251 ++++-------- lib/ui/sync/tab_sync.dart | 1 - macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 20 +- pubspec.yaml | 9 +- 22 files changed, 1004 insertions(+), 652 deletions(-) create mode 100644 assets/images/simulator.jpeg delete mode 100644 lib/ui/home/photo_typology.dart rename lib/ui/home/{photo_tag.dart => visit_photo_tag.dart} (88%) create mode 100644 lib/ui/home/visit_photo_typology.dart rename lib/ui/home/{photo_list.dart => visit_photo_typology_list.dart} (59%) rename lib/ui/home/{photo_detail.dart => visite_photo_typology_detail.dart} (58%) diff --git a/assets/images/simulator.jpeg b/assets/images/simulator.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..fb272ddb54b0c8ba67e5c8106331deccaf6907fa GIT binary patch literal 90875 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≮&2o;NbtA# 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 2.7.5) - Toast (4.0.0) + - wakelock (0.0.1): + - Flutter DEPENDENCIES: + - camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`) + - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - Flutter (from `Flutter`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) + - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - objectbox_flutter_libs (from `.symlinks/plugins/objectbox_flutter_libs/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`) - sqflite (from `.symlinks/plugins/sqflite/ios`) + - wakelock (from `.symlinks/plugins/wakelock/ios`) SPEC REPOS: trunk: @@ -39,32 +54,47 @@ SPEC REPOS: - Toast EXTERNAL SOURCES: + camera_avfoundation: + :path: ".symlinks/plugins/camera_avfoundation/ios" + device_info_plus: + :path: ".symlinks/plugins/device_info_plus/ios" Flutter: :path: Flutter fluttertoast: :path: ".symlinks/plugins/fluttertoast/ios" + image_picker_ios: + :path: ".symlinks/plugins/image_picker_ios/ios" objectbox_flutter_libs: :path: ".symlinks/plugins/objectbox_flutter_libs/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/ios" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/ios" sqflite: :path: ".symlinks/plugins/sqflite/ios" + wakelock: + :path: ".symlinks/plugins/wakelock/ios" SPEC CHECKSUMS: + camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb + device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 ObjectBox: a7900d5335218cd437cbc080b7ccc38a5211f7b4 objectbox_flutter_libs: 61d74196d924fbc773da5f5757d1e9fab7b3cc78 package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 + permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472 sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 + wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f PODFILE CHECKSUM: b634fd49380cdd3837626153fb977533b1916433 diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 1974f7b..f34142f 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -48,7 +48,10 @@ UIApplicationSupportsIndirectInputEvents NSPhotoLibraryUsageDescription + Cette application a besoin de votre autorisation pour accéder à votre galerie photo afin que vous puissiez sélectionner des photos pour votre profil. NSCameraUsageDescription + Cette application a besoin de votre autorisation pour accéder à votre caméra afin que vous puissiez prendre des photos pour votre profil. NSMicrophoneUsageDescription + Cette application a besoin de votre autorisation pour accéder à votre microphone afin que vous puissiez enregistrer des messages audio pour envoyer à vos amis. diff --git a/lib/db/box_photo.dart b/lib/db/box_photo.dart index 5b24a28..8fc6b16 100644 --- a/lib/db/box_photo.dart +++ b/lib/db/box_photo.dart @@ -1,7 +1,9 @@ import 'package:objectbox/objectbox.dart'; -import 'package:mobdr/objectbox.g.dart'; import 'package:intl/intl.dart'; +import 'package:mobdr/objectbox.g.dart'; +import 'package:mobdr/service/shared_prefs.dart'; + // ignore_for_file: public_member_api_docs @Entity() @@ -12,7 +14,6 @@ class Photo { int id_visite; int id_photo_typologie; - String image; String image_name; DateTime date_photo; int id_photo_mp4; @@ -25,7 +26,6 @@ class Photo { {this.id = 0, required this.id_visite, required this.id_photo_typologie, - required this.image, required this.image_name, this.id_photo_mp4 = 0, this.photo_privee = 0, @@ -35,6 +35,15 @@ class Photo { this.uploaded = 0}) : date_photo = date_photo ?? DateTime.now(); + static String? _photosDir = SharedPrefs().photosDir; + + String getImage() { + if (_photosDir == null) { + throw Exception('Photos directory not initialized'); + } + return '$_photosDir/$image_name'; + } + String get dateFormat => DateFormat('dd.MM.yyyy hh:mm:ss').format(date_photo); Photo copyWith({ @@ -54,7 +63,6 @@ class 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, diff --git a/lib/db/box_visite.dart b/lib/db/box_visite.dart index cec182f..59bc27e 100644 --- a/lib/db/box_visite.dart +++ b/lib/db/box_visite.dart @@ -1,4 +1,3 @@ -import 'package:intl/intl.dart'; import 'package:objectbox/objectbox.dart'; import 'package:mobdr/objectbox.g.dart'; import 'package:mobdr/config/constant.dart'; @@ -20,6 +19,7 @@ class Visite { int id_etab; int abandon; String url_photo_principale; + String langage; Visite( {this.id = 0, @@ -31,7 +31,8 @@ class Visite { required this.id_distrib_visite, required this.id_etab, required this.abandon, - required this.url_photo_principale}); + required this.url_photo_principale, + required this.langage}); Visite.fromJson(Map json) : id_visite = json['id_visite'], @@ -43,5 +44,6 @@ class Visite { id_etab = json['id_etab'], abandon = json['abandon'], url_photo_principale = - ApiConstants.baseUrl + json['url_photo_principale']; + ApiConstants.baseUrl + json['url_photo_principale'], + langage = 'fr'; } diff --git a/lib/main.dart b/lib/main.dart index 3a6a67f..d879d1d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,17 +1,11 @@ // ignore_for_file: prefer_const_constructors import 'dart:ui'; +import 'dart:developer' as developer; import 'dart:io'; -import 'package:mobdr/config/constant.dart'; - -import 'package:mobdr/cubit/language/language_cubit.dart'; -import 'package:mobdr/cubit/language/app_localizations.dart'; -import 'package:mobdr/cubit/language/initial_language.dart'; - -import 'package:mobdr/service/shared_prefs.dart'; - -import 'package:mobdr/ui/splash_screen.dart'; +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -22,9 +16,19 @@ import 'package:path_provider/path_provider.dart'; import 'objectbox.dart'; import 'package:wakelock/wakelock.dart'; +import 'package:mobdr/config/constant.dart'; + +import 'package:mobdr/cubit/language/language_cubit.dart'; +import 'package:mobdr/cubit/language/app_localizations.dart'; +import 'package:mobdr/cubit/language/initial_language.dart'; +import 'package:mobdr/service/shared_prefs.dart'; +import 'package:mobdr/ui/splash_screen.dart'; + /// Provides access to the ObjectBox Store throughout the app. late ObjectBox objectbox; +final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); + Future main() async { // This is required so ObjectBox can get the application directory // to store the database in. @@ -62,6 +66,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { initDirectories(); + initPlatformState(); // Initialize all bloc provider used on this entire application here return MultiBlocProvider( @@ -139,5 +144,193 @@ class MyApp extends StatelessWidget { print( 'The "photos" directory has been created in the documents directory.'); } + + // save directories into shared Prefs + SharedPrefs().documentsDir = documentsDir.path; + SharedPrefs().photosDir = photosDir.path; + + // Get a list of all files in the "photos" directory + final List files = await photosDir.list().toList(); + + // Print out the names of the files in the directory + for (FileSystemEntity file in files) { + print('File name: ${file.path.split('/').last}'); + } + } + + Future initPlatformState() async { + var deviceData = {}; + + try { + if (kIsWeb) { + deviceData = _readWebBrowserInfo(await deviceInfoPlugin.webBrowserInfo); + } else { + if (Platform.isAndroid) { + deviceData = + _readAndroidBuildData(await deviceInfoPlugin.androidInfo); + } else if (Platform.isIOS) { + deviceData = _readIosDeviceInfo(await deviceInfoPlugin.iosInfo); + } else if (Platform.isLinux) { + deviceData = _readLinuxDeviceInfo(await deviceInfoPlugin.linuxInfo); + } else if (Platform.isMacOS) { + deviceData = _readMacOsDeviceInfo(await deviceInfoPlugin.macOsInfo); + } else if (Platform.isWindows) { + deviceData = + _readWindowsDeviceInfo(await deviceInfoPlugin.windowsInfo); + } + } + + // save if we are on a simulator + if (deviceData['isPhysicalDevice'] == false) { + SharedPrefs().isSimulator = true; + } + + print(deviceData); + } on PlatformException { + deviceData = { + 'Error:': 'Failed to get platform version.' + }; + } + } + + Map _readAndroidBuildData(AndroidDeviceInfo build) { + return { + 'version.securityPatch': build.version.securityPatch, + 'version.sdkInt': build.version.sdkInt, + 'version.release': build.version.release, + 'version.previewSdkInt': build.version.previewSdkInt, + 'version.incremental': build.version.incremental, + 'version.codename': build.version.codename, + 'version.baseOS': build.version.baseOS, + 'board': build.board, + 'bootloader': build.bootloader, + 'brand': build.brand, + 'device': build.device, + 'display': build.display, + 'fingerprint': build.fingerprint, + 'hardware': build.hardware, + 'host': build.host, + 'id': build.id, + 'manufacturer': build.manufacturer, + 'model': build.model, + 'product': build.product, + 'supported32BitAbis': build.supported32BitAbis, + 'supported64BitAbis': build.supported64BitAbis, + 'supportedAbis': build.supportedAbis, + 'tags': build.tags, + 'type': build.type, + 'isPhysicalDevice': build.isPhysicalDevice, + 'systemFeatures': build.systemFeatures, + 'displaySizeInches': + ((build.displayMetrics.sizeInches * 10).roundToDouble() / 10), + 'displayWidthPixels': build.displayMetrics.widthPx, + 'displayWidthInches': build.displayMetrics.widthInches, + 'displayHeightPixels': build.displayMetrics.heightPx, + 'displayHeightInches': build.displayMetrics.heightInches, + 'displayXDpi': build.displayMetrics.xDpi, + 'displayYDpi': build.displayMetrics.yDpi, + 'serialNumber': build.serialNumber, + }; + } + + Map _readIosDeviceInfo(IosDeviceInfo data) { + return { + 'name': data.name, + 'systemName': data.systemName, + 'systemVersion': data.systemVersion, + 'model': data.model, + 'localizedModel': data.localizedModel, + 'identifierForVendor': data.identifierForVendor, + 'isPhysicalDevice': data.isPhysicalDevice, + 'utsname.sysname:': data.utsname.sysname, + 'utsname.nodename:': data.utsname.nodename, + 'utsname.release:': data.utsname.release, + 'utsname.version:': data.utsname.version, + 'utsname.machine:': data.utsname.machine, + }; + } + + Map _readLinuxDeviceInfo(LinuxDeviceInfo data) { + return { + 'name': data.name, + 'version': data.version, + 'id': data.id, + 'idLike': data.idLike, + 'versionCodename': data.versionCodename, + 'versionId': data.versionId, + 'prettyName': data.prettyName, + 'buildId': data.buildId, + 'variant': data.variant, + 'variantId': data.variantId, + 'machineId': data.machineId, + }; + } + + Map _readWebBrowserInfo(WebBrowserInfo data) { + return { + 'browserName': describeEnum(data.browserName), + 'appCodeName': data.appCodeName, + 'appName': data.appName, + 'appVersion': data.appVersion, + 'deviceMemory': data.deviceMemory, + 'language': data.language, + 'languages': data.languages, + 'platform': data.platform, + 'product': data.product, + 'productSub': data.productSub, + 'userAgent': data.userAgent, + 'vendor': data.vendor, + 'vendorSub': data.vendorSub, + 'hardwareConcurrency': data.hardwareConcurrency, + 'maxTouchPoints': data.maxTouchPoints, + }; + } + + Map _readMacOsDeviceInfo(MacOsDeviceInfo data) { + return { + 'computerName': data.computerName, + 'hostName': data.hostName, + 'arch': data.arch, + 'model': data.model, + 'kernelVersion': data.kernelVersion, + 'majorVersion': data.majorVersion, + 'minorVersion': data.minorVersion, + 'patchVersion': data.patchVersion, + 'osRelease': data.osRelease, + 'activeCPUs': data.activeCPUs, + 'memorySize': data.memorySize, + 'cpuFrequency': data.cpuFrequency, + 'systemGUID': data.systemGUID, + }; + } + + Map _readWindowsDeviceInfo(WindowsDeviceInfo data) { + return { + 'numberOfCores': data.numberOfCores, + 'computerName': data.computerName, + 'systemMemoryInMegabytes': data.systemMemoryInMegabytes, + 'userName': data.userName, + 'majorVersion': data.majorVersion, + 'minorVersion': data.minorVersion, + 'buildNumber': data.buildNumber, + 'platformId': data.platformId, + 'csdVersion': data.csdVersion, + 'servicePackMajor': data.servicePackMajor, + 'servicePackMinor': data.servicePackMinor, + 'suitMask': data.suitMask, + 'productType': data.productType, + 'reserved': data.reserved, + 'buildLab': data.buildLab, + 'buildLabEx': data.buildLabEx, + 'digitalProductId': data.digitalProductId, + 'displayVersion': data.displayVersion, + 'editionId': data.editionId, + 'installDate': data.installDate, + 'productId': data.productId, + 'productName': data.productName, + 'registeredOwner': data.registeredOwner, + 'releaseId': data.releaseId, + 'deviceId': data.deviceId, + }; } } diff --git a/lib/model/photo_model.dart b/lib/model/photo_model.dart index 80b06cb..f59d486 100644 --- a/lib/model/photo_model.dart +++ b/lib/model/photo_model.dart @@ -2,13 +2,11 @@ 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, 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 1ae3425..f32a88b 100644 --- a/lib/model/visite_model.dart +++ b/lib/model/visite_model.dart @@ -2,32 +2,25 @@ import 'package:mobdr/main.dart'; class VisiteModel { late int id; + late int id_distrib; + late int id_visite; late String name; - late int photo; + late int photoCount; 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 String langage; - 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, - }); + VisiteModel( + {required this.id, + required this.id_distrib, + required this.id_visite, + required this.name, + required this.photoCount, + required this.date, + required this.image, + required this.type_visite, + required this.langage}); static Future> getAllVisites() async { // Retrieve all visits from the database using the getAllVisites() method @@ -36,18 +29,15 @@ class VisiteModel { // Map each retrieved visit to VisiteModel final visiteModels = visites .map((visite) => VisiteModel( + id_distrib: visite.id_distrib_visite, id: visite.id, + id_visite: visite.id_visite, name: visite.title, - photo: 1, + photoCount: objectbox.getVisitPhotoCount(visite.id_visite), 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: "")) + langage: visite.langage)) .toList(); // Return the list of VisiteModel diff --git a/lib/objectbox-model.json b/lib/objectbox-model.json index d6ef092..b98ec04 100644 --- a/lib/objectbox-model.json +++ b/lib/objectbox-model.json @@ -195,7 +195,7 @@ }, { "id": "7:8290500625256822711", - "lastPropertyId": "13:1900114397693432703", + "lastPropertyId": "14:5831680857919010234", "name": "Visite", "properties": [ { @@ -248,6 +248,11 @@ "id": "13:1900114397693432703", "name": "url_photo_principale", "type": 9 + }, + { + "id": "14:5831680857919010234", + "name": "langage", + "type": 9 } ], "relations": [] @@ -332,11 +337,6 @@ "name": "uploaded", "type": 6 }, - { - "id": "15:1865824860595482227", - "name": "image", - "type": 9 - }, { "id": "16:539065583624712715", "name": "image_name", @@ -404,7 +404,8 @@ 5293139139799032553, 2141346538986140281, 7877546811840884522, - 3784190804330297742 + 3784190804330297742, + 1865824860595482227 ], "retiredRelationUids": [], "version": 1 diff --git a/lib/objectbox.dart b/lib/objectbox.dart index e5c7b44..83db299 100644 --- a/lib/objectbox.dart +++ b/lib/objectbox.dart @@ -8,9 +8,6 @@ import 'package:mobdr/db/box_photo.dart'; import 'package:mobdr/db/box_photo_typology.dart'; import 'model.dart'; -import 'package:mobdr/model/visite_model.dart'; -import 'package:mobdr/model/photo_model.dart'; - import 'objectbox.g.dart'; // created by `flutter pub run build_runner build` /// Provides access to the ObjectBox Store throughout the app. @@ -66,6 +63,7 @@ class ObjectBox { userBox.removeAll(); etabBox.removeAll(); concurrentBox.removeAll(); + //visiteBox.removeAll(); //visiteTagBox.removeAll(); //photoBox.removeAll(); @@ -289,7 +287,8 @@ class ObjectBox { int _id_etab, int _abandon, String _end, - String _url_photo_principale) => + String _url_photo_principale, + String _langage) => store.runInTransactionAsync( TxMode.write, _addVisiteInTx, @@ -302,7 +301,8 @@ class ObjectBox { id_distrib_visite: _id_distrib_visite, id_etab: _id_etab, abandon: _abandon, - url_photo_principale: _url_photo_principale)); + url_photo_principale: _url_photo_principale, + langage: _langage)); static void _addVisiteInTx(Store store, _Visite) { store.box().put(_Visite); @@ -367,15 +367,6 @@ class ObjectBox { 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 -------------------------------------------------------------------- /// /// @@ -385,15 +376,14 @@ class ObjectBox { return addedPhotos; } - Future addPhoto(int id_visite, int id_photo_typologie, String image, - String image_name) => + Future addPhoto( + int id_visite, int id_photo_typologie, String image_name) => store.runInTransactionAsync( TxMode.write, _addPhotoInTx, Photo( id_visite: id_visite, id_photo_typologie: id_photo_typologie, - image: image, image_name: image_name)); static void _addPhotoInTx(Store store, _Photo) { @@ -402,11 +392,13 @@ class ObjectBox { store.box().put(_Photo); } - List getAllPhotos() { + List getAllVisitTypologyPhotos( + int id_visite, int _id_photo_typologie) { // Query for all photos, sorted by their date. // https://docs.objectbox.io/queries final query = photoBox - .query() + .query(Photo_.id_visite.equals(id_visite) & + Photo_.id_photo_typologie.equals(_id_photo_typologie)) .order(Photo_.date_photo, flags: Order.descending) .build(); return query.find(); @@ -446,14 +438,58 @@ class ObjectBox { } } - int getVisitPhotoCount(int _id_visite, int _id_Photo_typologie) { + int getVisitPhotoCount(int _id_visite) { + final builder = photoBox.query(Photo_.id_visite.equals(_id_visite)).build(); + return builder.count(); + } + + int getVisitTypologiePhotoCount(int _id_visite, int _id_photo_typologie) { final builder = photoBox .query(Photo_.id_visite.equals(_id_visite) & - Photo_.id_photo_typologie.equals(_id_Photo_typologie)) + Photo_.id_photo_typologie.equals(_id_photo_typologie)) .build(); return builder.count(); } + Future putPhotoTypologie(int photoId, int typologieId) async { + final photo = photoBox.get(photoId); + + if (photo != null) { + final updatedPhoto = photo.copyWith(id_photo_typologie: typologieId); + await photoBox.putAsync(updatedPhoto); + } + } + + 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); + } + } + + Future putPhotoVisibilities( + int photoId, List visibilities) async { + final photo = photoBox.get(photoId); + + if (photo != null) { + final updatedPhoto = photo.copyWith( + photo_principale: visibilities.contains('principal') ? 1 : 0, + photo_privee: visibilities.contains('private') ? 1 : 0); + await photoBox.putAsync(updatedPhoto); + } + } + + /* remettre les principal à zero + final queryBuilder = box.query(Photo_.visite_id.equals(idVisite) & Photo_.photo_principale.equals(1)); + final updatedPhotos = queryBuilder.build().find(); + updatedPhotos.forEach((photo) { + photo.photo_principale = 0; + }); + box.putMany(updatedPhotos); + */ + /// PHOTO TYPOLOGY ----------------------------------------------------------- /// @@ -496,6 +532,13 @@ class ObjectBox { .toList(); } + List getPhotoTypologiesList() { + final query = photoTypologyBox.query().order(PhotoTypology_.ordre).build(); + final photoTypologies = query.find(); + + return photoTypologies.toList(); + } + Stream> getPhotoTypologies() { // Query for all Typologies, sorted by their order. // https://docs.objectbox.io/queries diff --git a/lib/objectbox.g.dart b/lib/objectbox.g.dart index 51a7dd0..2932a61 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(13, 1900114397693432703), + lastPropertyId: const IdUid(14, 5831680857919010234), flags: 0, properties: [ ModelProperty( @@ -272,6 +272,11 @@ final _entities = [ id: const IdUid(13, 1900114397693432703), name: 'url_photo_principale', type: 9, + flags: 0), + ModelProperty( + id: const IdUid(14, 5831680857919010234), + name: 'langage', + type: 9, flags: 0) ], relations: [], @@ -356,11 +361,6 @@ final _entities = [ name: 'uploaded', type: 6, flags: 0), - ModelProperty( - id: const IdUid(15, 1865824860595482227), - name: 'image', - type: 9, - flags: 0), ModelProperty( id: const IdUid(16, 539065583624712715), name: 'image_name', @@ -443,7 +443,8 @@ ModelDefinition getObjectBoxModel() { 5293139139799032553, 2141346538986140281, 7877546811840884522, - 3784190804330297742 + 3784190804330297742, + 1865824860595482227 ], retiredRelationUids: const [], modelVersion: 5, @@ -669,7 +670,8 @@ ModelDefinition getObjectBoxModel() { final titleOffset = fbb.writeString(object.title); final url_photo_principaleOffset = fbb.writeString(object.url_photo_principale); - fbb.startTable(14); + final langageOffset = fbb.writeString(object.langage); + fbb.startTable(15); fbb.addInt64(0, object.id); fbb.addInt64(1, object.id_visite); fbb.addOffset(2, type_visiteOffset); @@ -680,6 +682,7 @@ ModelDefinition getObjectBoxModel() { fbb.addInt64(8, object.abandon); fbb.addInt64(10, object.date_visite.millisecondsSinceEpoch); fbb.addOffset(12, url_photo_principaleOffset); + fbb.addOffset(13, langageOffset); fbb.finish(fbb.endTable()); return object.id; }, @@ -705,9 +708,10 @@ ModelDefinition getObjectBoxModel() { const fb.Int64Reader().vTableGet(buffer, rootOffset, 18, 0), abandon: const fb.Int64Reader().vTableGet(buffer, rootOffset, 20, 0), - url_photo_principale: - const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 28, '')); + url_photo_principale: const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 28, ''), + langage: + const fb.StringReader(asciiOptimization: true).vTableGet(buffer, rootOffset, 30, '')); return object; }), @@ -757,7 +761,6 @@ ModelDefinition getObjectBoxModel() { object.id = id; }, objectToFB: (Photo object, fb.Builder fbb) { - final imageOffset = fbb.writeString(object.image); final image_nameOffset = fbb.writeString(object.image_name); final tagsOffset = fbb.writeString(object.tags); fbb.startTable(18); @@ -769,7 +772,6 @@ ModelDefinition getObjectBoxModel() { fbb.addInt64(7, object.photo_privee); fbb.addInt64(8, object.photo_principale); fbb.addInt64(13, object.uploaded); - fbb.addOffset(14, imageOffset); fbb.addOffset(15, image_nameOffset); fbb.addOffset(16, tagsOffset); fbb.finish(fbb.endTable()); @@ -785,8 +787,6 @@ ModelDefinition getObjectBoxModel() { const fb.Int64Reader().vTableGet(buffer, rootOffset, 8, 0), id_photo_typologie: const fb.Int64Reader().vTableGet(buffer, rootOffset, 10, 0), - image: const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 32, ''), image_name: const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 34, ''), id_photo_mp4: @@ -990,6 +990,10 @@ class Visite_ { /// see [Visite.url_photo_principale] static final url_photo_principale = QueryStringProperty(_entities[5].properties[9]); + + /// see [Visite.langage] + static final langage = + QueryStringProperty(_entities[5].properties[10]); } /// [VisiteTag] entity fields to define ObjectBox queries. @@ -1047,15 +1051,12 @@ class Photo_ { static final uploaded = QueryIntegerProperty(_entities[7].properties[7]); - /// see [Photo.image] - static final image = QueryStringProperty(_entities[7].properties[8]); - /// see [Photo.image_name] static final image_name = - QueryStringProperty(_entities[7].properties[9]); + QueryStringProperty(_entities[7].properties[8]); /// see [Photo.tags] - static final tags = QueryStringProperty(_entities[7].properties[10]); + static final tags = QueryStringProperty(_entities[7].properties[9]); } /// [PhotoTypology] entity fields to define ObjectBox queries. diff --git a/lib/service/shared_prefs.dart b/lib/service/shared_prefs.dart index a48a33c..1ccb2c6 100644 --- a/lib/service/shared_prefs.dart +++ b/lib/service/shared_prefs.dart @@ -102,4 +102,25 @@ class SharedPrefs { set id_visite(int value) { _sharedPrefs.setInt('key_id_visite', value); } + + /// get/set isSimulator + bool get isSimulator => _sharedPrefs.getBool('key_issimulator') ?? false; + + set isSimulator(bool value) { + _sharedPrefs.setBool('key_issimulator', value); + } + + /// get/set application's document directory + String get documentsDir => _sharedPrefs.getString('documentsDir') ?? ""; + + set documentsDir(String value) { + _sharedPrefs.setString('documentsDir', value); + } + + /// get/set application's photo directory + String get photosDir => _sharedPrefs.getString('photosDir') ?? ""; + + set photosDir(String value) { + _sharedPrefs.setString('photosDir', value); + } } diff --git a/lib/ui/home/photo_typology.dart b/lib/ui/home/photo_typology.dart deleted file mode 100644 index b71a078..0000000 --- a/lib/ui/home/photo_typology.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'dart:async'; -import 'package:mobdr/main.dart'; -import 'package:mobdr/config/global_style.dart'; -import 'package:mobdr/config/constant.dart'; -import 'package:flutter/material.dart'; -import 'package:mobdr/db/box_photo_typology.dart'; -import 'package:mobdr/ui/home/photo_list.dart'; - -class PhotoTypologyPage extends StatefulWidget { - @override - _PhotoTypologyPageState createState() => _PhotoTypologyPageState(); -} - -class _PhotoTypologyPageState extends State { - GestureDetector Function(BuildContext, int) _itemBuilder( - List PhotoTypology) => - (BuildContext context, int index) => GestureDetector( - onTap: () { - Route route = - MaterialPageRoute(builder: (context) => PhotoListPage()); - Navigator.push(context, route).then(onGoBack); - }, - - ///objectbox.noteBox.remove(PhotoTypology[index].id), - child: Row( - children: [ - Expanded( - child: Container( - decoration: const BoxDecoration( - border: - Border(bottom: BorderSide(color: Colors.black12))), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 15.0, horizontal: 10.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - PhotoTypology[index].libelle + - " " + - objectbox - .getVisitPhotoCount(0, - PhotoTypology[index].id_photo_typologie) - .toString(), - style: const TextStyle( - fontSize: 15.0, - ), - // Provide a Key for the integration test - key: Key('list_log_$index'), - ), - Icon(Icons.chevron_right, size: 20, color: SOFT_GREY), - ], - ), - ), - ), - ), - ], - ), - ); - - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - - FutureOr onGoBack(dynamic value) { - //refreshData(); - setState(() {}); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - appBar: AppBar( - iconTheme: IconThemeData( - color: GlobalStyle.appBarIconThemeColor, - ), - elevation: GlobalStyle.appBarElevation, - title: Text( - 'Visite de ...', - style: GlobalStyle.appBarTitle, - ), - backgroundColor: GlobalStyle.appBarBackgroundColor, - systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle), - body: Column(children: [ - Expanded( - child: StreamBuilder>( - stream: objectbox.getPhotoTypologies(), - builder: (context, snapshot) => ListView.builder( - shrinkWrap: true, - //padding: const EdgeInsets.symmetric(horizontal: 20.0), - itemCount: snapshot.hasData ? snapshot.data!.length : 0, - itemBuilder: _itemBuilder(snapshot.data ?? [])))) - ])); - } -} diff --git a/lib/ui/home/tab_home.dart b/lib/ui/home/tab_home.dart index ed8d123..3340acb 100644 --- a/lib/ui/home/tab_home.dart +++ b/lib/ui/home/tab_home.dart @@ -3,20 +3,20 @@ This is home page we used AutomaticKeepAliveClientMixin to keep the state when moving from 1 navbar to another navbar, so the page is not refresh overtime */ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; + +import 'package:shared_preferences/shared_preferences.dart'; + 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'; import 'package:mobdr/ui/general/chat_us.dart'; import 'package:mobdr/ui/general/notification.dart'; -import 'package:mobdr/ui/home/photo_typology.dart'; -import 'package:mobdr/ui/general/product_detail/product_detail.dart'; +import 'package:mobdr/ui/home/visit_photo_typology.dart'; import 'package:mobdr/ui/reusable/reusable_widget.dart'; import 'package:mobdr/ui/reusable/cache_image_network.dart'; @@ -44,7 +44,7 @@ class _TabHomePageState extends State bool _isLoading = true; String _errorMessage = ''; - late List visiteData = []; + late List modelData = []; @override void initState() { @@ -91,7 +91,7 @@ class _TabHomePageState extends State final double boxImageSize = (MediaQuery.of(context).size.width / 4); if (_isLoading) { return Center(child: CircularProgressIndicator()); - } else if (visiteData.isEmpty) { + } else if (modelData.isEmpty) { return Center( child: Text('Aucune visite trouvée.'), ); @@ -127,11 +127,11 @@ class _TabHomePageState extends State ), body: AnimatedList( key: _listKey, - initialItemCount: visiteData.length, + initialItemCount: modelData.length, physics: AlwaysScrollableScrollPhysics(), itemBuilder: (context, index, animation) { return _buildVisitelistCard( - visiteData[index], boxImageSize, animation, index); + modelData[index], boxImageSize, animation, index); }, )); } @@ -142,41 +142,44 @@ class _TabHomePageState extends State sizeFactor: animation, child: Container( margin: EdgeInsets.fromLTRB(12, 6, 12, 0), - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - elevation: 2, - color: Colors.white, - child: Container( - margin: EdgeInsets.all(8), - child: Column( - children: [ - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductDetailPage( - name: visiteData.name, - image: visiteData.image, - price: visiteData.price, - photo: visiteData.photo, - rating: visiteData.rating, - review: visiteData.review, - sale: visiteData.sale, - date: visiteData.date))); - }, - child: Row( + child: GestureDetector( + onTap: () { + Route route = MaterialPageRoute( + builder: (context) => VisitPhotoTypologyPage( + pp_id_distrib: visiteData.id_distrib, + pp_langage: visiteData.langage, + pp_id_visite: visiteData.id_visite, + pp_name: visiteData.name, + onRefreshVisit: (int photoCount) { + setState(() { + modelData[index].photoCount = photoCount; + }); + }, + )); + Navigator.push(context, route); + }, + child: Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + elevation: 2, + color: Colors.white, + child: Container( + margin: EdgeInsets.all(8), + child: Column( + children: [ + Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(10)), - child: buildCacheNetworkImage( - width: boxImageSize, - height: boxImageSize, - url: visiteData.image)), + borderRadius: BorderRadius.all(Radius.circular(10)), + child: buildCacheNetworkImage( + width: boxImageSize, + height: boxImageSize, + url: visiteData.image, + ), + ), SizedBox( width: 10, ), @@ -187,34 +190,45 @@ class _TabHomePageState extends State Container(height: 8), Text( visiteData.name, - style: GlobalStyle.productName - .copyWith(fontSize: 13), + style: GlobalStyle.productName.copyWith( + fontSize: 13, + ), maxLines: 3, overflow: TextOverflow.ellipsis, ), Container( margin: EdgeInsets.only(top: 5), - child: Text(visiteData.date, - style: GlobalStyle.productSale), + 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), + '${visiteData.photoCount} Photo(s)', + style: GlobalStyle.productPrice, + ), ), Container(height: 5), Container( margin: EdgeInsets.only(top: 5), child: Row( children: [ - Icon(Icons.store, color: SOFT_GREY, size: 20), - Text(' ' + visiteData.type_visite, - style: GlobalStyle.productName - .copyWith(fontSize: 13), - maxLines: 1, - overflow: TextOverflow.ellipsis) + Icon( + Icons.store, + color: SOFT_GREY, + size: 20, + ), + Text( + ' ' + visiteData.type_visite, + style: GlobalStyle.productName.copyWith( + fontSize: 13, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ) ], ), ), @@ -223,72 +237,8 @@ class _TabHomePageState extends State ) ], ), - ), - Container( - margin: EdgeInsets.only(top: 12), - child: Row( - children: [ - Expanded( - child: (visiteData.stock == 0) - ? TextButton( - style: ButtonStyle( - minimumSize: - MaterialStateProperty.all(Size(0, 30)), - backgroundColor: - MaterialStateProperty.resolveWith( - (Set states) => - Colors.grey[300]!, - ), - overlayColor: MaterialStateProperty.all( - Colors.transparent), - shape: MaterialStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), - )), - ), - onPressed: null, - child: Text( - 'Out of Stock', - style: TextStyle( - color: Colors.grey[600], - fontWeight: FontWeight.bold, - fontSize: 13), - textAlign: TextAlign.center, - )) - : OutlinedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - PhotoTypologyPage())); - }, - style: ButtonStyle( - minimumSize: - MaterialStateProperty.all(Size(0, 30)), - overlayColor: MaterialStateProperty.all( - Colors.transparent), - shape: MaterialStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), - )), - side: MaterialStateProperty.all( - BorderSide(color: SOFT_BLUE, width: 1.0), - )), - child: Text( - AppLocalizations.of(context)! - .translate('i18n_take_pictures')!, - style: TextStyle( - color: SOFT_BLUE, - fontWeight: FontWeight.bold, - fontSize: 13), - textAlign: TextAlign.center, - )), - ), - ], - ), - ) - ], + ], + ), ), ), ), @@ -296,11 +246,21 @@ class _TabHomePageState extends State ); } - // data initialization on loading. + /// Called when a visit is refreshed with new photo count. + /// + /// [index]: The index of the visit being refreshed. + /// [newPhotoCount]: The new photo count for the visit. + void onRefreshVisit(int index, int newPhotoCount) { + setState(() { + modelData[index].photoCount = newPhotoCount; + }); + } + + /// Initializes data when the page loads. Future loadData() async { try { - // visite initialisation - visiteData = await VisiteModel.getAllVisites(); + // visite model initialisation + modelData = await VisiteModel.getAllVisites(); } catch (e) { // set errorMessage for debug _errorMessage = 'Error loading visites : $e'; diff --git a/lib/ui/home/photo_tag.dart b/lib/ui/home/visit_photo_tag.dart similarity index 88% rename from lib/ui/home/photo_tag.dart rename to lib/ui/home/visit_photo_tag.dart index dad5b75..7c3edf9 100644 --- a/lib/ui/home/photo_tag.dart +++ b/lib/ui/home/visit_photo_tag.dart @@ -9,13 +9,19 @@ 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; + final int pp_id_distrib; + final String pp_langage; + final int pp_photoId; + final List pp_currentTags; // Requiring data parameters - const PhotoTagPage( - {Key? key, required this.photoId, required this.currentTags}) - : super(key: key); + const PhotoTagPage({ + Key? key, + required this.pp_id_distrib, + required this.pp_langage, + required this.pp_photoId, + required this.pp_currentTags, + }) : super(key: key); @override _PhotoTagPageState createState() => _PhotoTagPageState(); @@ -187,8 +193,9 @@ class _PhotoTagPageState extends State { const Divider(), ElevatedButton( onPressed: () async { - // Save the selected tags to the database //TODO 1,fr === - await saveSelectedTags(_selectedTags, 1, 'fr'); + // Save the selected tags to the database + await saveSelectedTags( + _selectedTags, widget.pp_id_distrib, widget.pp_langage); Navigator.pop( context, _selectedTags.map((tag) => tag).toList()); @@ -203,9 +210,9 @@ class _PhotoTagPageState extends State { } Future loadData() async { - // TODO 1,fr - allTagsList = await objectbox.getVisiteTagsLabels(1, 'fr'); - _selectedTags = List.from(widget.currentTags); + allTagsList = await objectbox.getVisiteTagsLabels( + widget.pp_id_distrib, widget.pp_langage); + _selectedTags = List.from(widget.pp_currentTags); } /// Saves the selected tags for a photo to the ObjectBox database. @@ -223,20 +230,18 @@ class _PhotoTagPageState extends State { /// Nothing. Future saveSelectedTags( List tags, int distribId, String langage) async { - if (tags.isEmpty) { - return; // exit function without saving tags - } + if (tags.isNotEmpty) { + // determines if there are any new tags + final newTags = tags.where((tag) => !allTagsList.contains(tag)).toList(); - // 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); + 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); + objectbox.putPhotoTags(widget.pp_photoId, tags); } } diff --git a/lib/ui/home/visit_photo_typology.dart b/lib/ui/home/visit_photo_typology.dart new file mode 100644 index 0000000..2e00cd0 --- /dev/null +++ b/lib/ui/home/visit_photo_typology.dart @@ -0,0 +1,166 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; + +import 'package:mobdr/main.dart'; +import 'package:mobdr/config/global_style.dart'; +import 'package:mobdr/config/constant.dart'; +import 'package:mobdr/db/box_photo_typology.dart'; +import 'package:mobdr/ui/home/visit_photo_typology_list.dart'; + +class VisitPhotoTypologyPage extends StatefulWidget { + final int pp_id_distrib; + final String pp_langage; + final int pp_id_visite; + final String pp_name; + final Function(int) onRefreshVisit; + + VisitPhotoTypologyPage( + {Key? key, + required this.pp_id_distrib, + required this.pp_langage, + required this.pp_id_visite, + required this.pp_name, + required this.onRefreshVisit}) + : super(key: key); + + @override + _VisitPhotoTypologyPageState createState() => _VisitPhotoTypologyPageState(); +} + +class _VisitPhotoTypologyPageState extends State { + GestureDetector Function(BuildContext, int) _itemBuilder( + List PhotoTypology) => + (BuildContext context, int index) => GestureDetector( + onTap: () { + Route route = MaterialPageRoute( + builder: (context) => VisitPhotoTypologyListPage( + pp_id_distrib: widget.pp_id_distrib, + pp_langage: widget.pp_langage, + pp_id_visite: widget.pp_id_visite, + pp_id_typologie: + PhotoTypology[index].id_photo_typologie, + pp_libelle_typologie: PhotoTypology[index].libelle, + )); + Navigator.push(context, route).then(onGoBack); + }, + + /// TODO objectbox.noteBox.remove(PhotoTypology[index].id), + child: Container( + decoration: const BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.black12)), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 15.0, horizontal: 10.0), + child: Row( + children: [ + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _buildBadge( + widget.pp_id_visite, + PhotoTypology[index].id_photo_typologie, + PhotoTypology[index].libelle), + Icon(Icons.chevron_right, size: 20, color: SOFT_GREY), + ], + ), + ), + ], + ), + ), + ), + ); + + Widget _buildBadge(int visitId, int photoTypologyId, String libelle) { + int photoCount = + objectbox.getVisitTypologiePhotoCount(visitId, photoTypologyId); + if (photoCount > 0) { + return Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + libelle, + style: const TextStyle( + fontSize: 15.0, + fontWeight: FontWeight.bold, + ), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 6, vertical: 4), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.blue, + ), + child: Text( + photoCount.toString(), + style: TextStyle(color: Colors.white), + ), + ), + ], + ), + ); + } else { + return Text( + libelle, + style: const TextStyle( + fontSize: 15.0, + ), + ); + } + } + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + FutureOr onGoBack(dynamic value) { + setState(() {}); + } + + Future onBackPressed() async { + // Navigate back to the visits page and refresh the data + int newPhotoCount = objectbox.getVisitPhotoCount(widget.pp_id_visite); + widget.onRefreshVisit(newPhotoCount); + return true; + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + return onBackPressed(); + }, + child: Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + iconTheme: IconThemeData( + color: GlobalStyle.appBarIconThemeColor, + ), + elevation: GlobalStyle.appBarElevation, + title: Text( + widget.pp_name, + style: GlobalStyle.appBarTitle, + ), + backgroundColor: GlobalStyle.appBarBackgroundColor, + systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle), + body: Column(children: [ + Expanded( + child: StreamBuilder>( + stream: objectbox.getPhotoTypologies(), + builder: (context, snapshot) => ListView.builder( + shrinkWrap: true, + //padding: const EdgeInsets.symmetric(horizontal: 20.0), + itemCount: + snapshot.hasData ? snapshot.data!.length : 0, + itemBuilder: _itemBuilder(snapshot.data ?? [])))) + ]))); + } +} diff --git a/lib/ui/home/photo_list.dart b/lib/ui/home/visit_photo_typology_list.dart similarity index 59% rename from lib/ui/home/photo_list.dart rename to lib/ui/home/visit_photo_typology_list.dart index 9292ebf..83bdb55 100644 --- a/lib/ui/home/photo_list.dart +++ b/lib/ui/home/visit_photo_typology_list.dart @@ -1,21 +1,24 @@ -import 'dart:developer' as developer; import 'dart:async'; import 'dart:io'; +import 'package:intl/intl.dart'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:image/image.dart' as img; + import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'package:mobdr/config/constant.dart'; +import 'package:mobdr/service/shared_prefs.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/ui/home/visite_photo_typology_detail.dart'; import 'package:mobdr/db/box_photo.dart'; -import 'package:mobdr/ui/home/photo_detail.dart'; // TODO Il faut supprimer les possibles photos du répertoire cache ! @@ -26,17 +29,32 @@ extension FileNameExtension on File { } } -class PhotoListPage extends StatefulWidget { +class VisitPhotoTypologyListPage extends StatefulWidget { + final int pp_id_distrib; + final String pp_langage; + final int pp_id_visite; + final int pp_id_typologie; + final String pp_libelle_typologie; + + VisitPhotoTypologyListPage( + {required this.pp_id_distrib, + required this.pp_langage, + required this.pp_id_visite, + required this.pp_id_typologie, + required this.pp_libelle_typologie}); + @override - _PhotoListPageState createState() => _PhotoListPageState(); + _VisitPhotoTypologyListPageState createState() => + _VisitPhotoTypologyListPageState(); } -class _PhotoListPageState extends State { +class _VisitPhotoTypologyListPageState + extends State { final _globalWidget = GlobalWidget(); // initialize photos files list - final List photoFiles = []; - List _photoData = []; + final List _visitPhotoFiles = []; + List _visitPhotoData = []; Color _color1 = Color(0xff777777); Color _color2 = Color(0xFF515151); @@ -47,7 +65,7 @@ class _PhotoListPageState extends State { @override void initState() { super.initState(); - _loadData(); + loadData(); } @override @@ -55,10 +73,6 @@ class _PhotoListPageState extends State { super.dispose(); } - void _loadData() { - _photoData = objectbox.getAllPhotos(); - } - @override Widget build(BuildContext context) { final double boxImageSize = (MediaQuery.of(context).size.width / 4); @@ -70,7 +84,7 @@ class _PhotoListPageState extends State { systemOverlayStyle: SystemUiOverlayStyle.dark, elevation: 0, title: Text( - 'Catégorie : A trier', + widget.pp_libelle_typologie, style: TextStyle(fontSize: 18, color: Colors.black), ), backgroundColor: Colors.white, @@ -95,16 +109,107 @@ class _PhotoListPageState extends State { }), ], ), - body: AnimatedList( - key: _listKey, - initialItemCount: _photoData.length, - physics: AlwaysScrollableScrollPhysics(), - itemBuilder: (context, index, animation) { - return _buildPhotolistCard( - _photoData[index], boxImageSize, animation, index); - }, - ), - floatingActionButton: fabCart(context)); + body: Column(children: [ + Flexible( + child: AnimatedList( + key: _listKey, + initialItemCount: _visitPhotoData.length, + physics: AlwaysScrollableScrollPhysics(), + itemBuilder: (context, index, animation) { + return _buildPhotolistCard( + _visitPhotoData[index], boxImageSize, animation, index); + }, + ), + ), + Container( + padding: EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.grey, + offset: Offset(0.0, 1.0), //(x,y) + blurRadius: 2.0, + ), + ], + ), + child: Row( + children: [ + Container( + child: GestureDetector( + onTap: () { + // TODO functionality to be implemented + /*` + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ChatUsPage())); + */ + }, + child: ClipOval( + child: Container( + color: SOFT_BLUE, + padding: EdgeInsets.all(9), + child: + Icon(Icons.chat, color: Colors.white, size: 16)), + ), + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: GestureDetector( + onTap: () async { + // clear photoFiles list before taking photos + _visitPhotoFiles.clear(); + + // if we are not on a simulator + if (SharedPrefs().isSimulator == false) { + Route route = MaterialPageRoute( + builder: (context) => + CameraPage(photoFiles: _visitPhotoFiles)); + Navigator.push(context, route).then((val) { + // Restore the constraint before navigating away + // DO await here to avoid any other screen in + // landscape mode + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + ]); + + // if the user has validated photos + if (val == true) { + savePhotos(); + } + }); + } else { + // simulates the taking of a photo + final File imageFile = + await copyImageFromAssetsToTemporaryDirectory(); + _visitPhotoFiles.add(imageFile); + savePhotos(); + } + }, + child: Container( + alignment: Alignment.center, + padding: EdgeInsets.fromLTRB(12, 8, 12, 8), + margin: EdgeInsets.only(right: 8), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(width: 1, color: SOFT_BLUE), + borderRadius: BorderRadius.all(Radius.circular( + 10) // <--- border radius here + )), + child: Text('Prendre des photos', + style: TextStyle( + color: SOFT_BLUE, fontWeight: FontWeight.bold)), + ), + ), + ), + ], + ), + ) + ])); } Widget _buildPhotolistCard(Photo photoData, boxImageSize, animation, index) { @@ -124,24 +229,31 @@ class _PhotoListPageState extends State { children: [ GestureDetector( onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PhotoDetailPage( - id: _photoData[index].id, - name: 'visiteData.name', - image: _photoData[index].image, - price: 0, - photo: 1, - rating: 0, - review: 0, - sale: 0, - date: ''))); + Route route = MaterialPageRoute( + builder: (context) => VisitPhotoTypologyDetailPage( + pp_id: _visitPhotoData[index].id, + pp_id_distrib: widget.pp_id_distrib, + pp_langage: widget.pp_langage, + pp_image: _visitPhotoData[index].getImage(), + pp_id_typologie: widget.pp_id_typologie, + )); - // todo if qq chose à changé - // ne raffraichir que le widget en cours == - setState(() { - _listKey = GlobalKey(); + Navigator.push(context, route).then((result) { + if (result['change_typologie']) { + // the photo must be removed + setState(() { + _visitPhotoData.removeAt(index); + _listKey = GlobalKey(); + }); + } else { + setState(() { + _visitPhotoData[index].tags = result['tags']; + _visitPhotoData[index].photo_principale = + result['photo_principale']; + _visitPhotoData[index].photo_privee = + result['photo_privee']; + }); + } }); }, child: Row( @@ -150,7 +262,7 @@ class _PhotoListPageState extends State { children: [ ClipRRect( borderRadius: BorderRadius.all(Radius.circular(10)), - child: Image.file(File(photoData.image), + child: Image.file(File(photoData.getImage()), fit: BoxFit.cover, height: 100, width: 150), ), SizedBox( @@ -160,54 +272,34 @@ class _PhotoListPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Container( + margin: EdgeInsets.only(top: 5), + child: Row( + children: [ + Text( + DateFormat('dd/MM/yyyy HH:mm:ss') + .format(photoData.date_photo), + style: TextStyle( + fontSize: 11, color: SOFT_GREY)) + ], + ), + ), + Container(height: 8), Text( - photoData.id_photo_typologie.toString(), + "Private : ${photoData.photo_privee == 1 ? 'Yes' : 'No'}", style: TextStyle(fontSize: 13, color: _color2), maxLines: 3, overflow: TextOverflow.ellipsis, ), Container( margin: EdgeInsets.only(top: 5), - child: Text((index + 1).toString(), + child: Text( + '${photoData.tags.isNotEmpty ? (photoData.tags.length > 53 ? '${photoData.tags.substring(0, 50)}...' : photoData.tags) : "notag"}', style: TextStyle( fontSize: 13, fontWeight: FontWeight.bold)), ), - Container( - margin: EdgeInsets.only(top: 5), - child: Row( - children: [ - Icon(Icons.location_on, - color: SOFT_GREY, size: 12), - Text(' ' + photoData.image_name, - style: TextStyle( - fontSize: 11, color: SOFT_GREY)) - ], - ), - ), - Container( - margin: EdgeInsets.only(top: 5), - child: Row( - children: [ - Text( - '(' + - photoData.id_photo_typologie - .toString() + - ')', - style: TextStyle( - fontSize: 11, color: SOFT_GREY)) - ], - ), - ), - Container( - margin: EdgeInsets.only(top: 5), - child: Text( - photoData.id_photo_typologie.toString() + - ' ' + - 'Sale', - style: TextStyle( - fontSize: 11, color: SOFT_GREY)), - ), + Container(height: 8), ], ), ) @@ -279,12 +371,12 @@ class _PhotoListPageState extends State { borderRadius: BorderRadius.circular(5.0), )), side: MaterialStateProperty.all( - BorderSide(color: SOFT_BLUE, width: 1.0), + BorderSide(color: SOFT_GREY, width: 1.0), )), child: Text( 'Copier dans galerie', style: TextStyle( - color: SOFT_BLUE, + color: SOFT_GREY, fontWeight: FontWeight.bold, fontSize: 13), textAlign: TextAlign.center, @@ -297,7 +389,7 @@ class _PhotoListPageState extends State { behavior: HitTestBehavior.translucent, onTap: () async { await rotateAndReplaceImage( - File(_photoData[index].image), 90); + File(_visitPhotoData[index].getImage()), 90); setState(() { _listKey = GlobalKey(); }); @@ -322,7 +414,7 @@ class _PhotoListPageState extends State { behavior: HitTestBehavior.translucent, onTap: () async { await rotateAndReplaceImage( - File(_photoData[index].image), -90); + File(_visitPhotoData[index].getImage()), -90); setState(() { _listKey = GlobalKey(); }); @@ -351,78 +443,33 @@ class _PhotoListPageState extends State { ); } - Widget fabCart(context) { - return FloatingActionButton( - onPressed: () { - photoFiles.clear(); - Route route = MaterialPageRoute( - builder: (context) => CameraPage(photoFiles: photoFiles)); - Navigator.push(context, route).then((val) { - // Restore the constraint before navigating away - // DO await here to avoid any other screen in - // landscape mode - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitUp, - ]); - - /// if the user has validated photos - if (val == true) { - savePhotos(); - } - }); - }, - child: Stack(children: [ - Icon(Icons.add_a_photo, color: BLACK21, size: 42), - Positioned( - right: 0, - bottom: 0, - child: Container( - padding: EdgeInsets.all(1), - decoration: BoxDecoration( - color: PRIMARY_COLOR, - borderRadius: BorderRadius.circular(14), - ), - constraints: BoxConstraints( - minWidth: 16, - minHeight: 16, - ), - child: Center( - child: Text( - _photoData.length.toString(), - style: TextStyle( - color: Colors.white, - fontSize: 8, - ), - textAlign: TextAlign.center, - ), - ), - ), - ) - ]), - backgroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(4.0))), - ); + // TODO ƒuture void ? + void loadData() { + _visitPhotoData = objectbox.getAllVisitTypologyPhotos( + widget.pp_id_visite, widget.pp_id_typologie); } + /// Removes the image at the specified [imageURL] from the cache of the [NetworkImage] provider. + /// Returns a boolean indicating whether the image was successfully evicted. Future evictImage(String imageURL) async { final NetworkImage provider = NetworkImage(imageURL); return await provider.evict(); } + /// Saves photos to the database and updates the widget with the new photos. + /// void savePhotos() async { - if (photoFiles.length > 0) { + if (_visitPhotoFiles.length > 0) { final List _listPhotos = []; - for (var myTmpPhoto in photoFiles) { + for (var myTmpPhoto in _visitPhotoFiles) { /// move jpg file to photo directory final myPhoto = await moveFileFromTempToPhotosDir(myTmpPhoto); /// to insert into database _listPhotos.add(Photo( - id_visite: 0, - id_photo_typologie: 0, - image: myPhoto.path, + id_visite: widget.pp_id_visite, + id_photo_typologie: widget.pp_id_typologie, image_name: myPhoto.path.split('/').last)); } @@ -430,7 +477,7 @@ class _PhotoListPageState extends State { final addedPhotos = await objectbox.addPhotos(_listPhotos); /// insert photo(s) in widget at the beginning (0) - _photoData.insertAll(0, addedPhotos); + _visitPhotoData.insertAll(0, addedPhotos); /// refresh widget setState(() { @@ -439,6 +486,11 @@ class _PhotoListPageState extends State { } } + /// Deletes the given file if it exists. + /// + /// Returns nothing. + /// + /// Throws an error if there was an issue deleting the file. Future deleteFile(File file) async { try { if (await file.exists()) { @@ -451,6 +503,13 @@ class _PhotoListPageState extends State { } } + /// Shows an alert dialog to confirm the deletion of a photo from the visit and + /// removes it from the list of photos. Also deletes the photo file from the + /// database and local storage. + /// + /// Parameters: + /// - index : index of the photo in the list to be deleted. + /// - boxImageSize : size of the image to be displayed in the list. void showPopupDeletePhoto(index, boxImageSize) { // set up the buttons Widget cancelButton = TextButton( @@ -461,13 +520,13 @@ class _PhotoListPageState extends State { Widget continueButton = TextButton( onPressed: () { int removeIndex = index; - var removedItem = _photoData.removeAt(removeIndex); + var removedItem = _visitPhotoData.removeAt(removeIndex); // delete file on database objectbox.delPhoto(removedItem.image_name); // delete file on local storage - deleteFile(new File(removedItem.image)); + deleteFile(new File(removedItem.getImage())); // This builder is just so that the animation has something // to work with before it disappears from view since the original @@ -512,13 +571,18 @@ class _PhotoListPageState extends State { ); } + // Moves a temporary file to the photos directory in the app's document directory. + /// + /// Returns a `File` object for the new file in the photos directory. + /// + /// Parameters: + /// * `tempFile`: The temporary `File` object to move to the photos directory. + /// + /// Throws a `FileSystemException` if there is an error renaming the file. Future moveFileFromTempToPhotosDir(File tempFile) async { - // Get the application's document directory - final Directory documentsDir = await getApplicationDocumentsDirectory(); - // Set the new file path with the original file name final String newPath = - '${documentsDir.path}/photos/${tempFile.path.split('/').last}'; + '${SharedPrefs().photosDir}/${tempFile.path.split('/').last}'; // Rename the file to move it to the documents directory await tempFile.rename(newPath); @@ -527,6 +591,13 @@ class _PhotoListPageState extends State { return File(newPath); } + /// Rotates the image file clockwise by the specified angle (in degrees) and overwrites the original file with the rotated image. + /// + /// Parameters: + /// - `imageFile`: The image file to rotate and replace. + /// - `angle`: The angle (in degrees) by which to rotate the image. Valid values are 90, 180, and 270. + /// + /// Throws an exception if there is an error in the rotation process. Future rotateAndReplaceImage(File imageFile, int angle) async { // Read the image file into a Uint8List Uint8List bytes = await imageFile.readAsBytes(); @@ -546,4 +617,19 @@ class _PhotoListPageState extends State { // remove the flutter cache image FileImage(imageFile).evict(); } + + /// Copies the 'simulator.jpg' image file from the app's assets to a randomly named file in the app's temporary directory and returns the File object. + /// The temporary file name will start with 'sim_'. + Future copyImageFromAssetsToTemporaryDirectory() async { + final String randomName = 'sim_${DateTime.now().microsecondsSinceEpoch}'; + final Directory tempDir = await getTemporaryDirectory(); + final String tempPath = tempDir.path; + final String assetPath = 'assets/images/simulator.jpeg'; + + final ByteData data = await rootBundle.load(assetPath); + final File tempFile = File('$tempPath/$randomName.jpeg'); + await tempFile.writeAsBytes(data.buffer.asUint8List(), flush: true); + + return tempFile; + } } diff --git a/lib/ui/home/photo_detail.dart b/lib/ui/home/visite_photo_typology_detail.dart similarity index 58% rename from lib/ui/home/photo_detail.dart rename to lib/ui/home/visite_photo_typology_detail.dart index 32b8ac2..cb13d7e 100644 --- a/lib/ui/home/photo_detail.dart +++ b/lib/ui/home/visite_photo_typology_detail.dart @@ -5,79 +5,59 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:mobdr/config/constant.dart'; +import 'package:mobdr/service/shared_prefs.dart'; import 'package:mobdr/config/global_style.dart'; 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/ui/home/visit_photo_tag.dart'; import 'package:mobdr/db/box_photo.dart'; +import 'package:mobdr/db/box_photo_typology.dart'; -class PhotoDetailPage extends StatefulWidget { +//TODO : faire concurrents === + +class VisitPhotoTypologyDetailPage 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; - final int review; - final int sale; - final String date; + final int pp_id; + final int pp_id_distrib; + final String pp_langage; + final String pp_image; + final int pp_id_typologie; // 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, - this.review = 45, - this.sale = 63, - this.date = ''}) - : super(key: key); + VisitPhotoTypologyDetailPage({ + Key? key, + required this.pp_id, + required this.pp_id_distrib, + required this.pp_langage, + required this.pp_image, + required this.pp_id_typologie, + }) : super(key: key); @override - _PhotoDetailPageState createState() => _PhotoDetailPageState(); + _VisitPhotoTypologyDetailPageState createState() => + _VisitPhotoTypologyDetailPageState(); } -class _PhotoDetailPageState extends State { - // initialize global function and reusable widget - final _globalFunction = GlobalFunction(); - final _reusableWidget = ReusableWidget(); - +class _VisitPhotoTypologyDetailPageState + extends State { bool _isLoading = true; String _errorMessage = ''; // Typology list - late List _typologyList = []; + late List _typologyList = []; int _typologyIndex = 0; - List _chickenParts = []; - int _maxChickenParts = 2; + List _visibilities = []; - // shopping cart count - int _shoppingCartCount = 3; - - late String tags = ""; late List tagList = []; - late Photo _photo; @override void initState() { super.initState(); - loadData(widget.id).then((_) { + loadData(widget.pp_id).then((_) { setState(() { _isLoading = false; }); @@ -111,71 +91,31 @@ class _PhotoDetailPageState extends State { } return Scaffold( appBar: AppBar( - iconTheme: IconThemeData( - color: GlobalStyle.appBarIconThemeColor, - ), - elevation: GlobalStyle.appBarElevation, - titleSpacing: 0.0, - // create search text field in the app bar - title: Container( - margin: EdgeInsets.only(right: 16), - child: TextButton( - style: ButtonStyle( - backgroundColor: MaterialStateProperty.resolveWith( - (Set states) => Colors.grey[100]!, - ), - overlayColor: MaterialStateProperty.all(Colors.transparent), - shape: MaterialStateProperty.all(RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), - )), - ), - onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) => SearchPage())); - }, - child: Row( - children: [ - SizedBox(width: 8), - Icon(Icons.search, color: Colors.grey[500], size: 18), - SizedBox(width: 8), - Text( - 'Search Product', - style: TextStyle( - fontSize: 13, - color: Colors.grey[600], - fontWeight: FontWeight.normal), - ) - ], - )), - ), - backgroundColor: GlobalStyle.appBarBackgroundColor, - systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle, - actions: [ - IconButton( - padding: EdgeInsets.all(0), - constraints: BoxConstraints(), - icon: _customShoppingCart(_shoppingCartCount), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => TabShoppingCartPage())); - }), - IconButton( - icon: _reusableWidget.customNotifIcon( - count: 8, notifColor: BLACK_GREY), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => NotificationPage())); - }), - ], - bottom: _reusableWidget.bottomAppBar(), - ), + iconTheme: IconThemeData( + color: GlobalStyle.appBarIconThemeColor, + ), + elevation: GlobalStyle.appBarElevation, + title: Text( + 'Photo', + style: GlobalStyle.appBarTitle, + ), + backgroundColor: GlobalStyle.appBarBackgroundColor, + systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle), body: WillPopScope( onWillPop: () { - Navigator.pop(context); + // fred + Map result = { + 'change_typologie': _typologyIndex != + _typologyList.indexWhere((typology) => + typology.id_photo_typologie == widget.pp_id_typologie), + 'tags': tagList.join(","), + 'photo_principale': _visibilities.contains('principal') ? 1 : 0, + 'photo_privee': _visibilities.contains('private') ? 1 : 0, + }; + + // return to the parent page fred + Navigator.pop(context, result); + return Future.value(true); }, child: Column( @@ -183,8 +123,7 @@ class _PhotoDetailPageState extends State { Flexible( child: ListView( children: [ - Image.file(File(widget.image), fit: BoxFit.cover), - //_createProductSlider(), + Image.file(File(widget.pp_image), fit: BoxFit.cover), _buildPhotoTypology(), _buildPhotoVisibility(), _buildPhotoTag(context), @@ -230,7 +169,7 @@ class _PhotoDetailPageState extends State { child: GestureDetector( onTap: () { setState(() { - _shoppingCartCount++; + //_shoppingCartCount++; }); Fluttertoast.showToast( msg: 'Item has been added to Shopping Cart', @@ -246,7 +185,7 @@ class _PhotoDetailPageState extends State { borderRadius: BorderRadius.all(Radius.circular( 10) // <--- border radius here )), - child: Text('Add to Shopping Cart', + child: Text('Copier dans galerie', style: TextStyle( color: SOFT_BLUE, fontWeight: FontWeight.bold)), @@ -261,38 +200,6 @@ class _PhotoDetailPageState extends State { )); } - Widget _customShoppingCart(int count) { - return Stack( - children: [ - Icon(Icons.shopping_cart, color: BLACK_GREY), - Positioned( - right: 0, - child: Container( - padding: EdgeInsets.all(1), - decoration: BoxDecoration( - color: ASSENT_COLOR, - borderRadius: BorderRadius.circular(10), - ), - constraints: BoxConstraints( - minWidth: 14, - minHeight: 14, - ), - child: Center( - child: Text( - count.toString(), - style: TextStyle( - color: Colors.white, - fontSize: 8, - ), - textAlign: TextAlign.center, - ), - ), - ), - ) - ], - ); - } - Widget _buildPhotoTypology() { return Container( margin: EdgeInsets.only(top: 12), @@ -307,7 +214,7 @@ class _PhotoDetailPageState extends State { ), Wrap( children: List.generate(_typologyList.length, (index) { - return radioSize(_typologyList[index], index); + return radioSize(_typologyList[index].libelle, index); }), ), ], @@ -316,7 +223,11 @@ class _PhotoDetailPageState extends State { Widget radioSize(String txt, int index) { return GestureDetector( - onTap: () { + onTap: () async { + // save photo typology in the database + objectbox.putPhotoTypologie( + widget.pp_id, _typologyList[index].id_photo_typologie); + setState(() { _typologyIndex = index; }); @@ -339,20 +250,20 @@ class _PhotoDetailPageState extends State { ); } - // TODO changer chicken - Widget _checboxChicken({value = 'breast', primaryText = 'Chicken Breast'}) { + Widget _checkboxVisibility({value, primaryText}) { return GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { setState(() { - if (_chickenParts.contains(value)) { - _chickenParts.remove(value); + if (_visibilities.contains(value)) { + _visibilities.remove(value); } else { - if (_chickenParts.length < _maxChickenParts) { - _chickenParts.add(value); - } + _visibilities.add(value); } }); + + // save photo visibilities in the database + objectbox.putPhotoVisibilities(widget.pp_id, _visibilities); }, child: Row( children: [ @@ -360,14 +271,14 @@ class _PhotoDetailPageState extends State { decoration: BoxDecoration( border: Border.all( width: 1, - color: (_chickenParts.contains(value)) + color: (_visibilities.contains(value)) ? PRIMARY_COLOR : BLACK77), borderRadius: BorderRadius.all(Radius.circular(4.0)), ), child: Padding( padding: const EdgeInsets.all(2), - child: (_chickenParts.contains(value)) + child: (_visibilities.contains(value)) ? Icon( Icons.check, size: 12.0, @@ -385,7 +296,7 @@ class _PhotoDetailPageState extends State { style: TextStyle( fontSize: 13, color: BLACK77, - fontWeight: (_chickenParts.contains(value)) + fontWeight: (_visibilities.contains(value)) ? FontWeight.bold : FontWeight.normal)), ], @@ -406,12 +317,12 @@ class _PhotoDetailPageState extends State { ], ), SizedBox(height: 16), - _checboxChicken(value: 'public', primaryText: 'Public'), + _checkboxVisibility(value: 'private', primaryText: 'Privée'), Divider( height: 32, color: Colors.grey[400], ), - _checboxChicken(value: 'principal', primaryText: 'Principal') + _checkboxVisibility(value: 'principal', primaryText: 'Principale') ], ), ); @@ -424,8 +335,11 @@ class _PhotoDetailPageState extends State { final newTags = await Navigator.push>( context, MaterialPageRoute( - builder: (context) => - PhotoTagPage(photoId: this._photo.id, currentTags: tagList), + builder: (context) => PhotoTagPage( + pp_langage: widget.pp_langage, + pp_id_distrib: widget.pp_id_distrib, + pp_photoId: this._photo.id, + pp_currentTags: tagList), ), ); @@ -465,18 +379,27 @@ class _PhotoDetailPageState extends State { ); } - /// data initialization on loading. + /// Initializes data when the page loads. Future loadData(int photoId) async { + String tags = ""; + try { // photo typologies initialization - _typologyList = objectbox.getPhotoTypologiesLabels(); + _typologyList = objectbox.getPhotoTypologiesList(); + + _typologyIndex = _typologyList.indexWhere( + (typology) => typology.id_photo_typologie == widget.pp_id_typologie); // get photo object _photo = objectbox.getPhotoById(photoId)!; + // visibilities initialization + if (_photo.photo_privee == 1) _visibilities.add('private'); + if (_photo.photo_principale == 1) _visibilities.add('principal'); + // photo tag initialization tags = _photo.tags; - tagList = tags.isEmpty ? [] : tags.split(","); + tagList = tags.isEmpty ? [] : _photo.tags.split(","); } catch (e) { // set errorMessage for debug _errorMessage = 'Error loading photo: $e'; diff --git a/lib/ui/sync/tab_sync.dart b/lib/ui/sync/tab_sync.dart index 40d2895..325ae86 100644 --- a/lib/ui/sync/tab_sync.dart +++ b/lib/ui/sync/tab_sync.dart @@ -4,7 +4,6 @@ we used AutomaticKeepAliveClientMixin to keep the state when moving from 1 navba */ import 'package:mobdr/config/global_style.dart'; -import 'package:mobdr/main.dart'; import 'package:mobdr/ui/reusable/reusable_widget.dart'; import 'package:mobdr/network/api_provider.dart'; import 'package:flutter/material.dart'; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 049788b..83c4826 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,7 @@ import FlutterMacOS import Foundation +import device_info_plus import objectbox_flutter_libs import package_info_plus import path_provider_foundation @@ -13,6 +14,7 @@ import sqflite import wakelock_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) ObjectboxFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "ObjectboxFlutterLibsPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 7e1f7a8..ce8e0ea 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -149,10 +149,10 @@ packages: dependency: "direct main" description: name: camera - sha256: ad1c53c554a2f3e5708f3b01eb738d60b902bb61f7f4ad420c65c715e65a7379 + sha256: "7afc256902062cab191540c09908b98bc71e93d5e20b6486dbee51aa7731e9b2" url: "https://pub.dev" source: hosted - version: "0.10.3+2" + version: "0.10.4" camera_android: dependency: transitive description: @@ -297,6 +297,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + sha256: "435383ca05f212760b0a70426b5a90354fe6bd65992b3a5e27ab6ede74c02f5c" + url: "https://pub.dev" + source: hosted + version: "8.2.0" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" + source: hosted + version: "7.0.0" dio: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 64b04d0..2f0dd83 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -52,7 +52,10 @@ dependencies: shimmer: 2.0.0 image_picker: ^0.8.7 - camera: ^0.10.3+2 + + # https://pub.dev/packages/camera + camera: ^0.10.4 + permission_handler: 10.2.0 image: ^4.0.15 @@ -75,6 +78,9 @@ dependencies: universal_io: 2.2.0 xml: ^6.2.2 + # https://pub.dev/packages/device_info_plus/install + device_info_plus: ^8.2.0 + dev_dependencies: flutter_test: sdk: flutter @@ -148,6 +154,7 @@ flutter: - assets/images/process_timeline/status3.png - assets/images/process_timeline/status4.png - assets/images/process_timeline/status5.png + - assets/images/simulator.jpeg - assets/lang/fr.json - assets/lang/en.json