diff --git a/lib/core/auth/controllers/login_controller.dart b/lib/core/auth/controllers/login_controller.dart index 064f4c8..fd2e2d3 100644 --- a/lib/core/auth/controllers/login_controller.dart +++ b/lib/core/auth/controllers/login_controller.dart @@ -54,7 +54,7 @@ class LoginController extends GetxController { isEmailVerified = userCredintial.user!.emailVerified; // let's redirect 🚀 - if (isAdmin && isEmailVerified) { + if (isAdmin) { // this is admin logging in currentAuthState.value = AuthState.adminLoggedIn; Get.offAll(() => const EntryPointUI()); @@ -106,7 +106,11 @@ class LoginController extends GetxController { isAdmin = await UserServices.isAnAdmin(user.uid); isEmailVerified = user.emailVerified; if (!isEmailVerified) { - currentAuthState.value = AuthState.emailUnverified; + if (isAdmin) { + currentAuthState.value = AuthState.adminLoggedIn; + } else { + currentAuthState.value = AuthState.emailUnverified; + } } else { if (isAdmin) currentAuthState.value = AuthState.adminLoggedIn; if (!isAdmin) currentAuthState.value = AuthState.userLoggedIn; diff --git a/lib/core/data/services/app_photo.dart b/lib/core/data/services/app_photo.dart index 07803ec..96d2043 100644 --- a/lib/core/data/services/app_photo.dart +++ b/lib/core/data/services/app_photo.dart @@ -1,11 +1,15 @@ +import 'dart:async'; import 'dart:io'; +import 'dart:isolate'; +import 'dart:ui' as ui; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:http/http.dart' as http; import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:worker_manager/worker_manager.dart'; class AppPhotoService { static Future getImageFromGallery() async { @@ -16,10 +20,7 @@ class AppPhotoService { ); if (pickedFile != null) { - return workerManager.execute( - () => _processAndCropImage(pickedFile.path), - priority: WorkPriority.high, - ); + return _isolateTask(_processAndCropImage, pickedFile.path); } else { print('No image selected.'); return null; @@ -34,12 +35,9 @@ class AppPhotoService { ); if (pickedFile != null) { - return workerManager.execute( - () => _processAndCropImage(pickedFile.path), - priority: WorkPriority.high, - ); + return _isolateTask(_processAndCropImage, pickedFile.path); } else { - print('No image selected.'); + print('No image captured.'); return null; } } @@ -50,27 +48,39 @@ class AppPhotoService { } static Future _goToImageCropper(File? imageFile) async { - if (imageFile == null) return null; + if (imageFile == null) { + print('No image selected.'); + return null; + } else { + print('Image path: ${imageFile.path}'); - final croppedFile = await ImageCropper().cropImage( - sourcePath: imageFile.path, - aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1), - ); + final croppedFile = await ImageCropper().cropImage( + sourcePath: imageFile.path, + aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1), + ); + + if (croppedFile == null) { + print('Image cropping cancelled or failed.'); + return null; + } else { + print('Cropped image path: ${croppedFile.path}'); - if (croppedFile == null) return null; + // Create a File object directly from the path + final File imageFile = File(croppedFile.path); - final myFile = await croppedFile.readAsBytes(); - return File.fromRawPath(myFile); + // Print the path to verify + print('Selected image path: ${imageFile.path}'); + + return imageFile; + } + } } static Future fileFromImageUrl(String imageUrl) async { File? cachedImage = await getImageFromCache(imageUrl); if (cachedImage != null) return cachedImage; - return workerManager.execute( - () => downloadAndSaveImage(imageUrl), - priority: WorkPriority.high, - ); + return _isolateTask(downloadAndSaveImage, imageUrl); } static Future downloadAndSaveImage(String imageUrl) async { @@ -86,4 +96,91 @@ class AppPhotoService { final fileInfo = await DefaultCacheManager().getFileFromCache(imageUrl); return fileInfo?.file; } + + static Future _isolateTask(Function task, dynamic arg) async { + final ReceivePort receivePort = ReceivePort(); + final isolate = await Isolate.spawn( + _isolateEntry, + IsolateData(receivePort.sendPort, task, arg), + debugName: 'ImageProcessingIsolate', + ); + + final result = await receivePort.first as T; + receivePort.close(); + isolate.kill(); + return result; + } + + static void _isolateEntry(IsolateData data) async { + // Initialize BackgroundIsolateBinaryMessenger + BackgroundIsolateBinaryMessenger.ensureInitialized(data.token); + + final result = await data.task(data.arg); + data.sendPort.send(result); + } + + // static Future downloadImageWithProgress(String imageUrl) async { + // final ReceivePort receivePort = ReceivePort(); + // final token = RootIsolateToken.instance!; + // final isolate = await Isolate.spawn( + // _downloadWithProgressEntry, + // DownloadData(receivePort.sendPort, imageUrl, token), + // debugName: 'ImageDownloadIsolate', + // ); + + // File? downloadedFile; + // await for (var message in receivePort) { + // if (message is double) { + // print('Download progress: ${message.toStringAsFixed(2)}%'); + // } else if (message is File) { + // downloadedFile = message; + // break; + // } + // } + + // receivePort.close(); + // isolate.kill(); + // return downloadedFile; + // } + + // static void _downloadWithProgressEntry(DownloadData data) async { + // // Initialize BackgroundIsolateBinaryMessenger + // BackgroundIsolateBinaryMessenger.ensureInitialized(data.token); + + // final response = await http.get(Uri.parse(data.imageUrl)); + // final documentDirectory = await getApplicationDocumentsDirectory(); + // final file = File( + // '${documentDirectory.path}/downloaded_image_${DateTime.now().millisecondsSinceEpoch}'); + + // final totalBytes = response.contentLength ?? 0; + // var downloadedBytes = 0; + + // final sink = file.openWrite(); + // await for (var chunk in response.body.split('')) { + // sink.add(chunk.codeUnits); + // downloadedBytes += chunk.length; + // data.sendPort.send((downloadedBytes / totalBytes) * 100); + // } + // await sink.close(); + + // data.sendPort.send(file); + // } +} + +class IsolateData { + final SendPort sendPort; + final Function task; + final dynamic arg; + final RootIsolateToken token; + + IsolateData(this.sendPort, this.task, this.arg) + : token = RootIsolateToken.instance!; +} + +class DownloadData { + final SendPort sendPort; + final String imageUrl; + final RootIsolateToken token; + + DownloadData(this.sendPort, this.imageUrl, this.token); } diff --git a/lib/core/native_bridge/native_functions.dart b/lib/core/native_bridge/native_functions.dart index 850bc69..e6136e1 100644 --- a/lib/core/native_bridge/native_functions.dart +++ b/lib/core/native_bridge/native_functions.dart @@ -11,11 +11,14 @@ class NativeSDKFunctions { /// Initiate Database of Users to letter verify static Future setSdkDatabase(Map userLists) async { - Get.find().settingSDK(); - bool isDone = - await _channel.invokeMethod('setDatabase', {'membersList': userLists}); - Get.find().settingSdkDone(); - AppToast.show('Face Data Updated'); + bool isDone = false; + if (userLists.isNotEmpty) { + Get.find().settingSDK(); + isDone = await _channel + .invokeMethod('setDatabase', {'membersList': userLists}); + Get.find().settingSdkDone(); + AppToast.show('Face Data Updated'); + } return isDone; } diff --git a/lib/core/widgets/app_button.dart b/lib/core/widgets/app_button.dart index 25e3918..e4aa975 100644 --- a/lib/core/widgets/app_button.dart +++ b/lib/core/widgets/app_button.dart @@ -59,9 +59,10 @@ class AppButton extends StatelessWidget { const EdgeInsets.symmetric(horizontal: 14, vertical: 14), width: width, child: isLoading - ? const CircularProgressIndicator( - color: Colors.white, - strokeWidth: 3, + ? const FittedBox( + child: CircularProgressIndicator( + color: Colors.white, + ), ) : Row( mainAxisSize: MainAxisSize.min, @@ -145,10 +146,9 @@ class AppButtonOutline extends StatelessWidget { alignment: Alignment.center, width: width, child: isLoading - ? const AspectRatio( - aspectRatio: 1 / 1, + ? const FittedBox( child: CircularProgressIndicator( - color: Colors.white, + color: AppColors.primaryColor, ), ) : Row( diff --git a/lib/features/05_members/views/dialogs/camera_or_gallery.dart b/lib/features/05_members/views/dialogs/camera_or_gallery.dart index 338a4a3..d1ed2ec 100644 --- a/lib/features/05_members/views/dialogs/camera_or_gallery.dart +++ b/lib/features/05_members/views/dialogs/camera_or_gallery.dart @@ -60,6 +60,8 @@ class CameraGallerySelectDialog extends StatelessWidget { onTap: () async { File? image = await AppPhotoService.getImageFromGallery(); + + print("selected image path: ${image?.path}"); Get.back(result: image); }, child: Column( diff --git a/lib/features/07_settings/views/controllers/app_admin_controller.dart b/lib/features/07_settings/views/controllers/app_admin_controller.dart index 723ece6..523d91f 100644 --- a/lib/features/07_settings/views/controllers/app_admin_controller.dart +++ b/lib/features/07_settings/views/controllers/app_admin_controller.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:face_attendance/core/data/repository/face_repo.dart'; import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../../core/auth/controllers/login_controller.dart'; @@ -31,6 +32,7 @@ class AppAdminController extends GetxController { await _collectionReference.doc(_currentUserID).get().then((value) { currentUser = AppUser.fromDocumentSnap(value); isUserInitialized = true; + debugPrint("Current user ${currentUser.name}"); update(); }); } catch (e) { diff --git a/lib/main.dart b/lib/main.dart index cc798ac..9115dfd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -25,7 +26,7 @@ void main() async { await GetStorage.init(); AppUiUtil.autoRotateOff(); final core = Get.put(CoreController()); - await w.workerManager.init(); + await w.workerManager.init(dynamicSpawning: true); runApp(TuringTechApp(core: core)); }, (Object error, StackTrace stack) { diff --git a/pubspec.lock b/pubspec.lock index 77d0b96..56e2def 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1153,10 +1153,10 @@ packages: dependency: "direct main" description: name: worker_manager - sha256: "8de97b794040a988b41f475ab0efa03015cc8dff8e130fa3606043572abb4a2c" + sha256: "0c6c4e7d246bcbe7221273ef955732dafb097347d536ebe6acd6547d0398c49c" url: "https://pub.dev" source: hosted - version: "7.0.3" + version: "7.2.2" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 42455e0..a276348 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -45,7 +45,7 @@ dependencies: encrypt: ^5.0.1 visibility_detector: ^0.4.0+2 dartz: ^0.10.0 - worker_manager: ^7.0.3 + worker_manager: ^7.2.2 persistent_bottom_nav_bar: ^6.2.1 auto_size_text: ^3.0.0 firebase_crashlytics: ^3.5.7