diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 288304cb..f548d112 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,7 +1,124 @@ - - - + + package="com.freaccess.hub" + + xmlns:tools="http://schemas.android.com/tools"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 0264e87d..f548d112 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,119 +1,124 @@ - - - - - - - - - - - + package="com.freaccess.hub" - + xmlns:tools="http://schemas.android.com/tools"> + + + + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + + + - + + + + + + + + + + + + - - + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/freaccess/hub/MainActivity.kt b/android/app/src/main/kotlin/com/freaccess/hub/MainActivity.kt index 10a40dac..767f00ff 100644 --- a/android/app/src/main/kotlin/com/freaccess/hub/MainActivity.kt +++ b/android/app/src/main/kotlin/com/freaccess/hub/MainActivity.kt @@ -1,5 +1,29 @@ package com.freaccess.hub +import android.os.Bundle +import android.provider.Settings import io.flutter.embedding.android.FlutterFragmentActivity +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugin.common.MethodChannel -class MainActivity: FlutterFragmentActivity() {} +class MainActivity: FlutterFragmentActivity() { + private val CHANNEL = "com.freaccess.hub/getAndroidId" + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> + if (call.method == "getAndroidId") { + val androidId = getAndroidId() + if (androidId != null) { + result.success(androidId) + } else { + result.error("UNAVAILABLE", "Android ID not available.", null) + } + } else { + result.notImplemented() + } + } + } + private fun getAndroidId(): String? { + return Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID) + } +} \ No newline at end of file diff --git a/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart b/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart index 1565e678..0c68525e 100644 --- a/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart +++ b/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart @@ -14,7 +14,8 @@ import '/backend/api_requests/api_calls.dart'; import '/flutter_flow/flutter_flow_theme.dart'; class BottomArrowLinkedLocalsComponentWidget extends StatefulWidget { - const BottomArrowLinkedLocalsComponentWidget({super.key}); + const BottomArrowLinkedLocalsComponentWidget({super.key, required this.response}); + final ApiCallResponse? response; @override State createState() => _BottomArrowLinkedLocalsComponentWidgetState(); @@ -71,16 +72,15 @@ class _BottomArrowLinkedLocalsComponentWidgetState extends State _fetchLocals() async { try { setState(() => _loading = true); - var response = await PhpGroup.getLocalsCall.call(); - final bool isError = response.jsonBody['error']; + final bool isError = widget.response?.jsonBody['error']; if (isError) { - final String errorMsg = response.jsonBody['error_msg']; + final String errorMsg = widget.response?.jsonBody['error_msg']; _handleError(context, errorMsg); - return response; + return widget.response; } - final List locals = response.jsonBody['locais'] ?? []; + final List locals = widget.response?.jsonBody['locais'] ?? []; final bool isEmpty = locals.isEmpty; final bool isUnique = locals.length == 1; @@ -99,7 +99,7 @@ class _BottomArrowLinkedLocalsComponentWidgetState extends State getData() async { cliName = (await StorageHelper().get(SQLiteStorageKey.clientName.value, Storage.SQLiteStorage)) ?? ''; cliUUID = (await StorageHelper().get(SQLiteStorageKey.clientUUID.value, Storage.SQLiteStorage)) ?? ''; - ; setStateCallback?.call(); } diff --git a/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart b/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart index 05890176..0a8bb410 100644 --- a/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart +++ b/lib/components/organism_components/local_profile_component/local_profile_component_widget.dart @@ -3,6 +3,8 @@ import 'dart:developer'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hub/shared/helpers/base_storage.dart'; +import 'package:hub/shared/helpers/storage_helper.dart'; import '/flutter_flow/custom_functions.dart' as functions; import '/flutter_flow/flutter_flow_theme.dart'; @@ -34,10 +36,15 @@ class _LocalProfileComponentWidgetState extends State LocalProfileComponentModel()); _model.setOnUpdate(onUpdate: () => setState(() {})); _model.setStateCallback = () => safeSetState(() {}); - // - // WidgetsBinding.instance - // .addPostFrameCallback((_) async => await LocalizationService.processLocals(context).then((value) => value == true ? onUpdate() : null)); - // LocalizationService.processLocals(context).then((value) => value == true ? onUpdate() : null); + + WidgetsBinding.instance.addPostFrameCallback((_) async { + bool initialized = false; + bool isDevLinked = _model.cliUUID.isNotEmpty; + if (!isDevLinked && !initialized) { + initialized = true; + await LocalizationService.processLocals(context).then((value) => value == true ? onUpdate() : null); + } + }); } @override @@ -90,7 +97,8 @@ class _LocalProfileComponentWidgetState extends State value == true ? onUpdate() : null); }, child: ClipRRect( diff --git a/lib/main.dart b/lib/main.dart index 38828b06..06cb585d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -280,7 +280,7 @@ class _AppState extends State with WidgetsBindingObserver { if (state == AppLifecycleState.detached) { await LocalizationService.processLocals(context); FirebaseMessagingService().updateDeviceToken(); - } + } } @override diff --git a/lib/pages/pets_page/pets_page_model.dart b/lib/pages/pets_page/pets_page_model.dart index fd099522..fd717e00 100644 --- a/lib/pages/pets_page/pets_page_model.dart +++ b/lib/pages/pets_page/pets_page_model.dart @@ -20,15 +20,10 @@ import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:hub/shared/utils/validator_util.dart'; class PetsPageModel extends FlutterFlowModel { - static PetsPageModel? _instance = PetsPageModel._internal(); - PetsPageModel._internal(); - factory PetsPageModel() => _instance ?? PetsPageModel._internal(); - static void resetInstance() => _instance = null; - late final String devUUID; late final String userUUID; late final String cliUUID; - late String petAmountRegister = '0'; + late final String petAmountRegister; dynamic item; late final TabController tabBarController; @@ -50,6 +45,8 @@ class PetsPageModel extends FlutterFlowModel { FFUploadedFile? uploadedTempFile; String? imgBase64; + late String defaultDropDownText = ''; + String? dropDownValue1; FormFieldController? dropDownValueController1; @@ -108,18 +105,23 @@ class PetsPageModel extends FlutterFlowModel { String? Function(BuildContext, String?)? textControllerObservationValidator; Future initAsync() async { + defaultDropDownText = FFLocalizations.of(buildContext!).getVariableText( + enText: 'Select an option', + ptText: 'Selecione uma opção', + ); + dropDownValueController1 = FormFieldController(dropDownValue1 ??= defaultDropDownText); + dropDownValueController2 = FormFieldController(dropDownValue2 ??= defaultDropDownText); + devUUID = (await StorageHelper().get(SQLiteStorageKey.devUUID.value, Storage.SQLiteStorage)) ?? ''; userUUID = (await StorageHelper().get(SQLiteStorageKey.userUUID.value, Storage.SQLiteStorage)) ?? ''; cliUUID = (await StorageHelper().get(SQLiteStorageKey.clientUUID.value, Storage.SQLiteStorage)) ?? ''; - petAmountRegister = await StorageHelper().get(SQLiteStorageKey.petAmount.value, Storage.SQLiteStorage) ?? '0'; + petAmountRegister = (await StorageHelper().get(SQLiteStorageKey.petAmount.value, Storage.SQLiteStorage)) ?? ''; safeSetState?.call(); } @override void initState(BuildContext context) { - initAsync(); - resetInstance(); tabBarController = TabController( vsync: Navigator.of(context), length: 2, @@ -143,35 +145,7 @@ class PetsPageModel extends FlutterFlowModel { textFieldFocusObservation = FocusNode(); textControllerObservation = TextEditingController(); - dropDownValueController1 = FormFieldController(dropDownValue1 ??= 'Selecione uma opção'); - - dropDownValueController2 = FormFieldController(dropDownValue2 ??= 'Selecione uma opção'); - } - - @override - void dispose() { - tabBarController.dispose(); - - textFieldFocusName?.dispose(); - textControllerName?.dispose(); - - textFieldFocusSpecies?.dispose(); - textControllerSpecies?.dispose(); - - textFieldFocusRace?.dispose(); - textControllerRace?.dispose(); - - textFieldFocusColor?.dispose(); - textControllerColor?.dispose(); - - textFieldFocusData?.dispose(); - textControllerData?.dispose(); - - textFieldFocusObservation?.dispose(); - textControllerObservation?.dispose(); - - dropDownValueController1?.dispose(); - dropDownValueController2?.dispose(); + initAsync(); } void setEditForm() { @@ -221,26 +195,65 @@ class PetsPageModel extends FlutterFlowModel { dropDownValueController2 = FormFieldController(dropDownValue2); } + @override + void dispose() { + tabBarController.dispose(); + + textFieldFocusName?.dispose(); + textControllerName?.dispose(); + + textFieldFocusSpecies?.dispose(); + textControllerSpecies?.dispose(); + + textFieldFocusRace?.dispose(); + textControllerRace?.dispose(); + + textFieldFocusColor?.dispose(); + textControllerColor?.dispose(); + + textFieldFocusData?.dispose(); + textControllerData?.dispose(); + + textFieldFocusObservation?.dispose(); + textControllerObservation?.dispose(); + + dropDownValueController1?.dispose(); + dropDownValueController2?.dispose(); + } + bool isFormValid(BuildContext context) { if (uploadedLocalFile == null || uploadedLocalFile!.bytes!.isEmpty) { return false; } - if (textControllerName!.text.isEmpty || textControllerName!.text.length > 80 || textControllerName!.text == '') { + if (textControllerName.text.isEmpty || textControllerName.text.length > 80 || textControllerName.text == '') { return false; } - if (textControllerSpecies!.text.isEmpty || textControllerSpecies!.text == '') { + if (textControllerSpecies.text.isEmpty || textControllerSpecies.text == '') { return false; } - if (textControllerRace!.text.isEmpty || textControllerRace!.text == '') { + if (textControllerRace.text.isEmpty || textControllerRace.text == '') { return false; } - if (dropDownValue1 == null || dropDownValue1!.isEmpty || dropDownValue1 == '') { + if (dropDownValueController1!.value == defaultDropDownText || + dropDownValueController1!.value == '' || + dropDownValueController1!.value == null) { return false; } - if (dropDownValue2 == null || dropDownValue2!.isEmpty || dropDownValue2 == '') { + if (dropDownValueController2!.value == defaultDropDownText || + dropDownValueController2!.value == '' || + dropDownValueController2!.value == null) { return false; } + + if (dropDownValue1 == 'Selecione uma opção' || dropDownValue1 == null || dropDownValue1 == '') { + return false; + } + + if (dropDownValue2 == 'Selecione uma opção' || dropDownValue2 == null || dropDownValue2 == '') { + return false; + } + return true; } @@ -263,7 +276,7 @@ class PetsPageModel extends FlutterFlowModel { ); if (response.jsonBody['error'] == false) { - DialogUtil.success( + await DialogUtil.success( buildContext!, FFLocalizations.of(buildContext!).getVariableText( enText: 'Pet successfully updated', @@ -284,7 +297,7 @@ class PetsPageModel extends FlutterFlowModel { ptText: 'Falha ao atualizar o pet', ); } - DialogUtil.error(buildContext!, errorMessage); + await DialogUtil.error(buildContext!, errorMessage); } } @@ -304,7 +317,7 @@ class PetsPageModel extends FlutterFlowModel { ); if (response.jsonBody['error'] == false) { - DialogUtil.success( + await DialogUtil.success( buildContext!, FFLocalizations.of(buildContext!).getVariableText( enText: 'Pet successfully registered', @@ -316,15 +329,16 @@ class PetsPageModel extends FlutterFlowModel { String errorMessage; try { errorMessage = jsonDecode(response.jsonBody['error_msg'])[0]['message'].toString(); + await DialogUtil.error(buildContext!, errorMessage); } catch (e) { if (response.jsonBody['error_msg'] == "Limite de Cadastro de Pet Atingido.") { errorMessage = FFLocalizations.of(buildContext!).getVariableText( enText: 'Pet registration limit reached', ptText: 'Limite de cadastro de pets atingido', ); - DialogUtil.error(buildContext!, errorMessage); + await DialogUtil.error(buildContext!, errorMessage); } else { - DialogUtil.errorDefault(buildContext!); + await DialogUtil.errorDefault(buildContext!); } } } @@ -364,10 +378,8 @@ class PetsPageModel extends FlutterFlowModel { // dropDownValue1 = ''; // dropDownValue2 = ''; - // dropDownValueController1 = - // FormFieldController('Selecione uma opção'); - // dropDownValueController2 = - // FormFieldController('Selecione uma opção'); + // dropDownValueController1 = FormFieldController('Selecione uma opção'); + // dropDownValueController2 = FormFieldController('Selecione uma opção'); } Widget buildPetDetails({ @@ -378,123 +390,120 @@ class PetsPageModel extends FlutterFlowModel { required String cliUUID, required String cliName, required PetsPageModel model, - bool isInteractive = true, }) { return DetailsComponentWidget( buttons: [ // EDIT ACTION - if (isInteractive) - FFButtonWidget( - text: FFLocalizations.of(context).getVariableText( - ptText: 'Editar', - enText: 'Edit', - ), - icon: const Icon(Icons.edit), - onPressed: () async { - context.pop(); - - model.isEditing = true; - model.item = item; - model.switchTab(0); - model.setEditForm(); - // model.safeSetState!(); - }, - options: FFButtonOptions( - width: 100, - height: 40, - color: FlutterFlowTheme.of(context).primaryBackground, - elevation: 0, - textStyle: TextStyle( - color: FlutterFlowTheme.of(context).primaryText, - fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15), - ), - splashColor: const Color.fromARGB(95, 0, 146, 5), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).primaryBackground, - width: 1, - ), - // borderRadius: 12, - ), + FFButtonWidget( + text: FFLocalizations.of(context).getVariableText( + ptText: 'Editar', + enText: 'Edit', ), + icon: const Icon(Icons.edit), + onPressed: () async { + context.pop(); + + model.isEditing = true; + model.item = item; + model.switchTab(0); + model.setEditForm(); + // model.safeSetState!(); + }, + options: FFButtonOptions( + width: 100, + height: 40, + color: FlutterFlowTheme.of(context).primaryBackground, + elevation: 0, + textStyle: TextStyle( + color: FlutterFlowTheme.of(context).primaryText, + fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15), + ), + splashColor: const Color.fromARGB(95, 0, 146, 5), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primaryBackground, + width: 1, + ), + // borderRadius: 12, + ), + ), // DELETE ACTION - if (isInteractive) - FFButtonWidget( - text: FFLocalizations.of(context).getVariableText( - ptText: 'Excluir', - enText: 'Delete', - ), - icon: const Icon(Icons.close), - onPressed: () async { - showAlertDialog( - context, - FFLocalizations.of(context).getVariableText( - ptText: 'Excluir Pet', - enText: 'Delete Pet', - ), - FFLocalizations.of(context).getVariableText( - ptText: 'Você tem certeza que deseja excluir esse pet?', - enText: 'Are you sure you want to delete this pet?', - ), () async { - int id = item['id']; - await PhpGroup.deletePet - .call( - petID: id, - ) - .then((value) { - // Navigator.pop(context, value); - context.pop(value); - context.pop(value); + FFButtonWidget( + text: FFLocalizations.of(context).getVariableText( + ptText: 'Excluir', + enText: 'Delete', + ), + icon: const Icon(Icons.close), + onPressed: () async { + showAlertDialog( + context, + FFLocalizations.of(context).getVariableText( + ptText: 'Excluir Pet', + enText: 'Delete Pet', + ), + FFLocalizations.of(context).getVariableText( + ptText: 'Você tem certeza que deseja excluir esse pet?', + enText: 'Are you sure you want to delete this pet?', + ), () async { + int id = item['id']; + await PhpGroup.deletePet + .call( + petID: id, + ) + .then((value) { + // Navigator.pop(context, value); + context.pop(value); + context.pop(value); - if (value == false) { - showSnackbar( - context, - FFLocalizations.of(context).getVariableText( - ptText: 'Erro ao excluir pet', - enText: 'Error deleting pet', - ), - true, - ); - } else if (value == true) { - showSnackbar( - context, - FFLocalizations.of(context).getVariableText( - enText: 'Success deleting pet', - ptText: 'Succeso ao excluir pet', - ), - false, - ); - } - }).catchError((err, stack) { - context.pop(); + if (value == false) { showSnackbar( context, FFLocalizations.of(context).getVariableText( - enText: 'Error deleting pet', ptText: 'Erro ao excluir pet', + enText: 'Error deleting pet', ), true, ); - }); + } else if (value == true) { + showSnackbar( + context, + FFLocalizations.of(context).getVariableText( + enText: 'Success deleting pet', + ptText: 'Succeso ao excluir pet', + ), + false, + ); + } + }).catchError((err, stack) { + context.pop(); + showSnackbar( + context, + FFLocalizations.of(context).getVariableText( + enText: 'Error deleting pet', + ptText: 'Erro ao excluir pet', + ), + true, + ); }); - }, - options: FFButtonOptions( - width: 100, - height: 40, - color: FlutterFlowTheme.of(context).primaryBackground, - elevation: 0, - textStyle: TextStyle( - color: FlutterFlowTheme.of(context).primaryText, - fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15), - ), - splashColor: const Color.fromARGB(131, 255, 17, 0), - borderSide: BorderSide( - color: FlutterFlowTheme.of(context).primaryBackground, - width: 1, - ), - // borderRadius: 12, + }); + }, + options: FFButtonOptions( + width: 100, + height: 40, + color: FlutterFlowTheme.of(context).primaryBackground, + elevation: 0, + textStyle: TextStyle( + color: FlutterFlowTheme.of(context).primaryText, + fontSize: LimitedFontSizeUtil.getNoResizeFont(context, 15), ), + splashColor: const Color.fromARGB(131, 255, 17, 0), + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).primaryBackground, + width: 1, + ), + // borderRadius: 12, ), + ), ], // 'MIN', 'PEQ', 'MED', 'GRA', 'GIG' labelsHashMap: Map.from({ diff --git a/lib/pages/preferences_settings_page/preferences_settings_widget.dart b/lib/pages/preferences_settings_page/preferences_settings_widget.dart index c8603a7a..26f0f719 100644 --- a/lib/pages/preferences_settings_page/preferences_settings_widget.dart +++ b/lib/pages/preferences_settings_page/preferences_settings_widget.dart @@ -6,6 +6,7 @@ import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/pages/preferences_settings_page/preferences_settings_model.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; +import 'package:material_symbols_icons/symbols.dart'; import 'package:provider/provider.dart'; @@ -104,26 +105,26 @@ class _PreferencesPageWidgetState extends State { onPressed = () => model.toggleFingerprint(context); isEnabled = model.isFingerprint; content = FFLocalizations.of(context).getVariableText( - ptText: 'Ative a autenticação por impressão digital para login seguro.', - enText: 'Enable fingerprint authentication for secure login.', + ptText: 'Autenticar com impressão digital no QRCode', + enText: 'Authenticate with fingerprint on the QRCode', ); break; case 1: - icon = Icons.person; + icon = Icons.share; onPressed = () => model.enablePerson(context); isEnabled = model.isPerson; content = FFLocalizations.of(context).getVariableText( - ptText: 'Compartilhe o código de identificação remota', - enText: 'Share the remote identification code', + ptText: 'Compartilhar o código de identificação', + enText: 'Share the identification code', ); break; case 2: - icon = Icons.info; + icon = Icons.transfer_within_a_station_outlined; onPressed = () => model.toggleIdentification(context); isEnabled = false; content = FFLocalizations.of(context).getVariableText( - ptText: 'Atualize suas informações de identificação de acesso.', - enText: 'Update your access identification information.', + ptText: 'Habilitar dispositivo para acesso', + enText: 'Enable device for access', ); break; case 3: @@ -131,8 +132,8 @@ class _PreferencesPageWidgetState extends State { onPressed = () => model.toggleNotify(context); isEnabled = model.isNotify; content = FFLocalizations.of(context).getVariableText( - ptText: 'Ative para receber sua notificação de acesso', - enText: 'Enable to receive your access notification', + ptText: 'Receber notificação de acesso', + enText: 'Receive access notification', ); break; case 4: @@ -140,8 +141,8 @@ class _PreferencesPageWidgetState extends State { onPressed = () => model.toggleAccess(context); isEnabled = model.isAccess; content = FFLocalizations.of(context).getVariableText( - ptText: 'Ative para inserir uma credencial de acesso para o QRCode', - enText: 'Enable to enter an access credential for the QRCode', + ptText: 'Registrar senha de acesso para o QRCode', + enText: 'Register access password for the QRCode', ); break; case 5: @@ -149,19 +150,19 @@ class _PreferencesPageWidgetState extends State { onPressed = () => model.togglePanic(context); isEnabled = model.isPanic; content = FFLocalizations.of(context).getVariableText( - ptText: 'Ative para inserir uma credencial de pânico para o QRCode', - enText: 'Enable to enter a panic credential for the QRCode', + ptText: 'Registrar senha de pânico para o QRCode', + enText: 'Register panic password for the QRCode', ); break; case 6: - icon = Icons.landscape; + icon = Symbols.digital_out_of_home; onPressed = () { model.localUnlink(context); }; isEnabled = false; content = FFLocalizations.of(context).getVariableText( - ptText: 'Desative para se desvincular do local selecionado', - enText: 'Enable to unlink from the selected location', + ptText: 'Desvincular do local selecionado', + enText: 'Unlink from selected location', ); break; case 7: @@ -169,8 +170,8 @@ class _PreferencesPageWidgetState extends State { onPressed = () => model.deleteAccount(context); isEnabled = false; content = FFLocalizations.of(context).getVariableText( - ptText: 'Delete sua conta e todos os dados associados permanentemente.', - enText: 'Delete your account and all associated data permanently.', + ptText: 'Deletar conta permanentemente', + enText: 'Delete account permanently', ); break; case 8: @@ -178,8 +179,8 @@ class _PreferencesPageWidgetState extends State { onPressed = () => model.logout(context); isEnabled = false; content = FFLocalizations.of(context).getVariableText( - ptText: 'Sair da conta atual e voltar para a tela de login.', - enText: 'Log out of the current account and return to the login screen.', + ptText: 'Sair da conta', + enText: 'Logout', ); break; default: @@ -187,7 +188,7 @@ class _PreferencesPageWidgetState extends State { } return SizedBox( - height: 100, + height: 66, child: GestureDetector( onTap: () { switch (index) { diff --git a/lib/shared/services/localization/localization_service.dart b/lib/shared/services/localization/localization_service.dart index 8f9c6ae4..e8c44c87 100644 --- a/lib/shared/services/localization/localization_service.dart +++ b/lib/shared/services/localization/localization_service.dart @@ -3,6 +3,8 @@ import 'dart:developer'; import 'package:flutter/material.dart'; +import 'package:http/src/response.dart'; +import 'package:hub/backend/api_requests/api_manager.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/shared/helpers/base_storage.dart'; import 'package:hub/shared/helpers/storage_helper.dart'; @@ -21,12 +23,20 @@ class LocalizationService { try { final GetLocalsCall callback = PhpGroup.getLocalsCall; var response = await callback.call(); - final bool isError = response.jsonBody['error']; + final bool? isError = response.jsonBody['error']; - if (isError) { + if (isError == true) { _handleError(context, response.jsonBody['error_msg']); return; } + if (response.jsonBody == null) { + final String errorMsg = FFLocalizations.of(context).getVariableText( + enText: 'Verify your connection', + ptText: 'Verifique sua conexão', + ); + DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, response)); + return; + } final List locals = response.jsonBody['locais'] ?? []; final bool isEmpty = locals.isEmpty; @@ -50,13 +60,21 @@ class LocalizationService { try { final GetLocalsCall callback = PhpGroup.getLocalsCall; final ApiCallResponse response = await callback.call(); - final bool isError = response.jsonBody['error']; + final bool? isError = response.jsonBody['error']; - if (isError) { + if (isError == true) { final String errorMsg = response.jsonBody['error_msg']; _handleError(context, errorMsg); return false; } + if (response.jsonBody == null) { + final String errorMsg = FFLocalizations.of(context).getVariableText( + enText: 'Verify your connection', + ptText: 'Verifique sua conexão', + ); + DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, response)); + return false; + } final List locals = response.jsonBody['locais'].toList() ?? []; _logLocalsStatus(locals); @@ -82,7 +100,7 @@ class LocalizationService { return await _handleEnabled(context, locals[0]); } else if (isUnselected) { log('() => isUnselected'); - return await selectLocal(context); + return await selectLocal(context, response); } else if (isSelected) { log('() => isSelected'); return await processData(context); @@ -95,7 +113,7 @@ class LocalizationService { if (!isUnique && isPending) log('() => not unique and pending'); if (!isUnique && isBlocked) log('() => not unique and blocked'); log('() => else'); - return await selectLocal(context); + return await selectLocal(context, response); } } catch (e, s) { log('() => stack: $s'); @@ -105,7 +123,7 @@ class LocalizationService { enText: 'Error getting locals, verify your connection', ptText: 'Erro ao obter locais, verifique sua conexão', ); - DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context)); + DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, null)); return false; } } @@ -114,11 +132,18 @@ class LocalizationService { try { final GetDadosCall callback = PhpGroup.getDadosCall; var response = await callback.call(); - final bool error = response.jsonBody['error']; + final bool? isError = response.jsonBody['error']; - if (error == true || error == 'true') { + if (isError == true || isError == 'true') { final String errorMsg = response.jsonBody['error_msg']; - DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context)); + DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, response)); + return false; + } else if (response.jsonBody == null) { + final String errorMsg = FFLocalizations.of(context).getVariableText( + enText: 'Verify your connection', + ptText: 'Verifique sua conexão', + ); + DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, response)); return false; } else { await _updateStorageUtil(response.jsonBody); @@ -131,14 +156,12 @@ class LocalizationService { enText: 'Error getting data, verify your connection', ptText: 'Erro ao obter dados, verifique sua conexão', ); - DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context)); + DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context, null)); return false; } } - static Future selectLocal(BuildContext context) async { - final String? devUUID = await DeviceUtil.getSerialNumber(); - log('() A => ${devUUID}'); + static Future selectLocal(BuildContext context, ApiCallResponse? response) async { return await showModalBottomSheet( isScrollControlled: true, backgroundColor: Colors.transparent, @@ -151,7 +174,7 @@ class LocalizationService { canPop: false, child: Padding( padding: MediaQuery.viewInsetsOf(context), - child: const BottomArrowLinkedLocalsComponentWidget(), + child: BottomArrowLinkedLocalsComponentWidget(response: response), ), ), ).then((_) async => await processData(context)); @@ -207,6 +230,7 @@ class LocalizationService { final bool isAuthenticated = userUUID.isNotEmpty && devUUID.isNotEmpty; final bool isDevLinked = !errorMsg.contains('Esse dispositivo nao pertence a esse usuario'); log('() => isLinked: $errorMsg'); + log('() => isLinked: $errorMsg'); if (!isAuthenticated) { errorMsg = FFLocalizations.of(context).getVariableText( ptText: 'Erro ao obter credenciais de autenticação', @@ -224,7 +248,7 @@ class LocalizationService { await DialogUtil.warning(context, errorMsg); return; } - await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context)); + await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, null)); } static Future _handleUnavailable(BuildContext context, List locals) async { @@ -313,3 +337,4 @@ class LocalizationService { await StorageHelper().set(SQLiteStorageKey.userName.value, jsonBody['visitado']['VDO_NOME'], Storage.SQLiteStorage); } } + diff --git a/lib/shared/utils/device_util.dart b/lib/shared/utils/device_util.dart index 8d52fcc2..844a3c16 100644 --- a/lib/shared/utils/device_util.dart +++ b/lib/shared/utils/device_util.dart @@ -2,42 +2,73 @@ import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/services.dart'; + class DeviceUtil { + static const MethodChannel _channel = MethodChannel("com.freaccess.hub/getAndroidId"); + + static Future getAndroidId() async { + try { + final String? androidId = await _channel.invokeMethod('getAndroidId'); + + return androidId; + } on PlatformException catch (e) { + print("Failed to get Android ID: '${e.message}'."); + + return null; + } + } + static Future getDevUUID() async { var deviceInfo = DeviceInfoPlugin(); + if (Platform.isIOS) { - // import 'dart:io' var iosDeviceInfo = await deviceInfo.iosInfo; - return iosDeviceInfo.identifierForVendor; // unique ID on iOS + return iosDeviceInfo.identifierForVendor; } else if (Platform.isAndroid) { - var androidDeviceInfo = await deviceInfo.androidInfo; - return androidDeviceInfo.id; // unique ID on Android + try { + final String? secureAndroidId = await getAndroidId(); + return secureAndroidId; + } catch (e) { + final build = await deviceInfo.androidInfo; + return build.id; + } } + return null; } static Future getSerialNumber() async { var deviceInfo = DeviceInfoPlugin(); + if (Platform.isIOS) { // import 'dart:io' + var iosDeviceInfo = await deviceInfo.iosInfo; + return iosDeviceInfo.identifierForVendor; // unique ID on iOS } else if (Platform.isAndroid) { var androidDeviceInfo = await deviceInfo.androidInfo; + return androidDeviceInfo.serialNumber; // unique ID on Android } + return null; } static Future getDeviceOSVersion() async { var deviceInfo = DeviceInfoPlugin(); + if (Platform.isIOS) { var iosDeviceInfo = await deviceInfo.iosInfo; + return iosDeviceInfo.systemVersion; // unique ID on iOS. e.g. 14.5 } else if (Platform.isAndroid) { var androidDeviceInfo = await deviceInfo.androidInfo; + return androidDeviceInfo.version.release; // unique ID on Android. e.g . 11 } + return null; } }