diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index c59078fa..36196b33 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -9,6 +9,7 @@ + + + + + - - - - + + + + + + + + + + + + + + + - + android:resource="@drawable/notification_icon" /> @@ -87,4 +103,10 @@ + + + + + + \ No newline at end of file diff --git a/lib/backend/notifications/firebase_messaging_service.dart b/lib/backend/notifications/firebase_messaging_service.dart index 727c9762..d906b4ed 100644 --- a/lib/backend/notifications/firebase_messaging_service.dart +++ b/lib/backend/notifications/firebase_messaging_service.dart @@ -1,5 +1,6 @@ import 'dart:developer'; +import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:hub/app_state.dart'; import 'package:hub/backend/api_requests/api_calls.dart'; @@ -30,16 +31,28 @@ class FirebaseMessagingService { Future initNotifications() async { await _firebaseMessaging.requestPermission(); - _refreshToken(); + _firebaseMessaging.onTokenRefresh.listen((token) => updateDeviceToken); _firebaseMessaging.setAutoInitEnabled(false); _firebaseMessaging.pluginConstants; - FirebaseMessaging.onBackgroundMessage(handleMessage); + // FirebaseMessaging.onBackgroundMessage(handleMessage); - FirebaseMessaging.onMessage.listen((RemoteMessage message) { - handleMessage(message); - }); + // FirebaseMessaging.onMessage.listen((RemoteMessage message) { + // handleMessage(message); + // }); + + // FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { + // log('A Message was opened: $message'); + // }); + + // FirebaseMessaging.instance + // .getInitialMessage() + // .then((RemoteMessage? message) { + // if (message != null) { + // log('A Message was opened: $message'); + // } + // }); } Future updateDeviceToken() async { @@ -66,8 +79,4 @@ class FirebaseMessagingService { LogUtil.requestAPIFailed("updToken.php", "", "Atualizar Token", e, s); } } - - void _refreshToken() { - _firebaseMessaging.onTokenRefresh.listen((token) => updateDeviceToken); - } } diff --git a/lib/backend/notifications/notification_service.dart b/lib/backend/notifications/notification_service.dart index a494b6b6..0f8c7a6c 100644 --- a/lib/backend/notifications/notification_service.dart +++ b/lib/backend/notifications/notification_service.dart @@ -14,6 +14,189 @@ import 'package:hub/flutter_flow/flutter_flow_widgets.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/shared/utils/dialog_util.dart'; +Future onMessageReceived( + Map payload, String? extra, String? handleClick) async { + final localId = jsonDecode(payload['local']!)['CLI_ID']; + + switch (handleClick) { + case 'visit_request': + showDialog( + context: AppState().context!, + barrierColor: Colors.transparent, + barrierDismissible: true, + builder: (BuildContext context) { + return Dialog( + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.8, + height: MediaQuery.of(context).size.height * 0.6, + child: DetailsComponentWidget( + buttons: [ + FlutterFlowIconButton( + icon: const Icon(Icons.done), + onPressed: () async { + showAlertDialog( + context, + FFLocalizations.of(context).getVariableText( + ptText: 'Aprovar Visita', + enText: 'Approve Visit', + ), + FFLocalizations.of(context).getVariableText( + ptText: + 'Você tem certeza que deseja aprovar essa visita?', + enText: + 'Are you sure you want to approve this visit?', + ), + () async { + await answersRequest( + context, + payload['referencia'].toString(), + 'L', + 'Mensagem', + payload['idVisitante'].toString(), + ).then((value) { + if (value) { + context.pop(); + context.pop(); + } else { + context.pop(); + context.pop(); + DialogUtil.errorDefault(context); + } + }).catchError((e) { + context.pop(); + context.pop(); + DialogUtil.errorDefault(context); + }); + }, + ); + }, + ), + FlutterFlowIconButton( + icon: const Icon(Icons.close), + onPressed: () async { + showAlertDialog( + context, + FFLocalizations.of(context).getVariableText( + ptText: 'Bloquear Visita', + enText: 'Block Visit', + ), + FFLocalizations.of(context).getVariableText( + ptText: + 'Você tem certeza que deseja bloquear essa visita?', + enText: + 'Are you sure you want to block this visit?', + ), () async { + await answersRequest + .call( + context, + payload['referencia'].toString(), + 'B', + 'Mensagem', + payload['idVisitante'].toString(), + ) + .then((value) { + if (value) { + context.pop(); + context.pop(); + } else { + context.pop(); + context.pop(); + DialogUtil.errorDefault(context); + } + }).catchError((e) { + context.pop(); + context.pop(); + DialogUtil.errorDefault(context); + }); + }); + }, + ), + ], + labelsHashMap: Map.from({ + FFLocalizations.of(context).getVariableText( + enText: 'Visitor', + ptText: 'Visitante', + ): payload['nomevisita'], + FFLocalizations.of(context).getVariableText( + enText: 'Reason', + ptText: 'Motivo', + ): payload['motivo'], + FFLocalizations.of(context).getVariableText( + enText: 'Message', + ptText: 'Mensagem', + ): payload['mensagem'], + }), + imagePath: + 'https://freaccess.com.br/freaccess/getImage.php?cliID=${AppState().cliUUID}&atividade=getFoto&Documento=${payload['documento'] ?? ''}&tipo=E', + statusHashMap: [ + { + FFLocalizations.of(context).getVariableText( + enText: 'Active', + ptText: 'Ativo', + ): FlutterFlowTheme.of(context).warning, + }, + ], + ), + ), + ); + }); + + break; + case 'access': + showDialog( + context: AppState().context!, + barrierColor: Colors.transparent, + barrierDismissible: true, + builder: (BuildContext context) { + return Dialog( + backgroundColor: Colors.transparent, + child: AccessNotificationModalTemplateComponentWidget( + datetime: payload['ACE_DATAHORA'].toString(), + drive: payload['ACI_DESCRICAO'].toString(), + id: payload['USR_TIPO'].toString() == 'O' + ? payload['USR_ID'].toString() == '' + ? '0' + : payload['USR_ID'].toString() + : payload['USR_DOCUMENTO'].toString() == '' + ? '0' + : payload['USR_DOCUMENTO'].toString(), + name: payload['PES_NOME'].toString(), + type: payload['USR_TIPO'], + ), + ); + }); + break; + case 'mensagem': + showDialog( + context: AppState().context!, + barrierColor: Colors.transparent, + barrierDismissible: true, + builder: (BuildContext context) { + return Dialog( + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.3, + height: MediaQuery.of(context).size.height * 0.3, + child: MessageNotificationModalTemplateComponentWidget( + id: localId, + from: payload['remetente'].toString(), + to: payload['destinatario'].toString() == 'O' + ? 'Morador' + : 'Visitante', + message: + extra.toString().isEmpty ? 'Unknown' : extra.toString(), + ), + ), + ); + }); + + break; + default: + break; + } + + // showAlertDialog(AppState().context!, 'Test', 'Test', () async {}); +} + class NotificationService { static Future initialize() async { await AwesomeNotifications().initialize( @@ -40,7 +223,9 @@ class NotificationService { ], debug: kDebugMode); - await AwesomeNotifications().isNotificationAllowed().then((isAllowed) async { + await AwesomeNotifications() + .isNotificationAllowed() + .then((isAllowed) async { if (!AppState().isRequestOSNotification) { if (!isAllowed) { AppState().isRequestOSNotification = true; @@ -62,251 +247,7 @@ class NotificationService { final payload = receivedAction.payload ?? {}; final extra = receivedAction.body; final handleClick = payload['click_action']; - - final localId = jsonDecode(payload['local']!)['CLI_ID']; - - log('payload: $payload'); - log('extra: $extra'); - switch (handleClick) { - case 'visit_request': - showDialog( - context: AppState().context!, - barrierColor: Colors.transparent, - barrierDismissible: true, - builder: (BuildContext context) { - return Dialog( - child: SizedBox( - width: MediaQuery.of(context).size.width * 0.8, - height: MediaQuery.of(context).size.height * 0.6, - child: DetailsComponentWidget( - buttons: [ - FlutterFlowIconButton( - icon: const Icon(Icons.done), - onPressed: () async { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text( - FFLocalizations.of(context).getVariableText( - ptText: 'Aprovar Visita', - enText: 'Approve Visit', - ), - ), - content: Text( - FFLocalizations.of(context).getVariableText( - ptText: - 'Você tem certeza que deseja aprovar essa visita?', - enText: - 'Are you sure you want to approve this visit?', - ), - ), - backgroundColor: FlutterFlowTheme.of(context) - .primaryBackground, - actions: [ - FFButtonWidget( - text: FFLocalizations.of(context) - .getVariableText( - enText: 'No', - ptText: 'Não', - ), - onPressed: () { - context.pop(); - }, - options: FFButtonOptions( - width: 100, - height: 40, - color: FlutterFlowTheme.of(context) - .primaryBackground, - textStyle: TextStyle( - color: FlutterFlowTheme.of(context) - .primaryText, - ), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context) - .primaryBackground, - width: 1, - ), - borderRadius: - BorderRadius.circular(10)), - ), - FFButtonWidget( - text: FFLocalizations.of(context) - .getVariableText( - enText: 'Yes', - ptText: 'Sim', - ), - onPressed: () async { - log("payload: $payload"); - await answersRequest - .call( - context, - payload['referencia'].toString(), - 'L', - 'Mensagem', - payload['idVisitante'].toString(), - ) - .then((value) { - if (value) { - context.pop(); - context.pop(); - } else { - context.pop(); - context.pop(); - DialogUtil.errorDefault(context); - } - }).catchError((e) { - context.pop(); - context.pop(); - DialogUtil.errorDefault(context); - }); - }, - options: FFButtonOptions( - width: 100, - height: 40, - color: FlutterFlowTheme.of(context) - .primaryBackground, - textStyle: TextStyle( - color: FlutterFlowTheme.of(context) - .primaryText, - ), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context) - .primaryBackground, - width: 1, - ), - borderRadius: BorderRadius.circular(10), - ), - ), - ], - ); - }); - }, - ), - FlutterFlowIconButton( - icon: const Icon(Icons.close), - onPressed: () async { - showAlertDialog( - context, - FFLocalizations.of(context).getVariableText( - ptText: 'Bloquear Visita', - enText: 'Block Visit', - ), - FFLocalizations.of(context).getVariableText( - ptText: - 'Você tem certeza que deseja bloquear essa visita?', - enText: - 'Are you sure you want to block this visit?', - ), () async { - await answersRequest - .call( - context, - payload['referencia'].toString(), - 'B', - 'Mensagem', - payload['idVisitante'].toString(), - ) - .then((value) { - if (value) { - context.pop(); - context.pop(); - } else { - context.pop(); - context.pop(); - DialogUtil.errorDefault(context); - } - }).catchError((e) { - context.pop(); - context.pop(); - DialogUtil.errorDefault(context); - }); - }); - }, - ), - ], - labelsHashMap: Map.from({ - FFLocalizations.of(context).getVariableText( - enText: 'Visitor', - ptText: 'Visitante', - ): payload['nomevisita'], - FFLocalizations.of(context).getVariableText( - enText: 'Reason', - ptText: 'Motivo', - ): payload['motivo'], - FFLocalizations.of(context).getVariableText( - enText: 'Message', - ptText: 'Mensagem', - ): payload['mensagem'], - }), - imagePath: - 'https://freaccess.com.br/freaccess/getImage.php?cliID=${AppState().cliUUID}&atividade=getFoto&Documento=${payload['documento'] ?? ''}&tipo=E', - statusHashMap: [ - { - FFLocalizations.of(context).getVariableText( - enText: 'Active', - ptText: 'Ativo', - ): FlutterFlowTheme.of(context).warning, - }, - ], - ), - ), - ); - }); - - break; - case 'access': - showDialog( - context: AppState().context!, - barrierColor: Colors.transparent, - barrierDismissible: true, - builder: (BuildContext context) { - return Dialog( - backgroundColor: Colors.transparent, - child: AccessNotificationModalTemplateComponentWidget( - datetime: payload['ACE_DATAHORA'].toString(), - drive: payload['ACI_DESCRICAO'].toString(), - id: payload['USR_TIPO'].toString() == 'O' - ? payload['USR_ID'].toString() == '' - ? '0' - : payload['USR_ID'].toString() - : payload['USR_DOCUMENTO'].toString() == '' - ? '0' - : payload['USR_DOCUMENTO'].toString(), - name: payload['PES_NOME'].toString(), - type: payload['USR_TIPO'], - ), - ); - }); - break; - case 'mensagem': - showDialog( - context: AppState().context!, - barrierColor: Colors.transparent, - barrierDismissible: true, - builder: (BuildContext context) { - return Dialog( - child: SizedBox( - width: MediaQuery.of(context).size.width * 0.3, - height: MediaQuery.of(context).size.height * 0.3, - child: MessageNotificationModalTemplateComponentWidget( - id: localId, - from: payload['remetente'].toString(), - to: payload['destinatario'].toString() == 'O' - ? 'Morador' - : 'Visitante', - message: - extra.toString().isEmpty ? 'Unknown' : extra.toString(), - ), - ), - ); - }); - - break; - default: - break; - } - - // showAlertDialog(AppState().context!, 'Test', 'Test', () async {}); + onMessageReceived(payload, extra, handleClick); } static Future onNotificationCreatedMethod( diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart index 4e9e28fd..ac64bcb6 100644 --- a/lib/firebase_options.dart +++ b/lib/firebase_options.dart @@ -73,9 +73,10 @@ class DefaultFirebaseOptions { projectId: 'accessmoblie-da839', databaseURL: 'https://accessmoblie-da839.firebaseio.com', storageBucket: 'accessmoblie-da839.appspot.com', - androidClientId: '187064172787-7et0qu5p2qtmisvqgndn3kfi1b7u9ifl.apps.googleusercontent.com', - iosClientId: '187064172787-c5gs7fvp78om9r7dofkjn2qmpumkuvig.apps.googleusercontent.com', + androidClientId: + '187064172787-7et0qu5p2qtmisvqgndn3kfi1b7u9ifl.apps.googleusercontent.com', + iosClientId: + '187064172787-c5gs7fvp78om9r7dofkjn2qmpumkuvig.apps.googleusercontent.com', iosBundleId: 'br.com.freaccess.hub', ); - -} \ No newline at end of file +} diff --git a/lib/main.dart b/lib/main.dart index 2f51907a..5e2cc196 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,12 +3,12 @@ import 'dart:developer'; import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_web_plugins/url_strategy.dart'; -import 'package:hub/backend/notifications/firebase_messaging_service.dart'; import 'package:hub/backend/notifications/notification_service.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; @@ -28,7 +28,6 @@ Future initializeApp() async { await appState.initializePersistedState(); await Firebase.initializeApp(); - await FirebaseMessagingService().initNotifications(); await NotificationService.initialize(); setUrlStrategy(const PathUrlStrategy()); @@ -48,6 +47,15 @@ Future initializeApp() async { usePathUrlStrategy(); } +Future foregroundHandleMessage(RemoteMessage message) async { + NotificationService.show( + title: message.notification!.title!, + body: message.notification!.body!, + payload: Map.from(message.data)); +} + +Future _backgroundHandleMessage(RemoteMessage message) async {} + void main() async { await initializeApp(); runApp(const App()); @@ -79,6 +87,19 @@ class _AppState extends State { _router = createRouter(_appStateNotifier); Future.delayed(const Duration(milliseconds: 1000), () => setState(() => _appStateNotifier.stopShowingSplashImage())); + + FirebaseMessaging.onMessage.listen(foregroundHandleMessage); + FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { + onMessageReceived(message.data, message.notification!.body, + message.data['click_action']); + }); + FirebaseMessaging.onBackgroundMessage(_backgroundHandleMessage); + + FirebaseMessaging.instance.getInitialMessage().then((message) { + if (message != null) { + _backgroundHandleMessage(message); + } + }); } // diff --git a/lib/pages/home_page/home_page_widget.dart b/lib/pages/home_page/home_page_widget.dart index b7fd9894..5e2f88c5 100644 --- a/lib/pages/home_page/home_page_widget.dart +++ b/lib/pages/home_page/home_page_widget.dart @@ -120,9 +120,9 @@ class _HomePageWidgetState extends State { _model = createModel(context, () => HomePageModel()); _model.updateOnChange = true; - () async { - await FirebaseMessagingService().updateDeviceToken(); + FirebaseMessagingService().updateDeviceToken(); + () async { if (AppState().cliUUID.isEmpty) { await processLocals(); } @@ -252,4 +252,75 @@ class _HomePageWidgetState extends State { child: _localProfileComponentWidget, ); } + + Future processData() async { + try { + var response = await PhpGroup.getDadosCall.call( + devUUID: AppState().devUUID, + userUUID: AppState().userUUID, + cliUUID: AppState().cliUUID, + atividade: 'getDados', + ); + + final error = response.jsonBody['error']; + final errorMsg = response.jsonBody['error_msg']; + + if (error == false) { + AppState().whatsapp = response.jsonBody['whatsapp'] ?? false; + AppState().provisional = response.jsonBody['provisional'] ?? false; + AppState().name = response.jsonBody['visitado']['VDO_NOME']; + safeSetState(() {}); + return; + } + + DialogUtil.warningDefault(context).whenComplete(() => processLocals()); + safeSetState(() {}); + return; + } catch (e, s) { + DialogUtil.warningDefault(context).whenComplete(() => processLocals()); + } + } + + Future processLocals() async { + try { + var response = await PhpGroup.getLocalsCall.call( + devUUID: AppState().devUUID, + userUUID: AppState().userUUID, + ); + + List locals = response.jsonBody['locais'] ?? []; + + final activeLocals = + locals.where((local) => local['CLU_STATUS'] == 'A').toList(); + + if (activeLocals.isEmpty || AppState().cliUUID.isEmpty) { + await showModalSelectLocal(); + } else { + await processData(); + } + } catch (e) { + await showModalSelectLocal(); + } + } + + Future showModalSelectLocal() async { + await showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + enableDrag: false, + isDismissible: false, + context: context, + builder: (context) => Padding( + padding: MediaQuery.viewInsetsOf(context), + child: const BottomArrowLinkedLocalsComponentWidget(), + ), + ).then((_) async { + _model.updatePage(() => safeSetState(() { + _localProfileComponentWidget = LocalProfileComponentWidget( + showBottomSheet: showModalSelectLocal); + })); + + await processData(); + }); + } }