From 255724418c893b743699cf6cb33cc76e920f54d8 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Sat, 2 May 2026 15:12:46 +0300 Subject: [PATCH] service 2-5-26-1 --- android/app/build.gradle.kts | 4 +- lib/constant/box_name.dart | 2 + lib/constant/links.dart | 19 +- lib/controller/auth/register_controller.dart | 78 +++ lib/controller/best_driver_controllers.dart | 6 +- lib/controller/firebase.dart | 22 +- lib/controller/functions/crud.dart | 398 +++++++++------- lib/controller/functions/device_helper.dart | 49 ++ lib/controller/functions/encrypt_decrypt.dart | 37 +- lib/controller/functions/image.dart | 13 +- lib/controller/functions/initilize.dart | 2 +- lib/controller/login_controller.dart | 103 ++-- .../mainController/main_controller.dart | 26 +- .../pages/best_driver_page.dart | 2 +- .../ragister_service_controller.dart | 6 +- .../registration_captain_controller.dart | 6 +- lib/login_page.dart | 187 ++++++-- lib/main.dart | 1 - lib/views/auth/register_page.dart | 172 +++++++ lib/views/home/main.dart | 4 +- linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 - pubspec.lock | 450 +++++++++--------- pubspec.yaml | 2 + windows/flutter/generated_plugins.cmake | 1 + 25 files changed, 1063 insertions(+), 530 deletions(-) create mode 100644 lib/controller/auth/register_controller.dart create mode 100644 lib/controller/functions/device_helper.dart create mode 100644 lib/views/auth/register_page.dart diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 3d6d637..6ffa94b 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -32,7 +32,7 @@ android { defaultConfig { applicationId = "com.service_intaleq" - minSdk = 23 + minSdk = flutter.minSdkVersion targetSdk = 36 versionCode = 1 versionName = "1.0" @@ -90,4 +90,4 @@ dependencies { implementation("com.scottyab:rootbeer-lib:0.1.0") implementation("com.google.android.gms:play-services-safetynet:18.0.1") coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") -} \ No newline at end of file +} diff --git a/lib/constant/box_name.dart b/lib/constant/box_name.dart index e88a7c3..0277ddd 100644 --- a/lib/constant/box_name.dart +++ b/lib/constant/box_name.dart @@ -7,6 +7,8 @@ class BoxName { static const String firstTimeLoadKey = 'firstTimeLoadKey'; static const String jwt = "jwt"; static const String fingerPrint = "fingerPrint"; + static const String deviceFingerprint = "deviceFingerprint"; + static const String payMobApikey = "payMobApikey"; static const String employeename = "employeename"; static const String refreshToken = "refreshToken"; diff --git a/lib/constant/links.dart b/lib/constant/links.dart index af56266..4c0dcb5 100644 --- a/lib/constant/links.dart +++ b/lib/constant/links.dart @@ -10,17 +10,24 @@ class AppLink { static final String seferCairoServer = Env.seferCairoServer; static final String seferGizaServer = Env.seferGizaServer; static String paymentServer = 'https://walletintaleq.intaleq.xyz/v1/main'; - static String location = 'https://api.intaleq.xyz/intaleq/ride/location'; - static String locationServer = - 'https://location.intaleq.xyz/intaleq/ride/location'; + static String locationServer = 'https://location.intaleq.xyz/intaleq/ride/location'; + static String location = locationServer; + static String locationServerSide = 'https://location.intaleq.xyz/intaleq/ride/location'; + static String mapSaasRoute = 'https://map-saas.intaleqapp.com/api/maps/route'; + static String mapSaasPlaces = 'https://map-saas.intaleqapp.com/api/geocoding/places'; + static const String routeApiBaseUrl = "https://routesjo.intaleq.xyz/route/v1/driving"; + static final String syria = 'https://syria.intaleq.xyz/intaleq'; + static String seferPaymentServer0 = box.read('seferPaymentServer'); - static final String endPoint = 'https://api.intaleq.xyz/intaleq'; + static final String endPoint = 'https://api.intaleq.xyz/intaleq_v3'; static final String rideServer = 'https://rides.intaleq.xyz/intaleq'; // static final String server = Env.serverPHP; static String getBestDriver = "$server/Admin/driver/getBestDriver.php"; - static final String server = 'https://api.intaleq.xyz/intaleq'; + static final String server = 'https://api.intaleq.xyz/intaleq_v3'; static final String jwtService = '$server/jwtService.php'; + static String addError = "$server/Admin/errorApp.php"; + // static final String endPoint = box.read(BoxName.serverChosen); // static final String server = Env.seferCairoServer; @@ -34,6 +41,8 @@ class AppLink { static String uploadEgypt = "$server/uploadEgypt.php"; static String auth = '$server/auth'; static String login = "$serviceApp/login.php"; + static String register = "$serviceApp/register.php"; + static String signUp = "$auth/signup.php"; static String sendVerifyEmail = "$auth/sendVerifyEmail.php"; static String passengerRemovedAccountEmail = diff --git a/lib/controller/auth/register_controller.dart b/lib/controller/auth/register_controller.dart new file mode 100644 index 0000000..f3e04ea --- /dev/null +++ b/lib/controller/auth/register_controller.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:service/constant/links.dart'; +import 'package:service/controller/functions/crud.dart'; +import 'package:service/controller/functions/device_helper.dart'; +import 'package:service/print.dart'; + +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +class RegisterController extends GetxController { + final firstName = TextEditingController(); + final lastName = TextEditingController(); + final email = TextEditingController(); + final phone = TextEditingController(); + final password = TextEditingController(); + + final FlutterSecureStorage storage = const FlutterSecureStorage(); + final formKey = GlobalKey(); + + var isLoading = false.obs; + + void register() async { + if (formKey.currentState!.validate()) { + isLoading.value = true; + + // الحصول على البصمة + String fingerprint = await DeviceHelper.getDeviceFingerprint(); + + var payload = { + "first_name": firstName.text, + "last_name": lastName.text, + "email": email.text, + "phone": phone.text, + "password": password.text, + "fingerprint": fingerprint, + }; + + Log.print('🚀 Register Payload: $payload'); + var res = await CRUD().post(link: AppLink.register, payload: payload); + Log.print('📥 Register Response: $res'); + + isLoading.value = false; + + if (res != 'failure' && res is Map && res['status'] == 'success') { + // حفظ كلمة المرور للدخول التلقائي لاحقاً + await storage.write(key: 'password', value: password.text); + + Get.defaultDialog( + + title: "نجاح", + middleText: res['message']['message'] ?? "تم تقديم طلبك بنجاح. يرجى انتظار موافقة الإدارة.", + onConfirm: () { + Get.back(); // close dialog + Get.back(); // return to login + }, + textConfirm: "موافق", + ); + } else { + Get.snackbar( + "خطأ", + res is Map ? res['message'].toString() : "فشل تقديم طلب التسجيل", + backgroundColor: Colors.red.withOpacity(0.7), + colorText: Colors.white, + ); + } + } + } + + @override + void onClose() { + firstName.dispose(); + lastName.dispose(); + email.dispose(); + phone.dispose(); + password.dispose(); + super.onClose(); + } +} diff --git a/lib/controller/best_driver_controllers.dart b/lib/controller/best_driver_controllers.dart index c1da2a8..e360e3a 100644 --- a/lib/controller/best_driver_controllers.dart +++ b/lib/controller/best_driver_controllers.dart @@ -13,7 +13,7 @@ class Driverthebest extends GetxController { getBestDriver() async { var res = await CRUD().get(link: AppLink.getBestDriver, payload: {}); if (res != 'failure') { - driver = jsonDecode(res)['message']; + driver = res['message']; // Log.print('driver: ${driver}'); update(); } else { @@ -34,7 +34,7 @@ class DriverTheBestGizaController extends GetxController { getBestDriver() async { var res = await CRUD().get(link: AppLink.getBestDriverGiza, payload: {}); if (res != 'failure') { - driver = jsonDecode(res)['message']; + driver = res['message']; update(); } else { @@ -56,7 +56,7 @@ class DriverTheBestAlexandriaController extends GetxController { var res = await CRUD().get(link: AppLink.getBestDriverAlexandria, payload: {}); if (res != 'failure') { - driver = jsonDecode(res)['message']; + driver = res['message']; update(); } else { Get.snackbar('error', '', backgroundColor: AppColor.redColor); diff --git a/lib/controller/firebase.dart b/lib/controller/firebase.dart index 48afce8..90adabe 100644 --- a/lib/controller/firebase.dart +++ b/lib/controller/firebase.dart @@ -11,6 +11,7 @@ import '../../constant/colors.dart'; import '../../constant/links.dart'; import '../../constant/style.dart'; import '../../main.dart'; +import 'functions/crud.dart'; class FirebaseMessagesController extends GetxController { final fcmToken = FirebaseMessaging.instance; @@ -55,25 +56,16 @@ class FirebaseMessagesController extends GetxController { } Future getTokens() async { - String? basicAuthCredentials = - await storage.read(key: BoxName.basicAuthCredentials); - var res = await http.post( - Uri.parse(AppLink.getTokens), - headers: { - 'Authorization': - 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', - }, - body: {}, - ); - var jsonResponse = jsonDecode(res.body); - if (jsonResponse['status'] == 'success') { - dataTokens = jsonResponse['data']; + var res = await CRUD().post(link: AppLink.getTokens, payload: {}); + if (res != 'failure' && res['status'] == 'success') { + dataTokens = res['data']; for (var i = 0; i < dataTokens.length; i++) { - tokens.add(jsonResponse['data'][i]['token']); + tokens.add(res['data'][i]['token']); } box.write(BoxName.tokens, tokens); } else { - Get.defaultDialog(title: "Warning", middleText: "Server Error"); + Get.snackbar("Warning".tr, "Server Error".tr, + backgroundColor: AppColor.redColor); } } diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart index 66e74c2..1e679f4 100644 --- a/lib/controller/functions/crud.dart +++ b/lib/controller/functions/crud.dart @@ -1,82 +1,244 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:get/get.dart'; import 'package:http/http.dart' as http; -import 'package:jwt_decoder/jwt_decoder.dart'; -import 'package:secure_string_operations/secure_string_operations.dart'; -import 'package:service/constant/char_map.dart'; +import 'package:service/constant/box_name.dart'; +import 'package:service/constant/links.dart'; +import 'package:service/controller/functions/encrypt_decrypt.dart'; +import 'package:service/env/env.dart'; +import 'package:service/main.dart'; +import 'package:service/print.dart'; import '../../constant/api_key.dart'; -import '../../constant/box_name.dart'; -import '../../constant/info.dart'; -import '../../constant/links.dart'; -import '../../main.dart'; -import '../../print.dart'; -import 'encrypt_decrypt.dart'; -import 'initilize.dart'; class CRUD { - var dev; - getJWT(String pass, email) async { - var dev = Platform.isAndroid ? 'android' : 'ios'; - var payload = { - 'password': box.read(BoxName.password) ?? pass, - 'email': box.read(BoxName.email) ?? email, - 'aud': '${AK.allowed}$dev', - }; - var response0 = await http.post( - Uri.parse(AppLink.jwtService), - body: payload, - ); + static bool _isRefreshingJWT = false; + static String _lastErrorSignature = ''; + static DateTime _lastErrorTimestamp = DateTime(2000); + static const Duration _errorLogDebounceDuration = Duration(minutes: 1); - if (response0.statusCode == 200) { - final decodedResponse1 = jsonDecode(response0.body); - - final jwt = decodedResponse1['jwt']; - Log.print('jwt: ${jwt}'); - box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs)); + // ── JWT Validity Check (No external libs) ────────────────────── + static bool _isJwtValid(String? token) { + if (token == null || token.isEmpty) return false; + try { + final parts = token.split('.'); + if (parts.length != 3) return false; + String payload = parts[1]; + switch (payload.length % 4) { + case 2: + payload += '=='; + break; + case 3: + payload += '='; + break; + } + final decoded = jsonDecode(utf8.decode(base64Url.decode(payload))); + final exp = decoded['exp']; + if (exp == null) return false; + // 30 seconds buffer + return DateTime.now().millisecondsSinceEpoch < (exp * 1000 - 30000); + } catch (_) { + return false; } } + static Future addError( + String error, String details, String where) async { + try { + final currentErrorSignature = '$where-$error'; + final now = DateTime.now(); + + if (currentErrorSignature == _lastErrorSignature && + now.difference(_lastErrorTimestamp) < _errorLogDebounceDuration) { + return; + } + + _lastErrorSignature = currentErrorSignature; + _lastErrorTimestamp = now; + + final userId = + box.read(BoxName.driverID) ?? box.read(BoxName.passengerID); + final userType = 'Service'; + final phone = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver); + + CRUD().post( + link: AppLink.addError, + payload: { + 'error': error.toString(), + 'userId': userId.toString(), + 'userType': userType, + 'phone': phone.toString(), + 'device': where, + 'details': details, + }, + ); + } catch (e) {} + } + + String _getFpHeader() { + return box.read(BoxName.fingerPrint)?.toString() ?? ''; + } + + // ═══════════════════════════════════════════════════════════════ + // _makeRequest — Central Request Handler + // ─────────────────────────────────────────────────────────────── + Future _makeRequest({ + required String link, + Map? payload, + required Map headers, + }) async { + const totalTimeout = Duration(seconds: 60); + + Future doPost() { + final url = Uri.parse(link); + return http + .post(url, body: payload, headers: headers) + .timeout(totalTimeout); + } + + http.Response? response; + int attempts = 0; + final requestId = + DateTime.now().millisecondsSinceEpoch.toString().substring(7); + + Log.print('🚀 [REQ-$requestId] $link'); + Log.print('🔑 [FP-$requestId] ${headers['X-Device-FP']}'); + if (payload != null) Log.print('📦 [PAYLOAD-$requestId] $payload'); + + + while (attempts < 3) { + try { + attempts++; + response = await doPost(); + break; + } on SocketException catch (_) { + Log.print('⚠️ SocketException attempt $attempts — $link'); + if (attempts >= 3) return 'no_internet'; + await Future.delayed(const Duration(seconds: 1)); + } on TimeoutException catch (_) { + Log.print('⚠️ TimeoutException attempt $attempts — $link'); + if (attempts >= 3) return 'failure'; + } catch (e) { + if (e.toString().contains('errno = 9') && attempts < 3) { + await Future.delayed(const Duration(milliseconds: 500)); + continue; + } + addError( + 'HTTP Exception: $e', 'Try: $attempts', 'CRUD._makeRequest $link'); + return 'failure'; + } + } + + if (response == null) return 'failure'; + + final sc = response.statusCode; + final body = response.body; + + Log.print('📥 [RES-$requestId] [$sc] $link'); + Log.print('📄 [BODY-$requestId] $body'); + + if (sc >= 200 && sc < 300) { + try { + return jsonDecode(body); + } catch (e, st) { + addError( + 'JSON Decode Error', 'Body: $body\n$st', 'CRUD._makeRequest $link'); + return 'failure'; + } + } + + if (sc == 401) { + if (!_isRefreshingJWT && !link.contains('errorApp.php')) { + _isRefreshingJWT = true; + try { + await getJWT(); + } finally { + _isRefreshingJWT = false; + } + } + return 'token_expired'; + } + + if (sc >= 500) { + addError('Server 5xx', 'SC: $sc\nBody: $body', 'CRUD._makeRequest $link'); + return 'failure'; + } + + return 'failure'; + } + + // ═══════════════════════════════════════════════════════════════ + // post — standard POST + // ═══════════════════════════════════════════════════════════════ + Future post({ + required String link, + Map? payload, + }) async { + String token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0]; + + if (!_isJwtValid(token) && + !_isRefreshingJWT && + !link.contains('login.php')) { + _isRefreshingJWT = true; + try { + await getJWT(); + token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0]; + } finally { + _isRefreshingJWT = false; + } + } + + final headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Authorization': 'Bearer $token', + 'X-Device-FP': _getFpHeader(), + }; + + return await _makeRequest(link: link, payload: payload, headers: headers); + } + + // ═══════════════════════════════════════════════════════════════ + // get — standard GET (uses POST method in this architecture) + // ═══════════════════════════════════════════════════════════════ Future get({ required String link, Map? payload, }) async { - var url = Uri.parse( - link, - ); - bool isTokenExpired = JwtDecoder.isExpired(X - .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) - .toString() - .split(AppInformation.addd)[0]); - - if (isTokenExpired) { - await getJWT(box.read(BoxName.password), box.read(BoxName.email)); - } - var response = await http.post( - url, - body: payload, - headers: { - "Content-Type": "application/x-www-form-urlencoded", - 'Authorization': - 'Bearer ${X.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs).toString().split(AppInformation.addd)[0]}' - }, - ); - Log.print('esponse.body: ${response.body}'); - Log.print('esponse.req: ${response.request}'); - Log.print('payload: ${payload}'); - - var jsonData = jsonDecode(response.body); - - Log.print('jsonData: ${jsonData}'); - if (jsonData['status'] == 'success') { - return response.body; - } - - return jsonData['status']; + return await post(link: link, payload: payload); } - // } + // ═══════════════════════════════════════════════════════════════ + // getJWT — V1 Login Flow + // ═══════════════════════════════════════════════════════════════ + Future getJWT() async { + var payload = { + 'fingerprint': _getFpHeader(), + 'password': box.read(BoxName.password) ?? '', + 'aud': 'service', + }; + + final headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + }; + + final response = await _makeRequest( + link: AppLink.login, payload: payload, headers: headers); + + if (response != 'failure' && + response is Map && + response['status'] == 'success') { + final jwt = response['message']['jwt']; + Log.print('jwt: $jwt'); + box.write(BoxName.jwt, c(jwt)); + } + } + + // ───────────────────────────────────────────────────────────── + // Service Specific Methods (Preserved) + // ───────────────────────────────────────────────────────────── + Future arabicTextExtractByVisionAndAI({ required String imagePath, required String driverID, @@ -99,24 +261,24 @@ class CRUD { if (response.statusCode == 200) { return await response.stream.bytesToString(); - } else {} + } + return 'failure'; } Future getAgoraToken({ required String channelName, required String uid, }) async { - var uid = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver); - var res = await http.get(Uri.parse( - // 'https://repulsive-pig-rugby-shirt.cyclic.app/token?channelName=$channelName'), + var res = await http.get( + Uri.parse( 'https://orca-app-b2i85.ondigitalocean.app/token?channelName=$channelName'), - // headers: {'Authorization': 'Bearer ${AK.agoraAppCertificate}'}); headers: {'Authorization': 'Bearer '}); if (res.statusCode == 200) { var response = jsonDecode(res.body); return response['token']; - } else {} + } + return 'failure'; } Future getLlama({ @@ -124,18 +286,14 @@ class CRUD { required String payload, required String prompt, }) async { - var url = Uri.parse( - link, - ); + var url = Uri.parse(link); var headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy' - // 'Authorization': 'Bearer ${Env.llamaKey}' }; var data = json.encode({ "model": "Llama-3-70b-Inst-FW", - // "model": "llama-13b-chat", "messages": [ { "role": "user", @@ -145,11 +303,7 @@ class CRUD { ], "temperature": 0.9 }); - var response = await http.post( - url, - body: data, - headers: headers, - ); + var response = await http.post(url, body: data, headers: headers); if (response.statusCode == 200) { return response.body; @@ -157,54 +311,7 @@ class CRUD { return response.statusCode; } - Future post({ - required String link, - Map? payload, - }) async { - // String? basicAuthCredentials = - // await storage.read(key: BoxName.basicAuthCredentials); - var url = Uri.parse( - link, - ); - bool isTokenExpired = JwtDecoder.isExpired(X - .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) - .toString() - .split(AppInformation.addd)[0]); - - if (isTokenExpired) { - await getJWT(box.read(BoxName.password), box.read(BoxName.email)); - } - var response = await http.post( - url, - body: payload, - headers: { - "Content-Type": "application/x-www-form-urlencoded", - 'Authorization': - 'Bearer ${X.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs).toString().split(AppInformation.addd)[0]}' - }, - ); - Log.print('req: ${response.request}'); - Log.print('res: ${response.body}'); - var jsonData = jsonDecode(response.body); - - if (response.statusCode == 200) { - if (jsonData['status'] == 'success') { - return response.body; - } else { - String errorMessage = jsonData['message']; - // Get.snackbar('Error'.tr, errorMessage.tr, - // backgroundColor: AppColor.redColor); - return (jsonData['status']); - } - } else { - return response.statusCode; - } - } - - sendEmail( - String link, - Map? payload, - ) async { + sendEmail(String link, Map? payload) async { var headers = { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': @@ -215,45 +322,6 @@ class CRUD { request.headers.addAll(headers); http.StreamedResponse response = await request.send(); - if (response.statusCode == 200) { - } else {} + if (response.statusCode == 200) {} } - - Future update({ - required String endpoint, - required Map data, - required String id, - }) async { - // String? basicAuthCredentials = - // await storage.read(key: BoxName.basicAuthCredentials); - var url = Uri.parse('$endpoint/$id'); - var response = await http.put( - url, - body: json.encode(data), - headers: { - 'Authorization': - 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', - }, - ); - return json.decode(response.body); - } - - Future delete({ - required String endpoint, - required String id, - }) async { - // String? basicAuthCredentials = - // await storage.read(key: BoxName.basicAuthCredentials); - var url = Uri.parse('$endpoint/$id'); - var response = await http.delete( - url, - headers: { - 'Authorization': - 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', - }, - ); - return json.decode(response.body); - } - - extractTextFromLines(json) {} } diff --git a/lib/controller/functions/device_helper.dart b/lib/controller/functions/device_helper.dart new file mode 100644 index 0000000..75e7773 --- /dev/null +++ b/lib/controller/functions/device_helper.dart @@ -0,0 +1,49 @@ +import 'dart:io'; +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; +import 'package:service/constant/box_name.dart'; +import 'package:service/controller/functions/encrypt_decrypt.dart'; +import '../../main.dart'; +import '../../print.dart'; + +class DeviceHelper { + static Future getDeviceFingerprint() async { + await EncryptionHelper.initialize(); + final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); + var deviceData; + + try { + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo; + deviceData = androidInfo.toMap(); + } else if (Platform.isIOS) { + IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo; + deviceData = iosInfo.toMap(); + } else { + throw UnsupportedError('Unsupported platform'); + } + + final String deviceId = Platform.isAndroid + ? deviceData['id'] ?? + deviceData['androidId'] ?? + deviceData['fingerprint'] ?? + 'unknown' + : deviceData['identifierForVendor'] ?? 'unknown'; + + final String deviceModel = deviceData['model'] ?? 'unknown'; + + Log.print('DeviceId: $deviceId'); + Log.print('DeviceModel: $deviceModel'); + + final String fingerprint = + EncryptionHelper.instance.encryptData('${deviceId}_$deviceModel'); + + Log.print('Generated Fingerprint: $fingerprint'); + box.write(BoxName.fingerPrint, fingerprint); + return (fingerprint); + } catch (e) { + Log.print('Error generating device fingerprint: $e'); + return ''; + } + } +} diff --git a/lib/controller/functions/encrypt_decrypt.dart b/lib/controller/functions/encrypt_decrypt.dart index 94d72ab..62fc85c 100644 --- a/lib/controller/functions/encrypt_decrypt.dart +++ b/lib/controller/functions/encrypt_decrypt.dart @@ -2,8 +2,10 @@ import 'package:encrypt/encrypt.dart' as encrypt; import 'package:flutter/foundation.dart'; import 'package:service/env/env.dart'; -import '../../constant/box_name.dart'; -import '../../main.dart'; +import 'package:secure_string_operations/secure_string_operations.dart'; +import 'package:service/constant/char_map.dart'; +import 'package:service/print.dart'; + class EncryptionHelper { static EncryptionHelper? _instance; @@ -28,29 +30,35 @@ class EncryptionHelper { } debugPrint("Initializing EncryptionHelper..."); // Read stored keys - String? keyOfApp = Env.keyOfApp; - // Log.print('keyOfApp: ${keyOfApp}'); - String? initializationVector = Env.initializationVector; - // Log.print('initializationVector: ${initializationVector}'); + String keyOfApp = r(Env.keyOfApp).toString().split(Env.addd)[0]; + String initializationVector = r(Env.initializationVector).toString().split(Env.addd)[0]; + + Log.print('Key Length: ${keyOfApp.length}'); + Log.print('IV Length: ${initializationVector.length}'); + // Set the global instance _instance = EncryptionHelper._( - encrypt.Key.fromUtf8(keyOfApp!), - encrypt.IV.fromUtf8(initializationVector!), + encrypt.Key.fromUtf8(keyOfApp), + encrypt.IV.fromUtf8(initializationVector), ); debugPrint("EncryptionHelper initialized successfully."); } + /// Encrypts a string String encryptData(String plainText) { + Log.print('Encrypting: $plainText'); try { + final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc)); final encrypted = encrypter.encrypt(plainText, iv: iv); return encrypted.base64; } catch (e) { - debugPrint('Encryption Error: $e'); + Log.print('Encryption Error: $e'); return ''; } + } /// Decrypts a string @@ -66,3 +74,14 @@ class EncryptionHelper { } } } + +r(String string) { + var res = X.r(X.r(X.r(string, cn), cC), cs).toString(); + // Log.print('r($string) => $res'); + return res; +} + + +c(String string) { + return X.c(X.c(X.c(string, cn), cC), cs).toString(); +} diff --git a/lib/controller/functions/image.dart b/lib/controller/functions/image.dart index 589bf0d..d98c658 100644 --- a/lib/controller/functions/image.dart +++ b/lib/controller/functions/image.dart @@ -14,6 +14,9 @@ import '../../constant/api_key.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../main.dart'; +import 'package:service/controller/functions/encrypt_decrypt.dart'; +import 'package:service/env/env.dart'; + class ImageController extends GetxController { File? myImage; @@ -199,12 +202,13 @@ class ImageController extends GetxController { length, filename: basename(file.path), ); + String token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0]; request.headers.addAll({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', - 'Authorization': - 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', + 'Authorization': 'Bearer $token', + 'X-Device-FP': box.read(BoxName.fingerPrint)?.toString() ?? '', }); // Set the file name to the driverID request.files.add( @@ -292,9 +296,10 @@ class ImageController extends GetxController { length, filename: basename(file.path), ); + String token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0]; request.headers.addAll({ - 'Authorization': - 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', + 'Authorization': 'Bearer $token', + 'X-Device-FP': box.read(BoxName.fingerPrint)?.toString() ?? '', }); // Set the file name to the driverID request.files.add( diff --git a/lib/controller/functions/initilize.dart b/lib/controller/functions/initilize.dart index 7432739..cba2eeb 100644 --- a/lib/controller/functions/initilize.dart +++ b/lib/controller/functions/initilize.dart @@ -34,7 +34,7 @@ class AppInitializer { var res = await CRUD().get(link: Env.getapiKey, payload: {"keyName": key1}); if (res != 'failure') { - var d = jsonDecode(res)['message']; + var d = res['message']; await storage.write(key: key1, value: d[key1].toString()); await Future.delayed(Duration.zero); } else {} diff --git a/lib/controller/login_controller.dart b/lib/controller/login_controller.dart index b58b0f3..952eaab 100644 --- a/lib/controller/login_controller.dart +++ b/lib/controller/login_controller.dart @@ -1,9 +1,10 @@ import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:service/constant/links.dart'; import 'package:service/controller/functions/crud.dart'; +import 'package:service/controller/functions/device_helper.dart'; +import 'package:service/controller/functions/encrypt_decrypt.dart'; import '../constant/box_name.dart'; import '../main.dart'; @@ -12,73 +13,73 @@ import '../views/home/main.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'functions/initilize.dart'; - class LoginController extends GetxController { - var email = TextEditingController(); + var email = TextEditingController(); // Kept for UI compatibility var password = TextEditingController(); final formKey = GlobalKey(); - // Use FlutterSecureStorage instead of GetStorage final FlutterSecureStorage storage = const FlutterSecureStorage(); void login() async { - String? storedEmail = await storage.read(key: 'email'); + // Ensure fingerprint is ready + String fingerprint = box.read(BoxName.fingerPrint) ?? ''; + if (fingerprint.isEmpty) { + fingerprint = await DeviceHelper.getDeviceFingerprint(); + } + String? storedPassword = await storage.read(key: 'password'); + String pass = storedPassword ?? password.text; - await CRUD() - .getJWT(storedPassword ?? password.text, storedEmail ?? email.text); + if (pass.isEmpty && !formKey.currentState!.validate()) return; - if (storedEmail != null) { - var payload = { - "email": storedEmail, - "password": storedPassword, - }; - Log.print('payload: ${payload}'); - var res = await CRUD().get(link: AppLink.login, payload: payload); - Log.print('res: ${res}'); + var payload = { + "fingerprint": fingerprint, + "password": pass, + "aud": "service", + }; - // if (res != 'failure') { - var d = jsonDecode(res); - Log.print('d: ${d}'); - if (d['message'] == "Login successful") { - // Save data securely in FlutterSecureStorage + Log.print('🚀 Login Payload: $payload'); + var res = await CRUD().post(link: AppLink.login, payload: payload); + Log.print('📥 Login Response: $res'); - await box.write(BoxName.employeename, d['data']['first_name']); - Get.off(() => Main()); - // } - } + if (res != 'failure' && res is Map && res['status'] == 'success') { + var d = res['message']; // V1 returns {status, message: {jwt, data: {user...}}} + + // Store JWT + final jwt = d['jwt']; + box.write(BoxName.jwt, c(jwt)); + + // Store User Data + var userData = d['data']; + await storage.write(key: 'name', value: userData['first_name']); + await storage.write(key: 'driverID', value: userData['id'].toString()); + await storage.write(key: 'password', value: pass); + await box.write(BoxName.employeename, userData['first_name']); + await box.write(BoxName.password, pass); + + Get.offAll(() => Main()); } else { - if (formKey.currentState!.validate()) { - var payload = { - "email": storedEmail ?? email.text, - "password": storedPassword ?? password.text, - }; - Log.print('payload: ${payload}'); - var res = await CRUD().get(link: AppLink.login, payload: payload); - Log.print('res: ${res}'); - - // if (res != 'failure') { - var d = jsonDecode(res); - Log.print('d: ${d}'); - if (d['message'] == "Login successful") { - // Save data securely in FlutterSecureStorage - await storage.write(key: 'email', value: d['data']['email']); - await storage.write(key: 'name', value: d['data']['first_name']); - await storage.write(key: 'driverID', value: d['data']['id']); - await storage.write(key: 'password', value: password.text); - await box.write(BoxName.employeename, d['data']['first_name']); - - Get.off(() => Main()); - // } - } - } + Get.snackbar( + 'خطأ'.tr, + res is Map ? res['message'].toString().tr : 'فشل تسجيل الدخول'.tr, + backgroundColor: Colors.red.withOpacity(0.7), + colorText: Colors.white, + ); } } @override - void onInit() { - login(); + void onInit() async { + await EncryptionHelper.initialize(); + await DeviceHelper.getDeviceFingerprint(); + + // Auto login if credentials exist + String? storedPassword = await storage.read(key: 'password'); + if (storedPassword != null) { + login(); + } + + super.onInit(); } } diff --git a/lib/controller/mainController/main_controller.dart b/lib/controller/mainController/main_controller.dart index a659ce6..4a91b6f 100644 --- a/lib/controller/mainController/main_controller.dart +++ b/lib/controller/mainController/main_controller.dart @@ -180,7 +180,7 @@ class MainController extends GetxController { var res = await CRUD() .get(link: AppLink.getDriverNotCompleteRegistration, payload: {}); if (res != 'failure') { - var d = jsonDecode(res)['message']; + var d = res['message']; driverNotCompleteRegistration = d; filteredDrivers = driverNotCompleteRegistration; update(); @@ -208,7 +208,7 @@ class MainController extends GetxController { var res = await CRUD().get(link: AppLink.getDriversWaitingActive, payload: {}); if (res != 'failure') { - var d = jsonDecode(res)['message']; + var d = res['message']; driverWantCompleteRegistration = d; filteredDrivers = driverWantCompleteRegistration; update(); @@ -222,7 +222,7 @@ class MainController extends GetxController { var res = await CRUD().get(link: AppLink.getDriversPhoneNotComplete, payload: {}); if (res != 'failure') { - var d = jsonDecode(res)['message']; + var d = res['message']; driverWantCompleteRegistration = d; filteredDrivers = driverWantCompleteRegistration; update(); @@ -235,7 +235,7 @@ class MainController extends GetxController { getNewDriverRegister() async { var res = await CRUD().get(link: AppLink.getNewDriverRegister, payload: {}); if (res != 'failure') { - var d = jsonDecode(res)['message']; + var d = res['message']; newDriverRegister = d; update(); } else { @@ -248,7 +248,7 @@ class MainController extends GetxController { "driverId": driveId, "notes": notesController.text, }); - if (res != 'failue') { + if (res != 'failure') { Get.snackbar('Success'.tr, '', backgroundColor: AppColor.greenColor); } } @@ -259,7 +259,7 @@ class MainController extends GetxController { var res = await CRUD() .get(link: AppLink.getPassengersNotCompleteRegistration, payload: {}); if (res != 'failure') { - var d = jsonDecode(res)['message']; + var d = res['message']; passengerNotCompleteRegistration = d; update(); } else { @@ -285,7 +285,7 @@ class MainController extends GetxController { getCarPlateNotEdit() async { var res = await CRUD().get(link: AppLink.getCarPlateNotEdit, payload: {}); if (res != 'failure') { - var d = jsonDecode(res)['message']; + var d = res['message']; carPlateNotEdit = d; update(); } else { @@ -300,7 +300,7 @@ class MainController extends GetxController { getdriverWithoutCar() async { var res = await CRUD().get(link: AppLink.getdriverWithoutCar, payload: {}); if (res != 'failure') { - var d = jsonDecode(res)['message']; + var d = res['message']; driverWithoutCar = d; update(); } else { @@ -351,11 +351,11 @@ class MainController extends GetxController { isLoading = false; update(); - var status = jsonDecode(res); + var status = res; Log.print('res: $res'); Log.print('status: $status'); - if (status['status'] == 'success') { + if (status != 'failure' && status['status'] == 'success') { await Future.wait([ CRUD().post( link: @@ -492,7 +492,7 @@ class MainController extends GetxController { payload: {"phone": passengerPhoneController.text}); if (res != 'failure') { - var d = jsonDecode(res); + var d = res; passengerData = d; update(); } @@ -504,7 +504,7 @@ class MainController extends GetxController { payload: {"phone": driverPhoneController.text}); if (res != 'failure') { - var d = jsonDecode(res); + var d = res; driverData = d; update(); } else { @@ -518,7 +518,7 @@ class MainController extends GetxController { payload: {"national_number": driverPhoneController.text}); if (res != 'failure') { - var d = jsonDecode(res); + var d = res; driverData = d; update(); } else { diff --git a/lib/controller/mainController/pages/best_driver_page.dart b/lib/controller/mainController/pages/best_driver_page.dart index 18c9130..0511082 100644 --- a/lib/controller/mainController/pages/best_driver_page.dart +++ b/lib/controller/mainController/pages/best_driver_page.dart @@ -96,7 +96,7 @@ class Driverthebest extends GetxController { getBestDriver() async { var res = await CRUD().get(link: AppLink.getBestDriver, payload: {}); if (res != 'failure') { - driver = jsonDecode(res)['message']; + driver = res['message']; update(); } else { Get.snackbar('error', '', backgroundColor: AppColor.redColor); diff --git a/lib/controller/mainController/ragister_service_controller.dart b/lib/controller/mainController/ragister_service_controller.dart index f53fe0c..26000f6 100644 --- a/lib/controller/mainController/ragister_service_controller.dart +++ b/lib/controller/mainController/ragister_service_controller.dart @@ -108,7 +108,7 @@ class RegisterCaptainServiceController extends GetxController { payload: {'driverId': driverId.value}); if (responseString != 'failure') { - var decodedResponse = jsonDecode(responseString); + var decodedResponse = responseString; if (decodedResponse['status'] == 'success' && (decodedResponse['message'] as List).isNotEmpty) { var rawData = decodedResponse['message'][0] as Map; @@ -261,7 +261,7 @@ class RegisterCaptainServiceController extends GetxController { isLoading.value = false; var decodedResponse = (response); Log.print('decodedResponse: ${decodedResponse}'); - if (decodedResponse != 'failure') { + if (decodedResponse != 'failure' && decodedResponse['status'] == 'success') { MyDialog().getDialog('Success'.tr, '', Text('Driver has been activated successfully!'.tr), () { Get.back(); @@ -273,7 +273,7 @@ class RegisterCaptainServiceController extends GetxController { } else { Get.snackbar( 'Error'.tr, - 'Failed to update driver: ${decodedResponse['message']}'.tr, + 'Failed to update driver: ${decodedResponse is Map ? decodedResponse['message'] : 'failure'}'.tr, backgroundColor: Colors.red, colorText: Colors.white, ); diff --git a/lib/controller/mainController/registration_captain_controller.dart b/lib/controller/mainController/registration_captain_controller.dart index 5f568c8..7f1a7cd 100644 --- a/lib/controller/mainController/registration_captain_controller.dart +++ b/lib/controller/mainController/registration_captain_controller.dart @@ -107,7 +107,7 @@ class RegisterCaptainController extends GetxController { payload: {'driverId': driverId.value}); if (responseString != 'failure') { - var decodedResponse = jsonDecode(responseString); + var decodedResponse = responseString; if (decodedResponse['status'] == 'success' && (decodedResponse['message'] as List).isNotEmpty) { var rawData = decodedResponse['message'][0] as Map; @@ -247,7 +247,7 @@ class RegisterCaptainController extends GetxController { isLoading.value = false; var decodedResponse = (response); Log.print('decodedResponse: ${decodedResponse}'); - if (decodedResponse != 'failure') { + if (decodedResponse != 'failure' && decodedResponse['status'] == 'success') { MyDialog().getDialog('Success'.tr, '', Text('Driver has been activated successfully!'.tr), () { Get.back(); @@ -259,7 +259,7 @@ class RegisterCaptainController extends GetxController { } else { Get.snackbar( 'Error'.tr, - 'Failed to update driver: ${decodedResponse['message']}'.tr, + 'Failed to update driver: ${decodedResponse is Map ? decodedResponse['message'] : 'failure'}'.tr, backgroundColor: Colors.red, colorText: Colors.white, ); diff --git a/lib/login_page.dart b/lib/login_page.dart index c63b9db..cfbc9cc 100644 --- a/lib/login_page.dart +++ b/lib/login_page.dart @@ -1,50 +1,171 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:service/main.dart'; +import 'package:service/constant/colors.dart'; +import 'package:service/views/auth/register_page.dart'; import 'package:service/views/widgets/my_textField.dart'; import 'controller/login_controller.dart'; class LoginPage extends StatelessWidget { - final LoginController controller = Get.put(LoginController()); + const LoginPage({super.key}); @override Widget build(BuildContext context) { + final LoginController controller = Get.put(LoginController()); + return Scaffold( - appBar: const CupertinoNavigationBar( - middle: Text('Login'), - ), - body: SafeArea( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Form( - key: controller.formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox(height: 20), - MyTextForm( - controller: controller.email, - label: 'email', - hint: 'email', - type: TextInputType.emailAddress), - const SizedBox(height: 20), - MyTextForm( - controller: controller.password, - label: 'Password', - hint: 'Password', - type: TextInputType.name), - const SizedBox(height: 40), - CupertinoButton.filled( - child: const Text('Login'), - onPressed: () { - controller.login(); - }, + backgroundColor: Colors.white, + body: Stack( + children: [ + // Background Gradient Element + Positioned( + top: -100, + right: -100, + child: Container( + width: 300, + height: 300, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + colors: [AppColor.blueColor.withOpacity(0.2), Colors.transparent], + begin: Alignment.topRight, + end: Alignment.bottomLeft, ), - ], + ), ), ), - ), + + SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 30.0), + child: Form( + key: controller.formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 80), + // App Logo or Icon + const Center( + child: Icon( + Icons.support_agent_rounded, + size: 100, + color: AppColor.blueColor, + ), + ), + const SizedBox(height: 24), + const Center( + child: Text( + 'انطلق سيرفس', + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.black87, + letterSpacing: 1.2, + ), + ), + ), + const Center( + child: Text( + 'نظام خدمة العملاء المتكامل', + style: TextStyle( + fontSize: 16, + color: Colors.grey, + ), + ), + ), + const SizedBox(height: 60), + + // Fields with modern styling + const Text( + 'تسجيل الدخول', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: Colors.black87, + ), + ), + const SizedBox(height: 20), + + MyTextForm( + controller: controller.email, + label: 'البريد الإلكتروني', + hint: 'أدخل البريد الإلكتروني', + type: TextInputType.emailAddress, + ), + const SizedBox(height: 20), + + MyTextForm( + controller: controller.password, + label: 'كلمة المرور', + hint: 'أدخل كلمة المرور', + type: TextInputType.visiblePassword, + ), + + const SizedBox(height: 40), + + // Login Button + Container( + height: 55, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + gradient: const LinearGradient( + colors: [AppColor.blueColor, Color(0xFF1A237E)], + ), + boxShadow: [ + BoxShadow( + color: AppColor.blueColor.withOpacity(0.3), + blurRadius: 12, + offset: const Offset(0, 6), + ), + ], + ), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(16), + onTap: () => controller.login(), + child: const Center( + child: Text( + 'دخول', + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + ), + + const SizedBox(height: 30), + + // Register Link + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'ليس لديك حساب موظف؟ ', + style: TextStyle(color: Colors.grey), + ), + TextButton( + onPressed: () => Get.to(() => const RegisterPage()), + child: const Text( + 'إنشاء حساب جديد', + style: TextStyle( + color: AppColor.blueColor, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ], ), ); } diff --git a/lib/main.dart b/lib/main.dart index ae31a4e..cc48a0e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,7 +7,6 @@ import 'package:service/controller/firbase_messge.dart'; import 'package:service/firebase_options.dart'; import 'controller/functions/encrypt_decrypt.dart'; -import 'controller/functions/initilize.dart'; import 'controller/local/local_controller.dart'; import 'controller/local/translations.dart'; import 'login_page.dart'; diff --git a/lib/views/auth/register_page.dart b/lib/views/auth/register_page.dart new file mode 100644 index 0000000..e46ebd5 --- /dev/null +++ b/lib/views/auth/register_page.dart @@ -0,0 +1,172 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:service/constant/colors.dart'; +import 'package:service/controller/auth/register_controller.dart'; +import 'package:service/views/widgets/my_textField.dart'; + +class RegisterPage extends StatelessWidget { + const RegisterPage({super.key}); + + @override + Widget build(BuildContext context) { + final RegisterController controller = Get.put(RegisterController()); + + return Scaffold( + backgroundColor: const Color(0xFFF8F9FD), + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios_new, color: Colors.black87), + onPressed: () => Get.back(), + ), + title: Text( + 'إنشاء حساب موظف'.tr, + style: const TextStyle(color: Colors.black87, fontWeight: FontWeight.bold), + ), + centerTitle: true, + ), + body: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0), + child: Form( + key: controller.formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Center( + child: Icon( + Icons.person_add_rounded, + size: 80, + color: AppColor.blueColor, + ), + ), + const SizedBox(height: 32), + + _buildFieldTitle('الاسم الأول'), + MyTextForm( + controller: controller.firstName, + label: 'الاسم الأول', + hint: 'أدخل الاسم الأول', + type: TextInputType.name, + ), + const SizedBox(height: 16), + + _buildFieldTitle('الاسم الأخير'), + MyTextForm( + controller: controller.lastName, + label: 'الاسم الأخير', + hint: 'أدخل الاسم الأخير', + type: TextInputType.name, + ), + const SizedBox(height: 16), + + _buildFieldTitle('البريد الإلكتروني'), + MyTextForm( + controller: controller.email, + label: 'البريد الإلكتروني', + hint: 'example@mail.com', + type: TextInputType.emailAddress, + ), + const SizedBox(height: 16), + + _buildFieldTitle('رقم الهاتف'), + MyTextForm( + controller: controller.phone, + label: 'رقم الهاتف', + hint: '09xxxxxxxx', + type: TextInputType.phone, + ), + const SizedBox(height: 16), + + _buildFieldTitle('كلمة المرور'), + MyTextForm( + controller: controller.password, + label: 'كلمة المرور', + hint: '********', + type: TextInputType.visiblePassword, + ), + const SizedBox(height: 40), + + Obx(() => controller.isLoading.value + ? const Center(child: CircularProgressIndicator()) + : Container( + height: 55, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + gradient: const LinearGradient( + colors: [AppColor.blueColor, Color(0xFF1A237E)], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + boxShadow: [ + BoxShadow( + color: AppColor.blueColor.withOpacity(0.3), + blurRadius: 12, + offset: const Offset(0, 6), + ), + ], + ), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(16), + onTap: () => controller.register(), + child: const Center( + child: Text( + 'تقديم طلب تسجيل', + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + )), + + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'لديك حساب بالفعل؟ '.tr, + style: const TextStyle(color: Colors.grey), + ), + TextButton( + onPressed: () => Get.back(), + child: const Text( + 'تسجيل الدخول', + style: TextStyle( + color: AppColor.blueColor, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + const SizedBox(height: 20), + ], + ), + ), + ), + ), + ); + } + + Widget _buildFieldTitle(String title) { + return Padding( + padding: const EdgeInsets.only(bottom: 8.0, right: 4.0), + child: Text( + title, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Colors.black54, + ), + ), + ); + } +} diff --git a/lib/views/home/main.dart b/lib/views/home/main.dart index 98e460b..b7e3ae9 100644 --- a/lib/views/home/main.dart +++ b/lib/views/home/main.dart @@ -262,7 +262,7 @@ class Main extends StatelessWidget { "license_type": mainController.licenseTypeController.text, "phone": mainController.phoneController.text, }); - if (res != 'failure') { + if (res != 'failure' && res['status'] == 'success') { Get.back(); mainController.driverNameController.clear(); mainController.nationalIdController.clear(); @@ -361,7 +361,7 @@ class Main extends StatelessWidget { "phone": mainController.phoneCarController.text, }); Log.print('res: ${res}'); - if (res != 'failure') { + if (res != 'failure' && res['status'] == 'success') { Get.back(); mainController.ownerController.clear(); mainController.carNumberController.clear(); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 9ce94c4..fbedf4a 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -9,6 +9,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 87f6847..d845562 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -14,7 +14,6 @@ import flutter_image_compress_macos import flutter_local_notifications import flutter_secure_storage_macos import google_sign_in_ios -import path_provider_foundation import share_plus import sqflite_darwin import url_launcher_macos @@ -29,7 +28,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 62c4287..4762991 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,34 +5,34 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f + sha256: "8d7ff3948166b8ec5da0fbb5962000926b8e02f2ed9b3e51d1738905fbd4c98d" url: "https://pub.dev" source: hosted - version: "85.0.0" + version: "93.0.0" _flutterfire_internals: dependency: transitive description: name: _flutterfire_internals - sha256: bb84ee51e527053dd8e25ecc9f97a6abfdc19130fb4d883e4e8585e23e7e6dd8 + sha256: bda3b7b55958bfd867addc40d067b4b11f7b8846d57671f5b5a6e7f9a56fe3ad url: "https://pub.dev" source: hosted - version: "1.3.60" + version: "1.3.69" analyzer: dependency: transitive description: name: analyzer - sha256: "974859dc0ff5f37bc4313244b3218c791810d03ab3470a579580279ba971a48d" + sha256: de7148ed2fcec579b19f122c1800933dfa028f6d9fd38a152b04b1516cec120b url: "https://pub.dev" source: hosted - version: "7.7.1" + version: "10.0.1" archive: dependency: transitive description: name: archive - sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" + sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff url: "https://pub.dev" source: hosted - version: "4.0.7" + version: "4.0.9" args: dependency: transitive description: @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 url: "https://pub.dev" source: hosted - version: "2.13.0" + version: "2.13.1" boolean_selector: dependency: transitive description: @@ -69,50 +69,34 @@ packages: dependency: transitive description: name: build - sha256: "51dc711996cbf609b90cbe5b335bbce83143875a9d58e4b5c6d3c4f684d3dda7" + sha256: a156715e7cd728130c592f30552575908aae5b100005fbc1f0fb16b3c03a3d10 url: "https://pub.dev" source: hosted - version: "2.5.4" + version: "4.0.6" build_config: dependency: transitive description: name: build_config - sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + sha256: "4070d2a59f8eec34c97c86ceb44403834899075f66e8a9d59706f8e7834f6f71" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.3.0" build_daemon: dependency: transitive description: name: build_daemon - sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" + sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 url: "https://pub.dev" source: hosted - version: "4.0.4" - build_resolvers: - dependency: transitive - description: - name: build_resolvers - sha256: ee4257b3f20c0c90e72ed2b57ad637f694ccba48839a821e87db762548c22a62 - url: "https://pub.dev" - source: hosted - version: "2.5.4" + version: "4.1.1" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "382a4d649addbfb7ba71a3631df0ec6a45d5ab9b098638144faf27f02778eb53" + sha256: "22fdcc3cfeb9d974d7408718c4be15ec5e9b1b350088f3a6c88f154e74dd700d" url: "https://pub.dev" source: hosted - version: "2.5.4" - build_runner_core: - dependency: transitive - description: - name: build_runner_core - sha256: "85fbbb1036d576d966332a3f5ce83f2ce66a40bea1a94ad2d5fc29a19a0d3792" - url: "https://pub.dev" - source: hosted - version: "9.1.2" + version: "2.14.1" built_collection: dependency: transitive description: @@ -125,18 +109,18 @@ packages: dependency: transitive description: name: built_value - sha256: "0b1b12a0a549605e5f04476031cd0bc91ead1d7c8e830773a18ee54179b3cb62" + sha256: "0730c18c770d05636a8f945c32a4d7d81cb6e0f0148c8db4ad12e7748f7e49af" url: "https://pub.dev" source: hosted - version: "8.11.0" + version: "8.12.5" characters: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" checked_yaml: dependency: transitive description: @@ -161,14 +145,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" + url: "https://pub.dev" + source: hosted + version: "1.0.0" code_builder: dependency: transitive description: name: code_builder - sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d" url: "https://pub.dev" source: hosted - version: "4.10.1" + version: "4.11.1" collection: dependency: transitive description: @@ -189,44 +181,44 @@ packages: dependency: transitive description: name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" url: "https://pub.dev" source: hosted - version: "0.3.4+2" + version: "0.3.5+2" crypto: dependency: "direct main" description: name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.7" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" url: "https://pub.dev" source: hosted - version: "1.0.8" + version: "1.0.9" dart_style: dependency: transitive description: name: dart_style - sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" + sha256: "29f7ecc274a86d32920b1d9cfc7502fa87220da41ec60b55f329559d5732e2b2" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.7" dbus: dependency: transitive description: name: dbus - sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270 url: "https://pub.dev" source: hosted - version: "0.7.11" + version: "0.7.12" device_info_plus: - dependency: transitive + dependency: "direct main" description: name: device_info_plus sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" @@ -253,26 +245,26 @@ packages: dependency: "direct main" description: name: envied - sha256: a4e2b1d0caa479b5d61332ae516518c175a6d09328a35a0bc0a53894cc5d7e4d + sha256: cac8bf0df6c53bd3c3511a6ee295ba6b86e6547df25c8c8648fc479128d2317c url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.3.4" envied_generator: dependency: "direct dev" description: name: envied_generator - sha256: "894f6c5eb624c60a1ce6f642b6fd7ec68bc3440aa6f1881837aa9acbbeade0c8" + sha256: ac7c2d0871a25a917f145a42ca6b4596b81b97d71017a511e0b3ffa60067cf75 url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.3.4" equatable: dependency: transitive description: name: equatable - sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" + sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.0.8" fake_async: dependency: transitive description: @@ -285,10 +277,10 @@ packages: dependency: transitive description: name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" file: dependency: transitive description: @@ -301,106 +293,106 @@ packages: dependency: transitive description: name: file_selector_linux - sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" + sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0" url: "https://pub.dev" source: hosted - version: "0.9.3+2" + version: "0.9.4" file_selector_macos: dependency: transitive description: name: file_selector_macos - sha256: "8c9250b2bd2d8d4268e39c82543bacbaca0fda7d29e0728c3c4bbb7c820fd711" + sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a" url: "https://pub.dev" source: hosted - version: "0.9.4+3" + version: "0.9.5" file_selector_platform_interface: dependency: transitive description: name: file_selector_platform_interface - sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85" url: "https://pub.dev" source: hosted - version: "2.6.2" + version: "2.7.0" file_selector_windows: dependency: transitive description: name: file_selector_windows - sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" + sha256: "62197474ae75893a62df75939c777763d39c2bc5f73ce5b88497208bc269abfd" url: "https://pub.dev" source: hosted - version: "0.9.3+4" + version: "0.9.3+5" firebase_auth: dependency: "direct main" description: name: firebase_auth - sha256: "974541532dc3f5ea3c0d7c5bb3e6c90fb81a8950e0e15c4a11e2b17a06379070" + sha256: b12cb1e2e87797d27e0041100b73ebf890dbafcff2e7e991d4593f5e8e309808 url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.4.0" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface - sha256: "86a6318fd53a2958a9323454a4b8601b19963030157d71f92e356deadf9a3551" + sha256: c71517b3c78480be42789b05316a7692d69296c17848bd6a9e798300abae1ec7 url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.1.9" firebase_auth_web: dependency: transitive description: name: firebase_auth_web - sha256: "042d424d50515cd62b4c0bda70872f5fa7e69c905e442b087e07e0117aac1222" + sha256: "52b0224eb46b09f387e99710707be2d3f48da67c74fe14202e4b942cbe8ce9fd" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.1.5" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "6b343e6f7b72a4f32d7ce8df8c9a28d8f54b4ac20d7c6500f3e8b3969afca457" + sha256: d5a94b884dcb1e6d3430298e94bfe002238094cdfd5e29202d536ee2120f9158 url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.7.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: "5dbc900677dcbe5873d22ad7fbd64b047750124f1f9b7ebe2a33b9ddccc838eb" + sha256: "0ecda14c1bfc9ed8cac303dd0f8d04a320811b479362a9a4efb14fd331a473ce" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.0.3" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: "5d28b14dd32282fb7ce2b22b897362453755b6b8541d491127dc72b755bb7b16" + sha256: dc5096257cd67292d34d78ceeb90836f02a4be921b5f3934311a02bb2376118c url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.6.0" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: "10272b553a49c13a6cedfd00121047157521f82a5d3f2a1706b9dd28342cc482" + sha256: e5c93e8e7a9b0513f94bb684d2cf100e32e7dcdf2949574386b1955fc9a9b96a url: "https://pub.dev" source: hosted - version: "16.0.0" + version: "16.2.0" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: b846a305feb3f74ee3f0aace447f65a4696bc6550bc828ecf5a84a1b77473d16 + sha256: "8cbb7d842e5071bba836452aff262f7db4b14bb3a0d00c1896cf176df886d65a" url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "4.7.9" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: "28714749880f7242c5fb3b1ee6c66b41f61453f02ae348b43c82957df80b87ae" + sha256: "8750bacf50573c0383535fc3f9c58c6a2f9dff5320a16a82c30631b9dad894f1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.1.5" fixnum: dependency: transitive description: @@ -514,10 +506,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e + sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0" url: "https://pub.dev" source: hosted - version: "2.0.28" + version: "2.0.34" flutter_secure_storage: dependency: "direct main" description: @@ -576,22 +568,14 @@ packages: description: flutter source: sdk version: "0.0.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" get: dependency: "direct main" description: name: get - sha256: c79eeb4339f1f3deffd9ec912f8a923834bec55f7b49c9e882b8fef2c139d425 + sha256: "5ed34a7925b85336e15d472cc4cfe7d9ebf4ab8e8b9f688585bf6b50f4c3d79a" url: "https://pub.dev" source: hosted - version: "4.7.2" + version: "4.7.3" get_storage: dependency: "direct main" description: @@ -612,10 +596,10 @@ packages: dependency: "direct main" description: name: google_fonts - sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 + sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055 url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.3.3" google_identity_services_web: dependency: transitive description: @@ -628,42 +612,42 @@ packages: dependency: "direct main" description: name: google_sign_in - sha256: "939a8b58f84c4053811b8c1bc9adbcb59449a15b37958264bbf60020698cca0e" + sha256: "521031b65853b4409b8213c0387d57edaad7e2a949ce6dea0d8b2afc9cb29763" url: "https://pub.dev" source: hosted - version: "7.1.1" + version: "7.2.0" google_sign_in_android: dependency: transitive description: name: google_sign_in_android - sha256: f256b8f0e6c09d135c166fe20b25256e24d60fe1a72e6bdc112a200bd0d555b4 + sha256: be0d0733a6a7c5da165879d844a239aa87587a3c767a9163faedde581f731f76 url: "https://pub.dev" source: hosted - version: "7.0.3" + version: "7.2.10" google_sign_in_ios: dependency: transitive description: name: google_sign_in_ios - sha256: c7ee744ebbcd98353966dbdee735d4fca085226f6bf725c6bea8a5c8fe0055bc + sha256: ac1e4c1205267cb7999d1d81333fccffdfda29e853f434bbaf71525498bb6950 url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.3.0" google_sign_in_platform_interface: dependency: transitive description: name: google_sign_in_platform_interface - sha256: "8736443134d2cccadd4f228d600177cb3947e36683466a6ab96877ce6932885a" + sha256: "7f59208c42b415a3cca203571128d6f84f885fead2d5b53eb65a9e27f2965bb5" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.1.0" google_sign_in_web: dependency: transitive description: name: google_sign_in_web - sha256: "09ac306b2787b48f19c857b9f93375b654f774643c75bd6a1a078c85f4f7b468" + sha256: d473003eeca892f96a01a64fc803378be765071cb0c265ee872c7f8683245d14 url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.1.3" graphs: dependency: transitive description: @@ -672,14 +656,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + hooks: + dependency: transitive + description: + name: hooks + sha256: "025f060e86d2d4c3c47b56e33caf7f93bf9283340f26d23424ebcfccf34f621e" + url: "https://pub.dev" + source: hosted + version: "1.0.3" http: dependency: "direct main" description: name: http - sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.6.0" http_multi_server: dependency: transitive description: @@ -700,10 +692,10 @@ packages: dependency: "direct main" description: name: image - sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" + sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce url: "https://pub.dev" source: hosted - version: "4.5.4" + version: "4.8.0" image_cropper: dependency: "direct main" description: @@ -724,74 +716,74 @@ packages: dependency: transitive description: name: image_cropper_platform_interface - sha256: "6ca6b81769abff9a4dcc3bbd3d75f5dfa9de6b870ae9613c8cd237333a4283af" + sha256: "2d8db8f4b638e448fa89a1e77cd8f053b4547472bd3ae073169e86626d03afef" url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "7.2.0" image_picker: dependency: "direct main" description: name: image_picker - sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + sha256: "91c025426c2881c551100bce834e201c835a170151545f58d17da5180ca7d9ac" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.2" image_picker_android: dependency: transitive description: name: image_picker_android - sha256: "6fae381e6af2bbe0365a5e4ce1db3959462fa0c4d234facf070746024bb80c8d" + sha256: d5b3e1774af29c9ab00103afb0d4614070f924d2e0057ac867ec98800114793f url: "https://pub.dev" source: hosted - version: "0.8.12+24" + version: "0.8.13+17" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" + sha256: "66257a3191ab360d23a55c8241c91a6e329d31e94efa7be9cf7a212e65850214" url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.1.1" image_picker_ios: dependency: transitive description: name: image_picker_ios - sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100" + sha256: b9c4a438a9ff4f60808c9cf0039b93a42bb6c2211ef6ebb647394b2b3fa84588 url: "https://pub.dev" source: hosted - version: "0.8.12+2" + version: "0.8.13+6" image_picker_linux: dependency: transitive description: name: image_picker_linux - sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9" + sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" url: "https://pub.dev" source: hosted - version: "0.2.1+2" + version: "0.2.2" image_picker_macos: dependency: transitive description: name: image_picker_macos - sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1" + sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91" url: "https://pub.dev" source: hosted - version: "0.2.1+2" + version: "0.2.2+1" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface - sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0" + sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c" url: "https://pub.dev" source: hosted - version: "2.10.1" + version: "2.11.1" image_picker_windows: dependency: transitive description: name: image_picker_windows - sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae url: "https://pub.dev" source: hosted - version: "0.2.1+1" + version: "0.2.2" intl: dependency: "direct main" description: @@ -808,6 +800,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" + jni: + dependency: transitive + description: + name: jni + sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f + url: "https://pub.dev" + source: hosted + version: "1.0.0" + jni_flutter: + dependency: transitive + description: + name: jni_flutter + sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6" + url: "https://pub.dev" + source: hosted + version: "1.0.1" js: dependency: transitive description: @@ -820,10 +828,10 @@ packages: dependency: transitive description: name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 url: "https://pub.dev" source: hosted - version: "4.9.0" + version: "4.11.0" jwt_decoder: dependency: "direct main" description: @@ -836,34 +844,34 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: name: lints - sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.1.0" logging: dependency: transitive description: @@ -876,26 +884,26 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.18" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -904,6 +912,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" + url: "https://pub.dev" + source: hosted + version: "0.17.6" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" + url: "https://pub.dev" + source: hosted + version: "9.3.0" package_config: dependency: transitive description: @@ -932,18 +956,18 @@ packages: dependency: transitive description: name: path_provider_android - sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" url: "https://pub.dev" source: hosted - version: "2.2.17" + version: "2.3.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.6.0" path_provider_linux: dependency: transitive description: @@ -1020,10 +1044,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "7.0.2" platform: dependency: transitive description: @@ -1052,18 +1076,18 @@ packages: dependency: transitive description: name: pool - sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" url: "https://pub.dev" source: hosted - version: "1.5.1" + version: "1.5.2" posix: dependency: transitive description: name: posix - sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07" url: "https://pub.dev" source: hosted - version: "6.0.3" + version: "6.5.0" pub_semver: dependency: transitive description: @@ -1088,6 +1112,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" + record_use: + dependency: transitive + description: + name: record_use + sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" + url: "https://pub.dev" + source: hosted + version: "0.6.0" secure_string_operations: dependency: "direct main" description: @@ -1136,50 +1168,42 @@ packages: dependency: transitive description: name: source_gen - sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" + sha256: ec37cc0e6694374cbef59ed79685572c870a54ede6fa30a3e420feb3adffea02 url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "4.2.3" source_span: dependency: transitive description: name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" url: "https://pub.dev" source: hosted - version: "1.10.1" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" + version: "1.10.2" sqflite: dependency: "direct main" description: name: sqflite - sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 + sha256: "564cfed0746fe53140c23b70b308e045c3b31f17778f2f326ccb7d804ea0250a" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.2+1" sqflite_android: dependency: transitive description: name: sqflite_android - sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b" + sha256: "881e28efdcc9950fd8e9bb42713dcf1103e62a2e7168f23c9338d82db13dec40" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2+3" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" + sha256: "5e8377564d95166761a968ed96104e0569b6b6cc611faac92a36ab8a169112c3" url: "https://pub.dev" source: hosted - version: "2.5.6" + version: "2.5.6+1" sqflite_darwin: dependency: transitive description: @@ -1232,10 +1256,10 @@ packages: dependency: transitive description: name: synchronized - sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 + sha256: "63896c27e81b28f8cb4e69ead0d3e8f03f1d1e5fc531a3e579cabed6a2c7c9e5" url: "https://pub.dev" source: hosted - version: "3.4.0" + version: "3.4.0+1" term_glyph: dependency: transitive description: @@ -1248,10 +1272,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.9" timezone: dependency: transitive description: @@ -1260,14 +1284,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.10.1" - timing: - dependency: transitive - description: - name: timing - sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" - url: "https://pub.dev" - source: hosted - version: "1.0.2" typed_data: dependency: transitive description: @@ -1288,34 +1304,34 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79" + sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572" url: "https://pub.dev" source: hosted - version: "6.3.16" + version: "6.3.29" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" + sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" url: "https://pub.dev" source: hosted - version: "6.3.3" + version: "6.4.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.2.5" url_launcher_platform_interface: dependency: transitive description: @@ -1328,66 +1344,66 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" + sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" uuid: dependency: transitive description: name: uuid - sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "4.5.3" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vibration: dependency: "direct main" description: name: vibration - sha256: "804ee8f9628f31ee71fbe6137a2bc6206a64e101ec22cd9dd6d3a7dc0272591b" + sha256: "9bb06614c69260f8bd11c80fe01ed7988905cf00e3417d656c2647e41f261d87" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.8" vibration_platform_interface: dependency: transitive description: name: vibration_platform_interface - sha256: "03e9deaa4df48a1a6212e281bfee5f610d62e9247929dd2f26f4efd4fa5e225c" + sha256: "258c273268f8aa40c88d29741137c536874a738779b92ddb8aa32ed093721ec5" url: "https://pub.dev" source: hosted - version: "0.1.0" + version: "0.1.2" vm_service: dependency: transitive description: name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" url: "https://pub.dev" source: hosted - version: "15.0.0" + version: "15.2.0" watcher: dependency: transitive description: name: watcher - sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.1" web: dependency: transitive description: @@ -1416,10 +1432,10 @@ packages: dependency: transitive description: name: win32 - sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e url: "https://pub.dev" source: hosted - version: "5.14.0" + version: "5.15.0" win32_registry: dependency: transitive description: @@ -1440,10 +1456,10 @@ packages: dependency: transitive description: name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" url: "https://pub.dev" source: hosted - version: "6.5.0" + version: "6.6.1" yaml: dependency: transitive description: @@ -1453,5 +1469,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.8.0 <4.0.0" - flutter: ">=3.29.0" + dart: ">=3.11.0 <4.0.0" + flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml index 66e433d..d364ea1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,6 +34,8 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.6 + device_info_plus: ^11.3.3 + secure_string_operations: path: ./secure_string_operations firebase_messaging: ^16.0.0 diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index bc86d5b..56c2648 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -14,6 +14,7 @@ list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST flutter_local_notifications_windows + jni ) set(PLUGIN_BUNDLED_LIBRARIES)