diff --git a/android/app/build.gradle b/android/app/build.gradle index 705112da..9d29d984 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -93,6 +93,11 @@ dependencies { implementation 'androidx.window:window:1.0.0' implementation 'androidx.window:window-java:1.0.0' + implementation ('com.google.firebase:firebase-messaging:24.0.0') { + exclude group: 'com.google.firebase', module: 'firebase-iid' + } + + } apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b8fc876e..a04b84f9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -86,6 +86,7 @@ + diff --git a/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart b/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart index f1988f78..eeb79823 100644 --- a/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart +++ b/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart @@ -513,7 +513,7 @@ class _RegisiterVistorTemplateComponentWidgetState child: FFButtonWidget( onPressed: () async { final selectedMedia = - await selectMediaWithSourceBottomSheet( + await selectMediaWithSourceBottomSheetandFaceDetection( context: context, // maxWidth: 300.00, // maxHeight: 300.00, diff --git a/lib/flutter_flow/upload_data.dart b/lib/flutter_flow/upload_data.dart index 1e3b8b9e..b9c3de57 100644 --- a/lib/flutter_flow/upload_data.dart +++ b/lib/flutter_flow/upload_data.dart @@ -4,7 +4,9 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:google_mlkit_face_detection/google_mlkit_face_detection.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; +import 'package:hub/shared/utils/dialog_util.dart'; import 'package:image_picker/image_picker.dart'; import 'package:mime_type/mime_type.dart'; import 'package:video_player/video_player.dart'; @@ -44,6 +46,174 @@ enum MediaSource { camera, } +Future?> selectMediaWithSourceBottomSheetandFaceDetection({ + required BuildContext context, + String? storageFolderPath, + double? maxWidth, + double? maxHeight, + int? imageQuality, + required bool allowPhoto, + bool allowVideo = false, + String pickerFontFamily = 'Roboto', + // Color textColor = const Color(0xFF111417), + // Color backgroundColor = const Color(0xFFF5F5F5), + bool includeDimensions = false, + bool includeBlurHash = false, +}) async { + final faceDetector = FaceDetector( + options: FaceDetectorOptions( + enableContours: true, + enableLandmarks: true, + ), + ); + createUploadMediaListTile( + String label, MediaSource mediaSource, IconData icon) => + ListTile( + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(icon, color: FlutterFlowTheme.of(context).primaryText), + const SizedBox(width: 5), + Text( + label, + textAlign: TextAlign.center, + style: GoogleFonts.getFont( + pickerFontFamily, + color: FlutterFlowTheme.of(context).primaryText, + fontWeight: FontWeight.w600, + fontSize: 12, + ), + ), + ], + ), + tileColor: FlutterFlowTheme.of(context).primaryBackground, + dense: false, + onTap: () => context.pop(mediaSource), + ); + final mediaSource = await showModalBottomSheet( + context: context, + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + builder: (context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (!kIsWeb) ...[ + Container( + margin: const EdgeInsets.only(top: 10), + width: 40, + height: 5, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(10), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(0, 8, 0, 0), + child: ListTile( + title: Text( + FFLocalizations.of(context).getVariableText( + ptText: "Escolha uma das opções", + enText: "Choose one of the options"), + textAlign: TextAlign.center, + style: GoogleFonts.getFont( + pickerFontFamily, + color: FlutterFlowTheme.of(context) + .primaryText + .withOpacity(0.65), + fontWeight: FontWeight.w500, + fontSize: 14, + ), + ), + tileColor: FlutterFlowTheme.of(context).primaryBackground, + dense: true, + ), + ), + ], + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if (allowPhoto && allowVideo) ...[ + Expanded( + child: createUploadMediaListTile( + FFLocalizations.of(context).getVariableText( + ptText: "Galeria (Foto)", + enText: "Gallery (Photo)"), + MediaSource.photoGallery, + Icons.camera), + ), + Expanded( + child: createUploadMediaListTile( + FFLocalizations.of(context).getVariableText( + ptText: "Galeria (Video)", + enText: "Gallery (Video)"), + MediaSource.videoGallery, + Icons.videocam), + ) + ] else if (allowPhoto) + Expanded( + child: createUploadMediaListTile( + FFLocalizations.of(context).getVariableText( + ptText: "Galeria", enText: "Gallery"), + MediaSource.photoGallery, + Icons.photo)) + else + Expanded( + child: createUploadMediaListTile( + FFLocalizations.of(context).getVariableText( + ptText: "Galeria", enText: "Gallery"), + MediaSource.videoGallery, + Icons.videocam), + ), + if (!kIsWeb) ...[ + Expanded( + child: createUploadMediaListTile( + FFLocalizations.of(context).getVariableText( + ptText: "Camera", enText: "Camera"), + MediaSource.camera, + Icons.camera_alt), + ) + ], + ], + ), + const SizedBox(height: 15), + ], + ); + }); + if (mediaSource == null) { + return null; + } + final selectedMedia = await selectMedia( + storageFolderPath: storageFolderPath, + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + isVideo: mediaSource == MediaSource.videoGallery || + (mediaSource == MediaSource.camera && allowVideo && !allowPhoto), + mediaSource: mediaSource, + includeDimensions: includeDimensions, + includeBlurHash: includeBlurHash, + ); + + if (selectedMedia == null || selectedMedia.isEmpty) { + return null; + } + + // Verifique se há faces na imagem + for (final media in selectedMedia) { + final inputImage = InputImage.fromFilePath(media.filePath!); + final faces = await faceDetector.processImage(inputImage); + if (faces.isEmpty) { + final String message = FFLocalizations.of(context).getVariableText( + ptText: "Nenhuma face detectada na imagem", + enText: "No face detected in the image"); + DialogUtil.error(context, message); + return null; + } + } + + return selectedMedia; +} + Future?> selectMediaWithSourceBottomSheet({ required BuildContext context, String? storageFolderPath, @@ -58,7 +228,8 @@ Future?> selectMediaWithSourceBottomSheet({ bool includeDimensions = false, bool includeBlurHash = false, }) async { - createUploadMediaListTile(String label, MediaSource mediaSource, IconData icon) => + createUploadMediaListTile( + String label, MediaSource mediaSource, IconData icon) => ListTile( title: Row( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart index 3e792ee8..4d036e82 100644 --- a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart +++ b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart @@ -1536,7 +1536,8 @@ Widget scheduleVisit(BuildContext context, await ShareUtil.showShare(value.jsonBody); } else { - await DialogUtil.errorDefault(context); + final message = value.jsonBody['error_msg']; + await DialogUtil.error(context, message); context.pop(); } }); diff --git a/pubspec.lock b/pubspec.lock index 34dfa4d3..23421e70 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -113,6 +113,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + camera: + dependency: "direct main" + description: + name: camera + sha256: "26ff41045772153f222ffffecba711a206f670f5834d40ebf5eed3811692f167" + url: "https://pub.dev" + source: hosted + version: "0.11.0+2" + camera_android_camerax: + dependency: transitive + description: + name: camera_android_camerax + sha256: "7cd93578ad201dcc6bb5810451fb00d76a86bab9b68dceb68b8cbd7038ac5846" + url: "https://pub.dev" + source: hosted + version: "0.6.8+3" + camera_avfoundation: + dependency: transitive + description: + name: camera_avfoundation + sha256: "7c28969a975a7eb2349bc2cb2dfe3ad218a33dba9968ecfb181ce08c87486655" + url: "https://pub.dev" + source: hosted + version: "0.9.17+3" + camera_platform_interface: + dependency: transitive + description: + name: camera_platform_interface + sha256: b3ede1f171532e0d83111fe0980b46d17f1aa9788a07a2fbed07366bbdbb9061 + url: "https://pub.dev" + source: hosted + version: "2.8.0" + camera_web: + dependency: transitive + description: + name: camera_web + sha256: "595f28c89d1fb62d77c73c633193755b781c6d2e0ebcd8dc25b763b514e6ba8f" + url: "https://pub.dev" + source: hosted + version: "0.3.5" characters: dependency: transitive description: @@ -701,6 +741,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.2.1" + google_mlkit_commons: + dependency: transitive + description: + name: google_mlkit_commons + sha256: "9990a65f407a3ef6bae646bf10143faa93fec126683771465bc6c0b43fb0e6e9" + url: "https://pub.dev" + source: hosted + version: "0.8.1" + google_mlkit_face_detection: + dependency: "direct main" + description: + name: google_mlkit_face_detection + sha256: "0aeab4f39204f7a235ed4cccedfe7e61401b43f4ef139a868c01fa29fdc225ab" + url: "https://pub.dev" + source: hosted + version: "0.11.1" html: dependency: transitive description: @@ -1346,6 +1402,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -1627,5 +1691,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.22.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index 148e4c8b..3295e84e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,11 +58,13 @@ dependencies: image_picker_platform_interface: 2.10.0 local_auth: ^2.2.0 intl: ^0.19.0 + camera: ^0.11.0+2 json_path: 0.7.2 mime_type: 1.0.0 page_transition: 2.1.0 path_provider: 2.1.3 path_provider_android: 2.2.5 + google_mlkit_face_detection: ^0.11.1 path_provider_foundation: 2.4.0 path_provider_platform_interface: 2.1.2 percent_indicator: 4.2.2