diff --git a/.env b/.env index bb4b7b6..3d3921e 100644 --- a/.env +++ b/.env @@ -95,4 +95,5 @@ V=P W=T X=D Y=S -Z=M \ No newline at end of file +Z=M +emailService=seferservice@gmail.com diff --git a/android/app/build.gradle b/android/app/build.gradle index d5fb2ae..5d2fe05 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -55,8 +55,8 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdkVersion 23 targetSdkVersion 34 - versionCode 57 - versionName '1.5.57' + versionCode 58 + versionName '1.5.58' // manifestPlaceholders = [mapsApiKey: 'android/app/src/main/AndroidManifest.xml'] } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1bacb0c..83a2531 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -61,6 +61,11 @@ PODS: - GoogleUtilities/UserDefaults (~> 7.8) - nanopb (< 2.30911.0, >= 2.30908.0) - Flutter (1.0.0) + - flutter_image_compress_common (1.0.0): + - Flutter + - Mantle + - SDWebImage + - SDWebImageWebPCoder - flutter_local_notifications (0.0.1): - Flutter - flutter_secure_storage (6.0.0): @@ -153,10 +158,25 @@ PODS: - Flutter - just_audio (0.0.1): - Flutter + - libwebp (1.3.2): + - libwebp/demux (= 1.3.2) + - libwebp/mux (= 1.3.2) + - libwebp/sharpyuv (= 1.3.2) + - libwebp/webp (= 1.3.2) + - libwebp/demux (1.3.2): + - libwebp/webp + - libwebp/mux (1.3.2): + - libwebp/demux + - libwebp/sharpyuv (1.3.2) + - libwebp/webp (1.3.2): + - libwebp/sharpyuv - local_auth_ios (0.0.1): - Flutter - location (0.0.1): - Flutter + - Mantle (2.2.0): + - Mantle/extobjc (= 2.2.0) + - Mantle/extobjc (2.2.0) - MLImage (1.0.0-beta5) - MLKitCommon (11.0.0): - GoogleDataTransport (< 10.0, >= 9.4.1) @@ -195,6 +215,12 @@ PODS: - record_darwin (1.0.0): - Flutter - FlutterMacOS + - SDWebImage (5.19.4): + - SDWebImage/Core (= 5.19.4) + - SDWebImage/Core (5.19.4) + - SDWebImageWebPCoder (0.14.6): + - libwebp (~> 1.0) + - SDWebImage/Core (~> 5.17) - share (0.0.1): - Flutter - sign_in_with_apple (0.0.1): @@ -260,6 +286,7 @@ DEPENDENCIES: - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - Flutter (from `Flutter`) + - flutter_image_compress_common (from `.symlinks/plugins/flutter_image_compress_common/ios`) - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - flutter_tts (from `.symlinks/plugins/flutter_tts/ios`) @@ -307,6 +334,8 @@ SPEC REPOS: - GoogleUtilitiesComponents - GTMAppAuth - GTMSessionFetcher + - libwebp + - Mantle - MLImage - MLKitCommon - MLKitTextRecognition @@ -315,6 +344,8 @@ SPEC REPOS: - nanopb - PromisesObjC - RecaptchaInterop + - SDWebImage + - SDWebImageWebPCoder - Stripe - StripeApplePay - StripeCore @@ -342,6 +373,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_messaging/ios" Flutter: :path: Flutter + flutter_image_compress_common: + :path: ".symlinks/plugins/flutter_image_compress_common/ios" flutter_local_notifications: :path: ".symlinks/plugins/flutter_local_notifications/ios" flutter_secure_storage: @@ -412,6 +445,7 @@ SPEC CHECKSUMS: FirebaseInstallations: 91950fe859846fff0fbd296180909dd273103b09 FirebaseMessaging: 88950ba9485052891ebe26f6c43a52bb62248952 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be flutter_tts: 0f492aab6accf87059b72354fcb4ba934304771d @@ -433,8 +467,10 @@ SPEC CHECKSUMS: image_cropper: a3291c624a953049bc6a02e1f8c8ceb162a24b25 image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa + libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605 location: d5cf8598915965547c3f36761ae9cc4f4e87d22e + Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d MLImage: 1824212150da33ef225fbd3dc49f184cf611046c MLKitCommon: afec63980417d29ffbb4790529a1b0a2291699e1 MLKitTextRecognition: c83c18ad25496f2077f6ec93c5940487ff2eb343 @@ -447,6 +483,8 @@ SPEC CHECKSUMS: PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21 record_darwin: 1f6619f2abac4d1ca91d3eeab038c980d76f1517 + SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d + SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380 share: 0b2c3e82132f5888bccca3351c504d0003b3b410 sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440 sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a diff --git a/lib/constant/api_key.dart b/lib/constant/api_key.dart index 6433459..5def8a8 100644 --- a/lib/constant/api_key.dart +++ b/lib/constant/api_key.dart @@ -9,6 +9,8 @@ class AK { static final String secretKey = X.r(X.r(X.r(Env.secretKey, cn), cC), cs); static final String basicAuthCredentials = X.r(X.r(X.r(Env.basicAuthCredentials, cn), cC), cs); + static final String basicCompareFaces = + X.r(X.r(X.r(Env.basicCompareFaces, cn), cC), cs); static final String accountSIDTwillo = X.r(X.r(X.r(Env.accountSIDTwillo, cn), cC), cs); static final String serverAPI = X.r(X.r(X.r(Env.serverAPI, cn), cC), cs); diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart index 71fbf0d..948aa68 100644 --- a/lib/controller/firebase/firbase_messge.dart +++ b/lib/controller/firebase/firbase_messge.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:SEFER/controller/home/captin/home_captain_controller.dart'; import 'package:SEFER/views/home/Captin/home_captain/widget/call_page.dart'; +import 'package:SEFER/views/widgets/mydialoug.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -18,6 +19,7 @@ import '../../views/home/Captin/home_captain/home_captin.dart'; import '../../views/home/Captin/orderCaptin/order_speed_request.dart'; import '../../views/home/Captin/orderCaptin/order_request_page.dart'; import '../auth/google_sign.dart'; +import '../functions/face_detect.dart'; import 'local_notification.dart'; class FirebaseMessagesController extends GetxController { @@ -90,7 +92,7 @@ class FirebaseMessagesController extends GetxController { }); } - void fireBaseTitles(RemoteMessage message) { + Future fireBaseTitles(RemoteMessage message) async { if (message.notification!.title! == 'Order'.tr) { if (Platform.isAndroid) { NotificationController().showNotification('Order'.tr, '', 'order'); @@ -124,6 +126,32 @@ class FirebaseMessagesController extends GetxController { .showNotification('message From passenger', ''.tr, 'tone2'); passengerDialog(message.notification!.body!); + update(); + } else if (message.notification!.title! == 'face detect') { + NotificationController() + .showNotification('face detect'.tr, ''.tr, 'tone2'); + String result0 = await faceDetector(); + // Handle the result here, e.g., show a dialog or update the UI + var result = jsonDecode(result0); + Get.defaultDialog( + barrierDismissible: false, + title: 'Face Detection Result'.tr, + titleStyle: AppStyle.title, + content: Text( + result['similar'].toString() == 'true' + ? 'similar'.tr + : 'not similar'.tr, + style: AppStyle.title, + ), + backgroundColor: result['similar'].toString() == 'true' + ? AppColor.greenColor + : AppColor.redColor, + confirm: MyElevatedButton( + title: 'OK'.tr, + onPressed: () { + Get.back(); + })); + update(); } else if (message.notification!.title! == 'Hi ,I will go now') { // Get.snackbar('Hi ,I will go now', '', @@ -168,12 +196,18 @@ class FirebaseMessagesController extends GetxController { // // remoteID: driverList[2].toString(), // )); } catch (e) {} - } else if (message.notification!.title! == "Criminal Document Required") { + } else if (message.notification!.title! == + "Criminal Document Required".tr) { NotificationController().showNotification( "Criminal Document Required".tr, message.notification!.body!, 'tone2', ); + MyDialog().getDialog( + "Criminal Document Required".tr, 'You should have upload it .'.tr, + () { + Get.to(() => const CriminalDocumemtPage()); + }); Get.to(() => const CriminalDocumemtPage()); } else if (message.notification!.title! == 'Call End'.tr) { try { diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart index 6db4302..d29378d 100644 --- a/lib/controller/functions/crud.dart +++ b/lib/controller/functions/crud.dart @@ -136,6 +136,7 @@ class CRUD { // 'https://eastus.api.cognitive.microsoft.com/vision/v3.2/ocr' 'https://eastus.api.cognitive.microsoft.com/computervision/imageanalysis:analyze?features=caption,read&model-version=latest&language=en&api-version=2024-02-01')); request.body = json.encode({"url": imagePathFull}); + // request.body = json.encode({"url": imagePathFull}); request.headers.addAll(headers); http.StreamedResponse response = await request.send(); diff --git a/lib/controller/functions/face_detect.dart b/lib/controller/functions/face_detect.dart new file mode 100644 index 0000000..7742b2b --- /dev/null +++ b/lib/controller/functions/face_detect.dart @@ -0,0 +1,48 @@ +import 'dart:convert'; +import 'package:SEFER/constant/api_key.dart'; +import 'package:SEFER/constant/box_name.dart'; +import 'package:SEFER/main.dart'; +import 'package:http/http.dart' as http; + +import '../../constant/links.dart'; +import 'upload_image.dart'; + +Future faceDetector() async { + await ImageController().choosFace(AppLink.uploadEgypt, 'face_detect'); + await Future.delayed(const Duration(seconds: 2)); + + var headers = { + 'Authorization': 'Basic ${AK.basicCompareFaces}', + 'Content-Type': 'application/json' + }; + + var request = http.Request( + 'POST', + Uri.parse( + 'https://face-detect-f6924392c4c7.herokuapp.com/compare_faces')); + + request.body = json.encode({ + "url1": + "https://api.sefer.live/sefer/card_image/id_front-${box.read(BoxName.driverID)}.jpg", + "url2": + "https://api.sefer.live/sefer/card_image/face_detect-${box.read(BoxName.driverID)}.jpg" + }); + print('request.body: ${request.body}'); + request.headers.addAll(headers); + + try { + http.StreamedResponse response = await request.send(); + + if (response.statusCode == 200) { + String result = await response.stream.bytesToString(); + print('result: ${result}'); + return result; + } else { + print('Error: ${response.reasonPhrase}'); + return 'Error: ${response.reasonPhrase}'; + } + } catch (e) { + print('Exception occurred: $e'); + return 'Error: $e'; + } +} diff --git a/lib/controller/functions/gemeni.dart b/lib/controller/functions/gemeni.dart index 38e8803..315c546 100644 --- a/lib/controller/functions/gemeni.dart +++ b/lib/controller/functions/gemeni.dart @@ -8,6 +8,7 @@ import 'package:SEFER/controller/functions/crud.dart'; import 'package:SEFER/controller/functions/device_info.dart'; import 'package:SEFER/main.dart'; import 'package:SEFER/views/home/Captin/home_captain/home_captin.dart'; +import 'package:SEFER/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:image_cropper/image_cropper.dart'; @@ -21,6 +22,21 @@ import '../../constant/colors.dart'; import 'tts.dart'; import 'upload_image.dart'; +enum LicenseSide { + front, + back, + unknown, +} + +enum DocumentType { + carLicenseFront, + carLicenseBack, + idCardFront, + idCardBack, + driverLicense, + unknown, +} + class AI extends GetxController { bool approved = false; bool isDriverSaved = false; @@ -306,90 +322,6 @@ class AI extends GetxController { // } } - // Future addDriverEgypt() async { - // // try { - // // Extract values from box or set defaults - // var firstName = responseIdEgyptDriverLicense['firstName'] ?? ''; - // var lastName = responseIdEgyptDriverLicense['lastName'] ?? ''; - // var email = box.read(BoxName.emailDriver) ?? ''; - // var phone = box.read(BoxName.phoneDriver)?.toString() ?? ''; - // var driverId = box.read(BoxName.driverID)?.toString() ?? ''; - // var password = '123456'; - // var gender = responseIdEgyptBack['gender'] == 'ذكر' ? 'Male' : 'Female'; - // var licenseType = responseIdEgyptDriverLicense['license_type'] ?? ''; - // var nationalNumber = responseIdEgyptBack['nationalID'] ?? ''; - // var nameArabic = responseIdEgyptDriverLicense['name_arabic'] ?? ''; - // var nameEnglish = responseIdEgyptDriverLicense['name_english'] ?? ''; - // var issueDate = responseIdEgyptDriverLicense['issue_date'] ?? ''; - // var expiryDate = responseIdEgyptDriverLicense['expiry_date'] ?? ''; - // var licenseCategories = - // responseIdEgyptDriverLicense['license_categories'] ?? ''; - // var address = responseIdEgyptFront['address'] ?? ''; - // var cardId = responseIdEgyptFront['card_id'] ?? ''; - // var occupation = responseIdEgyptBack['occupation'] ?? ''; - // var education = responseIdEgyptBack['occupation'] ?? ''; - // var licenseIssueDate = - // responseIdEgyptDriverLicense['issue_date'].toString() ?? ''; - // var religion = responseIdEgyptBack['religion'] ?? ''; - // var status = responseIdEgyptBack['fullName'] ?? ''; - // var birthdate = responseIdEgyptFront['dob'] != null - // ? DateTime.parse(responseIdEgyptFront['dob'] + '-01-01').toString() - // : '1960-01-01'; - // - // var maritalStatus = responseIdEgyptBack['maritalStatus'] ?? ''; - // var site = responseIdEgyptDriverLicense['address'] ?? ''; - // var employmentType = responseIdEgyptDriverLicense['employmentType'] ?? ''; - // - // // Create payload - // var payload = { - // 'first_name': firstName, - // 'last_name': lastName, - // 'email': email, - // 'phone': phone, - // 'id': driverId, - // 'password': password, - // 'gender': gender, - // 'license_type': licenseType, - // 'national_number': nationalNumber, - // 'name_arabic': nameArabic, - // 'name_english': nameEnglish, - // 'issue_date': issueDate, - // 'expiry_date': expiryDate, - // 'license_categories': licenseCategories, - // 'address': address, - // 'card_id': cardId, - // 'occupation': occupation, - // 'education': education, - // 'licenseIssueDate': licenseIssueDate, - // 'religion': religion, - // 'status': status, - // 'birthdate': birthdate, - // 'maritalStatus': maritalStatus, - // 'site': site, - // 'employmentType': employmentType, - // }; - // isLoading = true; - // update(); - // // Make POST request - // var res = await CRUD().post(link: AppLink.signUpCaptin, payload: payload); - // var status1 = jsonDecode(res); - // isLoading = false; - // update(); - // // Handle response - // - // if (status1['status'] == 'success') { - // isDriverSaved = true; - // Get.snackbar('Success', 'Driver data saved successfully', - // backgroundColor: AppColor.greenColor); - // } else { - // Get.snackbar('Error', 'Failed to save driver data', - // backgroundColor: Colors.red); - // } - // // } catch (e) { - // // Get.snackbar('Error', 'An error occurred while saving driver data', - // // backgroundColor: Colors.red); - // // } - // } addCriminalDeocuments() async { var res = await CRUD().post(link: AppLink.addCriminalDocuments, payload: { "driverId": box.read(BoxName.driverID), @@ -448,9 +380,11 @@ class AI extends GetxController { Map responseIdEgyptDriverLicense = {}; String? responseIdCardDriverEgypt1; bool isloading = false; + bool isLoading = false; var image; CroppedFile? croppedFile; DateTime now = DateTime.now(); + Future pickImage() async { final pickedImage = await picker.pickImage(source: ImageSource.gallery); @@ -498,23 +432,121 @@ class AI extends GetxController { } } - bool isLoading = false; - Future allMethodForAI(String prompt, linkPHP, imagePath) async { + DocumentType checkDocumentType(String text) { + // Convert text to lowercase and remove all spaces and new lines + text = text.toLowerCase().replaceAll(RegExp(r'\s+'), ''); + + // Keywords for each document type + final Map> keywords = { + DocumentType.carLicenseBack: ['شاسيه', 'موتور', 'سم٣'], + DocumentType.carLicenseFront: ['وزارةالداخلية', 'رخصةتسيير'], + DocumentType.idCardFront: ['بطاقةتحقيقالشخصية'], + DocumentType.idCardBack: ['البطاقةساريةحتى'], + DocumentType.driverLicense: ['قيادةخاصة', 'خاصه'], + }; + + // Check each document type + for (var entry in keywords.entries) { + if (entry.value.any((keyword) => text.contains(keyword))) { + return entry.key; + } + } + + // If no match is found + return DocumentType.unknown; + } + + Future allMethodForAI( + String prompt, String linkPHP, String imagePath) async { isLoading = true; update(); - await ImageController().choosImage(linkPHP, imagePath); - Future.delayed(const Duration(seconds: 2)); - // print(imagePath); - var extractedString = - await CRUD().arabicTextExtractByVisionAndAI(imagePath: imagePath); - print(extractedString); - var json = jsonDecode(extractedString); - var textValues = CRUD().extractTextFromLines(json); - print(textValues); - // await Get.put(AI()).geminiAiExtraction(prompt, textValues, imagePath); - await Get.put(AI()).anthropicAI(textValues, prompt, imagePath); - isLoading = false; - update(); + + try { + await ImageController().choosImage(linkPHP, imagePath); + await Future.delayed(const Duration(seconds: 2)); + + var extractedString = + await CRUD().arabicTextExtractByVisionAndAI(imagePath: imagePath); + var json = jsonDecode(extractedString); + var textValues = CRUD().extractTextFromLines(json); + print('textValues: ${textValues}'); + + DocumentType detectedType = checkDocumentType(textValues); + String expectedDocument = getExpectedDocument(imagePath); + String detectedDocument = getDetectedDocument(detectedType); + + bool isCorrectDocument = (detectedType == getExpectedType(imagePath)); + + if (!isCorrectDocument) { + MyDialog().getDialog('incorrect_document_title'.tr, + '${'expected'.tr}: $expectedDocument\n${'detected'.tr}: $detectedDocument', + () { + Get.back(); + }); + } else { + // Process the correct document + await Get.put(AI()).anthropicAI(textValues, prompt, imagePath); + } + } catch (e) { + print('Error in allMethodForAI: $e'); + MyDialog().getDialog('error'.tr, 'error_processing_document'.tr, () { + Get.back(); + }); + } finally { + isLoading = false; + update(); + } + } + + String getExpectedDocument(String imagePath) { + switch (imagePath) { + case 'car_front': + return 'car_license_front'.tr; + case 'car_back': + return 'car_license_back'.tr; + case 'id_back': + return 'id_card_back'.tr; + case 'id_front': + return 'id_card_front'.tr; + case 'driver_license': + return 'driver_license'.tr; + default: + return 'unknown_document'.tr; + } + } + + DocumentType getExpectedType(String imagePath) { + switch (imagePath) { + case 'car_front': + return DocumentType.carLicenseFront; + case 'car_back': + return DocumentType.carLicenseBack; + case 'id_back': + return DocumentType.idCardBack; + case 'id_front': + return DocumentType.idCardFront; + case 'driver_license': + return DocumentType.driverLicense; + default: + return DocumentType.unknown; + } + } + + String getDetectedDocument(DocumentType type) { + switch (type) { + case DocumentType.carLicenseFront: + return 'car_license_front'.tr; + case DocumentType.carLicenseBack: + return 'car_license_back'.tr; + case DocumentType.idCardFront: + return 'id_card_front'.tr; + case DocumentType.idCardBack: + return 'id_card_back'.tr; + case DocumentType.driverLicense: + return 'driver_license'.tr; + default: + return 'unknown_document'.tr; + } } Future generateContent() async { diff --git a/lib/controller/functions/upload_image.dart b/lib/controller/functions/upload_image.dart index 776c62a..2d8773a 100644 --- a/lib/controller/functions/upload_image.dart +++ b/lib/controller/functions/upload_image.dart @@ -8,6 +8,10 @@ import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path/path.dart'; import 'package:image/image.dart' as image_package; + +import 'package:flutter_image_compress/flutter_image_compress.dart'; +import 'package:path_provider/path_provider.dart' as path_provider; + import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../main.dart'; @@ -53,11 +57,12 @@ class ImageController extends GetxController { isloading = true; update(); // Save the cropped image - File savedCroppedImage = File(croppedFile!.path); + // File savedCroppedImage = File(croppedFile!.path); + File compressedImage = await compressImage(File(croppedFile!.path)); print('link =$link'); try { await uploadImage( - savedCroppedImage, + compressedImage, { 'driverID': box.read(BoxName.driverID) ?? box.read(BoxName.passengerID), @@ -74,6 +79,41 @@ class ImageController extends GetxController { } } + choosFace(String link, String imageType) async { + final pickedImage = await picker.pickImage( + source: ImageSource.camera, + preferredCameraDevice: CameraDevice.front, + ); + if (pickedImage != null) { + image = File(pickedImage.path); + isloading = true; + update(); +// Compress the image + File compressedImage = await compressImage(File(pickedImage.path)); + + // Save the picked image directly + // File savedImage = File(pickedImage.path); + print('link =$link'); + try { + await uploadImage( + compressedImage, + { + 'driverID': + box.read(BoxName.driverID) ?? box.read(BoxName.passengerID), + 'imageType': imageType + }, + link, + ); + } catch (e) { + Get.snackbar('Image Upload Failed'.tr, e.toString(), + backgroundColor: AppColor.redColor); + } finally { + isloading = false; + update(); + } + } + } + uploadImage(File file, Map data, String link) async { var request = http.MultipartRequest( 'POST', @@ -149,11 +189,12 @@ class ImageController extends GetxController { isloading = true; update(); // Save the cropped image - File savedCroppedImage = File(croppedFile!.path); + // File savedCroppedImage = File(croppedFile!.path); + File compressedImage = await compressImage(File(croppedFile!.path)); print('link =$link'); try { await uploadImage( - savedCroppedImage, + compressedImage, { 'driverID': box.read(BoxName.driverID) ?? box.read(BoxName.passengerID), @@ -210,3 +251,18 @@ class ImageController extends GetxController { } } } + +Future compressImage(File file) async { + final dir = await path_provider.getTemporaryDirectory(); + final targetPath = "${dir.absolute.path}/temp.jpg"; + + var result = await FlutterImageCompress.compressAndGetFile( + file.absolute.path, + targetPath, + quality: 70, + minWidth: 1024, + minHeight: 1024, + ); + + return File(result!.path); +} diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart index 64c3f38..c4edd65 100644 --- a/lib/controller/local/translations.dart +++ b/lib/controller/local/translations.dart @@ -4,6 +4,30 @@ class MyTranslation extends Translations { @override Map> get keys => { "ar": { + "face detect": "كشف الوجه", + "Face Detection Result": "نتيجة كشف الوجه", + "false": "خطأ", + "true": "صحيح", + "similar": "مشابه", + "not similar": "غير مشابه", + "error": "خطأ", + "error_processing_document": "خطأ في معالجة المستند", + "expected": "متوقع", + "detected": "تم الكشف عنه", + "car_license_front": "الجانب الأمامي لرخصة السيارة", + "car_license_back": "الجانب الخلفي لرخصة السيارة", + "id_card_front": "الجانب الأمامي لبطاقة الهوية", + "id_card_back": "الجانب الخلفي لبطاقة الهوية", + "driver_license": "رخصة القيادة", + "unknown_document": "وثيقة غير معروفة", + "incorrect_document_title": "وثيقة غير صحيحة", + "incorrect_document_message": + "الرجاء تحميل {expected} الصحيحة. تم الكشف عن {detected}.", + "driver_license": "رخصة_القيادة", + "id_front": "هوية_أمامية", + "id_back": "هوية_خلفية", + "car_back": "سيارة_خلفية", + "car_front": "سيارة_أمامية", "ID Documents Front": "الوثيقه الشخصية - الأمامية", "Vehicle Details Front": "تفاصيل المركبة - الأمامية", "Vehicle Details Back": "تفاصيل المركبة - الخلفية", diff --git a/lib/views/auth/captin/cards/egypt_card_a_i.dart b/lib/views/auth/captin/cards/egypt_card_a_i.dart index fa23c76..157a2fb 100644 --- a/lib/views/auth/captin/cards/egypt_card_a_i.dart +++ b/lib/views/auth/captin/cards/egypt_card_a_i.dart @@ -1,6 +1,7 @@ import 'package:SEFER/controller/functions/gemeni.dart'; import 'package:SEFER/controller/functions/tts.dart'; import 'package:SEFER/views/widgets/elevated_btn.dart'; +import 'package:SEFER/views/widgets/my_circular_indicator_timer.dart'; import 'package:SEFER/views/widgets/my_textField.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -34,7 +35,9 @@ class EgyptCardAI extends StatelessWidget { body: [ GetBuilder(builder: (controller) { return controller.isLoading - ? const MyCircularProgressIndicator() + ? MyCircularProgressIndicatorWithTimer( + isLoading: controller.isLoading, + ) : Padding( padding: const EdgeInsets.all(8.0), child: Column( diff --git a/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart b/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart index 31953da..73d91c7 100644 --- a/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart +++ b/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart @@ -1,5 +1,12 @@ +import 'dart:convert'; + import 'package:SEFER/constant/box_name.dart'; +import 'package:SEFER/constant/style.dart'; +import 'package:SEFER/controller/functions/face_detect.dart'; import 'package:SEFER/main.dart'; +import 'package:SEFER/views/auth/captin/cards/egypt_card_a_i.dart'; +import 'package:SEFER/views/widgets/elevated_btn.dart'; +import 'package:SEFER/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:get/get.dart'; @@ -31,37 +38,28 @@ GetBuilder leftMainMenuCaptainIcons() { // // String apikey = AK.passwordPayMob; // // String convertedStringN = credentials.c( // // credentials.c(credentials.c(apikey, cs), cC), cn); - // // print(convertedStringN); // // String retrievedStringS = credentials.r( // // credentials.r(credentials.r(convertedStringN, cn), cC), // // cs); - // // print(retrievedStringS); // // // // // if (retrievedStringS == // // 'apikey') { - // // print('same'); // // } // // key.forEach((key, apiKey) { // // Get.to(() => SmsSignupEgypt()); // // keys.forEach((key, apiKey) { // // String apikey = Env.basicAuthCredentials; - // // print('apikey: ${apikey}'); // // String retrievedStringS = credentials.r( // // credentials.r(credentials.r(apikey, cn), cC), cs); - // // print('retrievedStringS: $retrievedStringS'); // // String encryptedApiKey = // // X.c(X.c(X.c(retrievedStringS, cs), cC), cn); - // // print('encrypted $encryptedApiKey'); // // String decryptedApiKey = // // X.r(X.r(X.r(encryptedApiKey, cn), cC), cs); - // // print('Decrypted API Key for : $decryptedApiKey'); // // if (decryptedApiKey == retrievedStringS) { - // // print('match '); // // } else { - // // print('Keys do not match for '); // // } // // } // // ); @@ -189,8 +187,8 @@ GetBuilder leftMainMenuCaptainIcons() { // border: Border.all(color: AppColor.blueColor), // borderRadius: BorderRadius.circular(15)), // child: IconButton( - // onPressed: () { - // print(box.read(BoxName.tokenDriver)); + // onPressed: () async { + // Get.to(() => EgyptCardAI()); // }, // icon: const Icon( // FontAwesome5.grin_tears, diff --git a/lib/views/widgets/my_circular_indicator_timer.dart b/lib/views/widgets/my_circular_indicator_timer.dart new file mode 100644 index 0000000..87ba35c --- /dev/null +++ b/lib/views/widgets/my_circular_indicator_timer.dart @@ -0,0 +1,73 @@ +import 'package:SEFER/constant/style.dart'; +import 'package:flutter/material.dart'; +import 'dart:async'; + +class MyCircularProgressIndicatorWithTimer extends StatelessWidget { + final Color backgroundColor; + final bool isLoading; + + MyCircularProgressIndicatorWithTimer({ + Key? key, + this.backgroundColor = Colors.transparent, + required this.isLoading, + }) : super(key: key); + + final StreamController _streamController = StreamController(); + + void startTimer() { + int _timeLeft = 60; + Timer.periodic(const Duration(seconds: 1), (timer) { + if (_timeLeft > 0 && isLoading) { + _streamController.add(_timeLeft); + _timeLeft--; + } else { + timer.cancel(); + _streamController.close(); + } + }); + } + + @override + Widget build(BuildContext context) { + if (isLoading) { + startTimer(); + } + + return Center( + child: Container( + width: 200, + height: 200, + decoration: BoxDecoration( + color: backgroundColor, + shape: BoxShape.circle, + ), + child: Stack( + children: [ + const Center(child: CircularProgressIndicator()), + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Align( + alignment: Alignment.center, + child: Image.asset( + 'assets/images/logo.gif', + width: 140, + height: 140, + ), + ), + const SizedBox(height: 10), + StreamBuilder( + stream: _streamController.stream, + initialData: 60, + builder: (context, snapshot) { + return Text('${snapshot.data}', style: AppStyle.title); + }, + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 51d85d2..1a3c0b5 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -11,6 +11,7 @@ import file_selector_macos import firebase_auth import firebase_core import firebase_messaging +import flutter_image_compress_macos import flutter_local_notifications import flutter_secure_storage_macos import flutter_tts @@ -34,6 +35,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) + FlutterImageCompressMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterImageCompressMacosPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 15601d5..274b800 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -558,6 +558,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.7" + flutter_image_compress: + dependency: "direct main" + description: + name: flutter_image_compress + sha256: "45a3071868092a61b11044c70422b04d39d4d9f2ef536f3c5b11fb65a1e7dd90" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + flutter_image_compress_common: + dependency: transitive + description: + name: flutter_image_compress_common + sha256: "7f79bc6c8a363063620b4e372fa86bc691e1cb28e58048cd38e030692fbd99ee" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + flutter_image_compress_macos: + dependency: transitive + description: + name: flutter_image_compress_macos + sha256: "26df6385512e92b3789dc76b613b54b55c457a7f1532e59078b04bf189782d47" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + flutter_image_compress_ohos: + dependency: transitive + description: + name: flutter_image_compress_ohos + sha256: e76b92bbc830ee08f5b05962fc78a532011fcd2041f620b5400a593e96da3f51 + url: "https://pub.dev" + source: hosted + version: "0.0.3" + flutter_image_compress_platform_interface: + dependency: transitive + description: + name: flutter_image_compress_platform_interface + sha256: "579cb3947fd4309103afe6442a01ca01e1e6f93dc53bb4cbd090e8ce34a41889" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + flutter_image_compress_web: + dependency: transitive + description: + name: flutter_image_compress_web + sha256: f02fe352b17f82b72f481de45add240db062a2585850bea1667e82cc4cd6c311 + url: "https://pub.dev" + source: hosted + version: "0.1.4+1" flutter_launcher_icons: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 48bee6a..e7f3a46 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -67,6 +67,7 @@ dependencies: sign_in_with_apple: ^6.1.0 firebase_auth: ^4.19.6 package_info_plus: ^8.0.0 + flutter_image_compress: ^2.3.0 dev_dependencies: flutter_test: