Refactor MessageWellComponentWidget, update totalPageNumber handling, implement settings preferences page and fix share

This commit is contained in:
jantunesmesias 2024-07-23 08:06:24 -03:00
parent 630376e416
commit ff43303205
27 changed files with 1793 additions and 156 deletions

View File

@ -7,6 +7,8 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<application <application
android:label="FREHub" android:label="FREHub"
tools:replace="android:label" tools:replace="android:label"
@ -14,7 +16,7 @@
android:requestLegacyExternalStorage="true"> android:requestLegacyExternalStorage="true">
<activity <activity
android:name=".MainActivity" android:name="io.flutter.embedding.android.FlutterFragmentActivity"
android:exported="true" android:exported="true"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"

View File

@ -1,6 +1,6 @@
package com.freaccess.hub package com.freaccess.hub
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity: FlutterActivity() { class MainActivity: FlutterFragmentActivity() {
} }

View File

@ -78,6 +78,8 @@
<string>Main</string> <string>Main</string>
<key>UIRequiresFullScreen</key> <key>UIRequiresFullScreen</key>
<true/> <true/>
<key>NSFaceIDUsageDescription</key>
<string>Why is my app authenticating using face id?</string>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>

View File

@ -1,9 +1,67 @@
import 'dart:ffi';
import 'package:f_r_e_hub/flutter_flow/permissions_util.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:csv/csv.dart'; import 'package:csv/csv.dart';
import 'package:local_auth/local_auth.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:synchronized/synchronized.dart'; import 'package:synchronized/synchronized.dart';
class FFAppState extends ChangeNotifier { class FFAppState extends ChangeNotifier {
// Adiciona a variável para controle de autenticação biométrica
bool _isBiometricAuthenticated = false;
bool get isBiometricAuthenticated => _isBiometricAuthenticated;
// Instância do LocalAuthentication
final LocalAuthentication auth = LocalAuthentication();
// Verifica suporte biométrico
Future<bool> checkBiometrics() async {
try {
return await auth.canCheckBiometrics;
} catch (e) {
clearBiometricAuthentication();
debugPrint('Error checking biometrics: $e');
return false;
}
}
// Solicita autenticação biométrica
Future<void> authenticateBiometric() async {
bool authenticated = false;
try {
authenticated = await auth.authenticate(
localizedReason: 'Scan your fingerprint to authenticate',
options: const AuthenticationOptions(
biometricOnly: true,
stickyAuth: true,
useErrorDialogs: true,
sensitiveTransaction: true,
)
);
if (authenticated) {
_isBiometricAuthenticated = true;
notifyListeners();
// Salvar o estado de autenticação biométrica, se necessário
}
} catch (e) {
print(e);
debugPrint('Error authenticating: $e');
clearBiometricAuthentication();
}
}
// Função para limpar o estado de autenticação biométrica
void clearBiometricAuthentication() {
_isBiometricAuthenticated = false;
notifyListeners();
// Limpar a informação salva, se necessário
}
static FFAppState _instance = FFAppState._internal(); static FFAppState _instance = FFAppState._internal();
factory FFAppState() { factory FFAppState() {
@ -69,6 +127,25 @@ class FFAppState extends ChangeNotifier {
await _safeInitAsync(() async { await _safeInitAsync(() async {
_serialNumber = await secureStorage.getString('ff_serialNumber') ?? _serialNumber; _serialNumber = await secureStorage.getString('ff_serialNumber') ?? _serialNumber;
}); });
await _safeInitAsync(() async {
_fingerprintOPT = await secureStorage.getBool('fingerprint') ?? _fingerprintOPT;
});
await _safeInitAsync(() async {
_personOPT = await secureStorage.getBool('person') ?? _personOPT;
});
await _safeInitAsync(() async {
_passOPT = await secureStorage.getBool('pass') ?? _passOPT;
});
await _safeInitAsync(() async {
_notifyOPT = await secureStorage.getBool('notify') ?? _notifyOPT;
});
await _safeInitAsync(() async {
_accessPass = await secureStorage.getString('accessPass') ?? _accessPass;
});
await _safeInitAsync(() async {
_panicPass = await secureStorage.getString('panicPass') ?? _panicPass;
});
} }
void update(VoidCallback callback) { void update(VoidCallback callback) {
@ -78,6 +155,70 @@ class FFAppState extends ChangeNotifier {
late FlutterSecureStorage secureStorage; late FlutterSecureStorage secureStorage;
String _accessPass = '';
String get accessPass => _accessPass;
set accessPass(String value) {
_accessPass = value;
secureStorage.setString('accessPass', value);
}
void deleteAccessPass() {
secureStorage.delete(key: 'accessPass');
}
String _panicPass = '';
String get panicPass => _panicPass;
set panicPass(String value) {
_panicPass = value;
secureStorage.setString
('panicPass', value);
}
void deletePanicPass() {
secureStorage.delete(key: 'panicPass');
}
bool _notifyOPT = false;
bool get notify => _notifyOPT;
set notify(bool value) {
_notifyOPT = value;
secureStorage.setBool('notify', value);
}
bool _passOPT = false;
bool get pass => _passOPT;
set pass(bool value) {
_passOPT =
value;
secureStorage.setBool('pass', value);
}
void deletePass() {
secureStorage.delete(key: 'pass');
}
bool _personOPT = false;
bool get person => _personOPT;
set person(bool value) {
_personOPT = value;
secureStorage.setBool('person', value);
}
void deletePerson() {
secureStorage.delete(key: 'person');
}
bool _fingerprintOPT = false;
bool get fingerprint => _fingerprintOPT;
set fingerprint(bool value) {
_fingerprintOPT = value;
secureStorage.setBool('fingerprint', value);
}
void deleteFingerprint() {
secureStorage.delete(key: 'fingerprint');
}
String _serialNumber = ''; String _serialNumber = '';
String get serialNumber => _serialNumber; String get serialNumber => _serialNumber;
set serialNumber(String value) { set serialNumber(String value) {
@ -270,6 +411,10 @@ class FFAppState extends ChangeNotifier {
void deleteName() { void deleteName() {
secureStorage.delete(key: 'ff_name'); secureStorage.delete(key: 'ff_name');
} }
void deleteAll() {
secureStorage.deleteAll();
}
} }
void _safeInit(Function() initializeField) { void _safeInit(Function() initializeField) {

View File

@ -41,8 +41,125 @@ class PhpGroup {
static GetLiberationsCopyCall getLiberationsCopyCall = static GetLiberationsCopyCall getLiberationsCopyCall =
GetLiberationsCopyCall(); GetLiberationsCopyCall();
static GetMessagesCall getMessagesCall = GetMessagesCall(); static GetMessagesCall getMessagesCall = GetMessagesCall();
static ChangeNotifica changeNotifica = ChangeNotifica();
static RespondeVinculo resopndeVinculo = RespondeVinculo();
static ChangePass changePass = ChangePass();
} }
class ChangePass {
Future<ApiCallResponse> call({
String? devUUID = '',
String? userUUID = '',
String? cliID = '',
String? atividade = '',
String? newSenha = '',
}) async {
final baseUrl = PhpGroup.getBaseUrl();
return ApiManager.instance.makeApiCall(
callName: 'changePass',
apiUrl: '$baseUrl/processRequest.php',
callType: ApiCallType.POST,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
params: {
'devUUID': devUUID,
'userUUID': userUUID,
'cliID': cliID,
'atividade': atividade,
'newSenha': newSenha,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
}
bool? error(dynamic response) => castToType<bool>(getJsonField(
response,
r'''$.error''',
));
}
class RespondeVinculo {
Future<ApiCallResponse> call({
String? devUUID = '',
String? userUUID = '',
String? cliID = '',
String? tarefa = '',
}) async {
final baseUrl = PhpGroup.getBaseUrl();
return ApiManager.instance.makeApiCall(
callName: 'respondeVinculo',
apiUrl: '$baseUrl/processRequest.php',
callType: ApiCallType.POST,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
params: {
'devUUID': devUUID,
'userUUID': userUUID,
'cliID': cliID,
'tarefa': tarefa,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
}
}
class ChangeNotifica {
Future<ApiCallResponse> call({
String? devUUID = '',
String? userUUID = '',
String? cliID = '',
String? atividade = '',
String? notifica = '',
}) async {
final baseUrl = PhpGroup.getBaseUrl();
return ApiManager.instance.makeApiCall(
callName: 'changeNotifica',
apiUrl: '$baseUrl/processRequest.php',
callType: ApiCallType.POST,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
params: {
'devUUID': devUUID,
'userUUID': userUUID,
'cliID': cliID,
'atividade': atividade,
'notifica': notifica,
},
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
returnBody: true,
encodeBodyUtf8: false,
decodeUtf8: false,
cache: false,
isStreamingApi: false,
alwaysAllowBody: false,
);
}
bool? error(dynamic response) => castToType<bool>(getJsonField(
response,
r'''$.error''',
));
}
class UpdToken { class UpdToken {
Future<ApiCallResponse> call({ Future<ApiCallResponse> call({
String? token = '', String? token = '',

View File

@ -0,0 +1,31 @@
import '/flutter_flow/flutter_flow_util.dart';
import '/flutter_flow/form_field_controller.dart';
import 'opt_modal_widget.dart' show OptModalWidget;
import 'package:flutter/material.dart';
class OptModalModel extends FlutterFlowModel<OptModalWidget> {
/// State fields for stateful widgets in this component.
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode;
TextEditingController? textController;
String? Function(BuildContext, String?)? textControllerValidator;
// State field(s) for Checkbox widget.
bool? checkboxValue1;
// State field(s) for Checkbox widget.
bool? checkboxValue2;
// State field(s) for CheckboxGroup widget.
FormFieldController<List<String>>? checkboxGroupValueController;
List<String>? get checkboxGroupValues => checkboxGroupValueController?.value;
set checkboxGroupValues(List<String>? v) =>
checkboxGroupValueController?.value = v;
@override
void initState(BuildContext context) {}
@override
void dispose() {
textFieldFocusNode?.dispose();
textController?.dispose();
}
}

View File

@ -0,0 +1,330 @@
import 'package:f_r_e_hub/components/molecular_components/opt_modal/opt_modal_model.dart';
import 'package:f_r_e_hub/flutter_flow/flutter_flow_theme.dart';
import 'package:f_r_e_hub/flutter_flow/flutter_flow_util.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class OptModalWidget extends StatefulWidget {
final String defaultPersonType;
final String defaultAccessType;
const OptModalWidget({
Key? key,
this.defaultPersonType = '.*',
this.defaultAccessType = '.*',
}) : super(key: key);
@override
_OptModalWidgetState createState() => _OptModalWidgetState();
}
class _OptModalWidgetState extends State<OptModalWidget> {
late OptModalModel _model;
late Map<String, dynamic> selected;
final List<Map<String, String>> personTypeOptions = [
{'title': 'zok7lu4w', 'value': 'E'},
{'title': 'oonqk812', 'value': 'O'},
];
final List<Map<String, String>> accessTypeOptions = [
{'title': '580z80ct', 'value': '0'},
{'title': '1nbwqtzs', 'value': '1'},
];
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => OptModalModel());
_model.textController ??= TextEditingController();
_model.textFieldFocusNode ??= FocusNode();
selected = {
'personType': widget.defaultPersonType == '.*'
? ['E', 'O']
: [widget.defaultPersonType],
'accessType': widget.defaultAccessType == '.*'
? ['0', '1']
: [widget.defaultAccessType],
'search': '.*',
};
}
void _applyFilter() {
Map<String, String> filterResult = {
'personType': '',
'accessType': '',
'search': _model.textController.text == ''
? '.*'
: _model.textController.text.toLowerCase(),
};
if (selected['personType']!.isEmpty) {
filterResult['personType'] = '.*';
} else if (selected['personType']!.length > 1) {
filterResult['personType'] = '.*';
} else {
filterResult['personType'] = selected['personType']!.first;
}
if (selected['accessType']!.isEmpty) {
filterResult['accessType'] = '.*';
} else if (selected['accessType']!.length > 1) {
filterResult['accessType'] = '.*';
} else {
filterResult['accessType'] = selected['accessType']!.first;
}
Navigator.pop(context, filterResult);
}
Widget _buildCheckboxListTile(String key, List<Map<String, String>> options) {
return Column(
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(0.0, 10.0, 0.0, 0.0),
child: Text(
FFLocalizations.of(context).getText('l7tw8b92'),
textAlign: TextAlign
.left, // Adiciona esta linha para alinhar o texto à esquerda
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).bodyMediumFamily),
color: FlutterFlowTheme.of(context).primaryText,
),
),
),
],
),
ListView.builder(
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (context, index) {
final option = options[index];
return CheckboxListTile(
title: Text(
FFLocalizations.of(context).getText(option['title']!),
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).bodyMediumFamily),
color: FlutterFlowTheme.of(context).primaryText,
),
),
dense: true,
value: selected[key]!.contains(option['value']),
onChanged: (bool? value) {
setState(() {
if (value == true) {
if (!selected[key]!.contains(option['value'])) {
selected[key]!.add(option['value']);
}
} else {
selected[key]!.remove(option['value']);
}
});
},
activeColor: FlutterFlowTheme.of(context).primary,
checkColor: FlutterFlowTheme.of(context).info,
checkboxShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
enableFeedback: true,
side: BorderSide(
width: 10,
color: FlutterFlowTheme.of(context).secondaryText,
),
controlAffinity:
ListTileControlAffinity.leading, // Adiciona esta linha
);
},
),
],
);
}
void _updateSelection(String? value, String key) {
setState(() {
if (value == '.') {
selected[key] = [];
} else if (value != null) {
if (selected[key]!.contains(value)) {
selected[key]!.remove(value);
} else {
selected[key]!.add(value);
}
}
});
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Align(
alignment: const AlignmentDirectional(1.0, -1.0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 50.0, 50.0, 0.0),
child: Container(
width: 300.0,
height: 450.0,
decoration: BoxDecoration(
color: FlutterFlowTheme.of(context).primaryBackground,
borderRadius: BorderRadius.circular(24.0),
),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
10.0, 10.0, 0.0, 10.0),
child: Text(
FFLocalizations.of(context)
.getText('yfj9pd6k'), // Filtros
style: FlutterFlowTheme.of(context)
.headlineMedium
.override(
fontFamily: FlutterFlowTheme.of(context)
.headlineMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 16.0,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.headlineMediumFamily),
),
),
),
],
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
8.0, 0.0, 8.0, 0.0),
child: TextFormField(
controller: _model.textController,
focusNode: _model.textFieldFocusNode,
autofocus: false,
obscureText: false,
decoration: InputDecoration(
isDense: true,
labelText: FFLocalizations.of(context).getText(
'0enrtljz' /* Pesquise aqui..... */,
),
labelStyle: FlutterFlowTheme.of(context)
.labelMedium
.override(
fontFamily: FlutterFlowTheme.of(context)
.labelMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.labelMediumFamily),
),
hintStyle: FlutterFlowTheme.of(context)
.labelMedium
.override(
fontFamily: FlutterFlowTheme.of(context)
.labelMediumFamily,
color: FlutterFlowTheme.of(context).primaryText,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context)
.labelMediumFamily),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).alternate,
width: 1,
),
borderRadius: BorderRadius.circular(8.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).primary,
width: 1,
),
borderRadius: BorderRadius.circular(8.0),
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error,
width: 1,
),
borderRadius: BorderRadius.circular(8.0),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error,
width: 1,
),
borderRadius: BorderRadius.circular(8.0),
),
filled: true,
fillColor: FlutterFlowTheme.of(context).alternate,
suffixIcon: const Icon(
Icons.search_outlined,
),
),
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily:
FlutterFlowTheme.of(context).bodyMediumFamily,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).bodyMediumFamily),
),
validator:
_model.textControllerValidator.asValidator(context),
),
),
SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildCheckboxListTile(
'personType', personTypeOptions),
_buildCheckboxListTile(
'accessType', accessTypeOptions),
],
),
),
),
ElevatedButton(
onPressed: _applyFilter,
child:
Text(FFLocalizations.of(context).getText('88kshkph')),
style: ElevatedButton.styleFrom(
foregroundColor: FlutterFlowTheme.of(context).info,
backgroundColor: FlutterFlowTheme.of(context).primary,
),
),
],
),
),
),
),
),
);
}
}

View File

@ -101,9 +101,9 @@ class MenuComponentModel extends FlutterFlowModel<MenuComponentWidget> {
); );
} }
Future acessHistoryOptAction(BuildContext context) async { Future preferencesSettings(BuildContext context) async {
context.pushNamed( context.pushNamed(
'acessHistoryPage', 'preferencesSettings',
extra: <String, dynamic>{ extra: <String, dynamic>{
kTransitionInfoKey: const TransitionInfo( kTransitionInfoKey: const TransitionInfo(
hasTransition: true, hasTransition: true,

View File

@ -62,8 +62,8 @@ class _MenuComponentWidgetState extends State<MenuComponentWidget> {
await _model.peopleOnThePropertyAction(context); await _model.peopleOnThePropertyAction(context);
setState(() {}); setState(() {});
}, },
acessHistoryOptAction: () async { preferencesSettings: () async {
await _model.acessHistoryOptAction(context); await _model.preferencesSettings(context);
setState(() {}); setState(() {});
}, },
liberationHistoryOptAction: () async { liberationHistoryOptAction: () async {
@ -98,8 +98,8 @@ class _MenuComponentWidgetState extends State<MenuComponentWidget> {
await _model.peopleOnThePropertyAction(context); await _model.peopleOnThePropertyAction(context);
setState(() {}); setState(() {});
}, },
accessHistoryOptAction: () async { preferencesSettings: () async {
await _model.acessHistoryOptAction(context); await _model.preferencesSettings(context);
setState(() {}); setState(() {});
}, },
liberationHistoryOptAction: () async { liberationHistoryOptAction: () async {

View File

@ -16,7 +16,7 @@ class MenuListViewComponentWidget extends StatefulWidget {
required this.registerVisitorOptAction, required this.registerVisitorOptAction,
required this.scheduleVisitOptAction, required this.scheduleVisitOptAction,
required this.peopleOnThePropertyOptAction, required this.peopleOnThePropertyOptAction,
required this.acessHistoryOptAction, required this.preferencesSettings,
required this.liberationHistoryOptAction, required this.liberationHistoryOptAction,
required this.accessQRCodeOptAction, required this.accessQRCodeOptAction,
}); });
@ -25,7 +25,7 @@ class MenuListViewComponentWidget extends StatefulWidget {
final Future Function()? registerVisitorOptAction; final Future Function()? registerVisitorOptAction;
final Future Function()? scheduleVisitOptAction; final Future Function()? scheduleVisitOptAction;
final Future Function()? peopleOnThePropertyOptAction; final Future Function()? peopleOnThePropertyOptAction;
final Future Function()? acessHistoryOptAction; final Future Function()? preferencesSettings;
final Future Function()? liberationHistoryOptAction; final Future Function()? liberationHistoryOptAction;
final Future Function()? accessQRCodeOptAction; final Future Function()? accessQRCodeOptAction;
@ -876,7 +876,7 @@ Propriedade */
hoverColor: Colors.transparent, hoverColor: Colors.transparent,
highlightColor: Colors.transparent, highlightColor: Colors.transparent,
onTap: () async { onTap: () async {
await widget.acessHistoryOptAction?.call(); await widget.preferencesSettings?.call();
}, },
child: Container( child: Container(
width: 100.0, width: 100.0,
@ -931,7 +931,7 @@ Propriedade */
alignment: alignment:
const AlignmentDirectional(0.0, 0.0), const AlignmentDirectional(0.0, 0.0),
child: Icon( child: Icon(
Icons.history_sharp, Icons.settings,
color: FlutterFlowTheme.of(context) color: FlutterFlowTheme.of(context)
.accent1, .accent1,
size: 24.0, size: 24.0,
@ -953,8 +953,8 @@ Propriedade */
alignment: const AlignmentDirectional(0.0, 0.0), alignment: const AlignmentDirectional(0.0, 0.0),
child: Text( child: Text(
FFLocalizations.of(context).getVariableText( FFLocalizations.of(context).getVariableText(
enText: 'Consult\nHistories', enText: 'Preferences\nSystem',
ptText: 'Consultar\nHistóricos', ptText: 'Preferências\ndo Sistema',
), ),
style: FlutterFlowTheme.of(context) style: FlutterFlowTheme.of(context)
.titleLarge .titleLarge
@ -979,6 +979,7 @@ Propriedade */
), ),
), ),
), ),
].divide(const SizedBox(width: 15.0)), ].divide(const SizedBox(width: 15.0)),
), ),
), ),

View File

@ -18,7 +18,7 @@ class MenuStaggeredViewComponentWidget extends StatefulWidget {
required this.registerVisitorOptAction, required this.registerVisitorOptAction,
required this.scheduleVisitOptAction, required this.scheduleVisitOptAction,
required this.peopleOnThePropertyOptAction, required this.peopleOnThePropertyOptAction,
required this.accessHistoryOptAction, required this.preferencesSettings,
required this.liberationHistoryOptAction, required this.liberationHistoryOptAction,
required this.accessQRCodeOptAction, required this.accessQRCodeOptAction,
}); });
@ -27,7 +27,7 @@ class MenuStaggeredViewComponentWidget extends StatefulWidget {
final Future Function()? registerVisitorOptAction; final Future Function()? registerVisitorOptAction;
final Future Function()? scheduleVisitOptAction; final Future Function()? scheduleVisitOptAction;
final Future Function()? peopleOnThePropertyOptAction; final Future Function()? peopleOnThePropertyOptAction;
final Future Function()? accessHistoryOptAction; final Future Function()? preferencesSettings;
final Future Function()? liberationHistoryOptAction; final Future Function()? liberationHistoryOptAction;
final Future Function()? accessQRCodeOptAction; final Future Function()? accessQRCodeOptAction;
@ -85,7 +85,7 @@ class _MenuStaggeredViewComponentWidgetState
), ),
crossAxisSpacing: 10.0, crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0, mainAxisSpacing: 10.0,
itemCount: 7, itemCount: 8,
padding: const EdgeInsets.fromLTRB( padding: const EdgeInsets.fromLTRB(
0, 0,
10.0, 10.0,
@ -900,6 +900,126 @@ Propriedade */
), ),
), ),
), ),
() => InkWell(
splashColor: Colors.transparent,
focusColor: Colors.transparent,
hoverColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () async {
await widget.preferencesSettings?.call();
},
child: Container(
width: 100.0,
height: 100.0,
decoration: BoxDecoration(
color:
FlutterFlowTheme.of(context).primaryBackground,
boxShadow: [
BoxShadow(
blurRadius: 4.0,
color:
FlutterFlowTheme.of(context).customColor5,
offset: const Offset(
0.0,
2.0,
),
)
],
borderRadius: BorderRadius.circular(24.0),
shape: BoxShape.rectangle,
border: Border.all(
color: FlutterFlowTheme.of(context).alternate,
width: 0.5,
),
),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Align(
alignment:
const AlignmentDirectional(0.0, 0.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Align(
alignment: const AlignmentDirectional(
-1.0, 0.0),
child: Padding(
padding: const EdgeInsetsDirectional
.fromSTEB(8.0, 0.0, 0.0, 0.0),
child: Container(
width: 30.0,
height: 30.0,
decoration: BoxDecoration(
color:
FlutterFlowTheme.of(context)
.primaryBackground,
shape: BoxShape.circle,
),
alignment:
const AlignmentDirectional(
0.0, 0.0),
child: Icon(
Icons.history_sharp,
color:
FlutterFlowTheme.of(context)
.accent1,
size: 24.0,
),
),
),
),
),
],
),
),
Align(
alignment:
const AlignmentDirectional(0.0, 0.0),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
alignment: const AlignmentDirectional(
0.0, 0.0),
child: Text(
FFLocalizations.of(context)
.getVariableText(
enText: 'Preferences\nSettings',
ptText: 'Preferências\ndo Sistema',
),
style: FlutterFlowTheme.of(context)
.titleLarge
.override(
fontFamily: 'Nunito',
color:
FlutterFlowTheme.of(context)
.primaryText,
fontSize: 14.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts:
GoogleFonts.asMap()
.containsKey('Nunito'),
),
),
),
],
),
),
].divide(const SizedBox(height: 0.0)),
),
),
),
),
][index](); ][index]();
}, },
), ),

View File

@ -1,13 +1,22 @@
import 'dart:async';
import 'dart:collection';
import 'dart:developer'; import 'dart:developer';
import 'package:f_r_e_hub/app_state.dart'; import 'package:f_r_e_hub/app_state.dart';
import 'package:f_r_e_hub/backend/api_requests/api_calls.dart'; import 'package:f_r_e_hub/backend/api_requests/api_calls.dart';
import 'package:f_r_e_hub/flutter_flow/flutter_flow_theme.dart'; import 'package:f_r_e_hub/flutter_flow/flutter_flow_theme.dart';
import 'package:f_r_e_hub/flutter_flow/internationalization.dart'; import 'package:f_r_e_hub/flutter_flow/flutter_flow_util.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
final dropdown = BehaviorSubject<LinkedHashMap<String, String>>.seeded(
LinkedHashMap.from({
'All': 'A',
}),
);
class MessageWellComponentWidget extends StatefulWidget { class MessageWellComponentWidget extends StatefulWidget {
const MessageWellComponentWidget({super.key}); const MessageWellComponentWidget({super.key});
@ -19,29 +28,29 @@ class MessageWellComponentWidget extends StatefulWidget {
class _MessageWellComponentWidgetState class _MessageWellComponentWidgetState
extends State<MessageWellComponentWidget> { extends State<MessageWellComponentWidget> {
late ScrollController _listViewController; StreamSubscription? _dropdownSubscription;
late VoidCallback _scrollListener;
final dropdownValueNotifier = ValueNotifier<String>('All');
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_listViewController = ScrollController(); WidgetsBinding.instance?.addPostFrameCallback((_) {
_scrollListener = MessageWellNotifier()._scrollListener; context.read<MessageWellNotifier>().fetchMessages();
_listViewController.addListener(_scrollListener); });
_dropdownSubscription = dropdown.stream.listen((_) {
context.read<MessageWellNotifier>().fetchMessages();
});
} }
@override @override
void dispose() { void dispose() {
_listViewController.dispose(); _dropdownSubscription?.cancel();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final state = context.watch<MessageWellNotifier>(); final messages = context.read<MessageWellNotifier>().getMessages();
final messages = state.getMessages();
final theme = FlutterFlowTheme.of(context);
return Align( return Align(
alignment: Alignment.center, alignment: Alignment.center,
child: Padding( child: Padding(
@ -50,21 +59,17 @@ class _MessageWellComponentWidgetState
height: MediaQuery.of(context).size.height * 0.8, height: MediaQuery.of(context).size.height * 0.8,
child: Column( child: Column(
children: [ children: [
_buildHandleMessageWell(context, theme), _buildHandleMessageWell(context, FlutterFlowTheme.of(context)),
_buildMenuMessageWell(context, theme, dropdownValueNotifier), _buildMenuMessageWell(context, FlutterFlowTheme.of(context)),
Expanded( Expanded(
child: NotificationListener<ScrollNotification>( child: ListView.builder(
onNotification: _buildScrollMessageListManager, itemCount: messages.length,
child: ListView.builder( shrinkWrap: true,
controller: _listViewController, physics: const AlwaysScrollableScrollPhysics(),
itemCount: messages.length, itemBuilder: (context, index) {
shrinkWrap: true, var message = messages[index];
physics: const AlwaysScrollableScrollPhysics(), return _buildMessageItem(context, message, index);
itemBuilder: (context, index) { },
var message = messages[index];
return _buildMessageItem(context, message, index);
},
),
), ),
), ),
], ],
@ -74,44 +79,61 @@ class _MessageWellComponentWidgetState
); );
} }
bool _buildScrollMessageListManager(ScrollNotification notification) {
final notifier = context.read<MessageWellNotifier>();
if (notification is ScrollUpdateNotification) {
log('Scrolling ...');
if (_listViewController.offset <= 0 && notification.scrollDelta! < 0) {
log('Scrolling up ...');
setState(() {});
} else {
log('Scrolling down ...');
if (_listViewController.position.extentAfter == 0) {
log('Reached end of list. Incrementing pageNumber...');
notifier.incrementPageNumber();
}
setState(() {});
}
}
return true;
}
Widget _buildMenuMessageWell(BuildContext context, FlutterFlowTheme theme,
ValueNotifier<String> dropdownValueNotifier) {
final locations = FFLocalizations.of(context);
final all = locations.getVariableText(enText: 'All', ptText: 'All');
final personal =
locations.getVariableText(enText: 'Personal', ptText: 'Pessoal');
final global = locations.getVariableText(enText: 'Global', ptText: 'Global');
Widget _buildMenuMessageWell(BuildContext context, FlutterFlowTheme theme) {
final dropdownItems = LinkedHashMap.from({
'All': 'A',
'Personal': 'O',
'Global': 'C',
});
return SizedBox( return SizedBox(
key: UniqueKey(), key: UniqueKey(),
width: 200, width: 200,
height: 40, height: 40,
child: ValueListenableBuilder<String>( child: StreamBuilder<String>(
valueListenable: dropdownValueNotifier, stream: dropdown.stream.map((event) => event.keys.first),
builder: (context, value, child) { builder: (context, snapshot) {
final value = snapshot.data;
return DropdownButtonFormField<String>( return DropdownButtonFormField<String>(
value: value, value: value,
decoration: InputDecoration( decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(horizontal: 10.0), isDense: true,
contentPadding: const EdgeInsets.symmetric(horizontal: 10.0),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: theme.error,
width: 2,
),
borderRadius: BorderRadius.circular(10),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: theme.primary,
width: 2,
),
borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: theme.primary,
width: 2,
),
borderRadius: BorderRadius.circular(10),
),
disabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: theme.primary,
width: 2,
),
borderRadius: BorderRadius.circular(10),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: theme.error,
width: 2,
),
borderRadius: BorderRadius.circular(10),
),
border: OutlineInputBorder( border: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: theme.primary, color: theme.primary,
@ -123,20 +145,16 @@ class _MessageWellComponentWidgetState
fillColor: theme.primary, fillColor: theme.primary,
), ),
onChanged: (String? newValue) { onChanged: (String? newValue) {
if (newValue != null) { safeSetState(() => dropdown.value = LinkedHashMap.from({newValue!: dropdownItems[newValue].toString()}));
dropdownValueNotifier.value = newValue;
}
}, },
items: [ items: dropdownItems.entries
DropdownMenuItem<String>(value: all, child: Text(all)), .map((entry) => DropdownMenuItem<String>(
DropdownMenuItem<String>(value: personal, child: Text(personal)), value: entry.key,
DropdownMenuItem<String>(value: global, child: Text(global)), child: Text(entry.key),
], ))
style: theme.labelMedium.override( .toList(),
fontFamily: theme.labelMediumFamily, style: theme.bodyMedium.copyWith(
color: theme.primaryText, color: theme.primaryText,
useGoogleFonts:
GoogleFonts.asMap().containsKey(theme.labelMediumFamily),
), ),
); );
}, },
@ -144,21 +162,22 @@ class _MessageWellComponentWidgetState
); );
} }
Text _buildHandleMessageWell( Text _buildHandleMessageWell(BuildContext context, FlutterFlowTheme theme) {
BuildContext context, FlutterFlowTheme theme) {
return Text( return Text(
FFLocalizations.of(context).getText('8fworxmb'), FFLocalizations.of(context).getVariableText(
style: theme.bodyMedium.override( ptText: 'Mural de Mensagens',
enText: 'Message Wall',
),
style: theme.bodyMedium.copyWith(
fontFamily: 'Nunito Sans', fontFamily: 'Nunito Sans',
letterSpacing: 0.0, letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey('Nunito Sans'),
), ),
); );
} }
Widget _buildMessageItem( Widget _buildMessageItem(
BuildContext context, dynamic message, int index) { BuildContext context, dynamic message, int index) {
final theme = Theme.of(context); final theme = FlutterFlowTheme.of(context);
String formatMessageOrigin(String messageOrigin) { String formatMessageOrigin(String messageOrigin) {
final words = messageOrigin.split(' '); final words = messageOrigin.split(' ');
final formattedWords = words.map((word) { final formattedWords = words.map((word) {
@ -168,17 +187,15 @@ class _MessageWellComponentWidgetState
}); });
return formattedWords.join(' '); return formattedWords.join(' ');
} }
return GestureDetector( return GestureDetector(
onTap: () => onTap: () => {},
log('Message tapped ...\nmessage[$index]: $message'),
child: Padding( child: Padding(
padding: const EdgeInsets.fromLTRB(20, 5, 20, 5), padding: const EdgeInsets.fromLTRB(20, 5, 20, 5),
child: Container( child: Container(
width: MediaQuery.of(context).size.width * 0.9, width: MediaQuery.of(context).size.width * 0.9,
height: 127.0, height: 127.0,
decoration: const BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)), borderRadius: BorderRadius.circular(10),
), ),
child: Row( child: Row(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
@ -201,9 +218,9 @@ class _MessageWellComponentWidgetState
Center( Center(
child: Text( child: Text(
'~ ${formatMessageOrigin(message['MSG_ORIGEM_DESC'].toString())}', '~ ${formatMessageOrigin(message['MSG_ORIGEM_DESC'].toString())}',
style: theme.textTheme.headlineMedium!.copyWith( style: theme.bodyMedium.copyWith(
fontFamily: 'Nunito Sans', fontFamily: 'Nunito Sans',
color: FlutterFlowTheme.of(context).primary, color: theme.primary,
fontSize: 14.0, fontSize: 14.0,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -215,9 +232,9 @@ class _MessageWellComponentWidgetState
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: Text( child: Text(
formatMessageOrigin(message['MSG_TEXTO'].toString()), formatMessageOrigin(message['MSG_TEXTO'].toString()),
style: theme.textTheme.bodyMedium!.copyWith( style: theme.bodyMedium.copyWith(
fontFamily: 'Nunito Sans', fontFamily: 'Nunito Sans',
color: FlutterFlowTheme.of(context).primaryText, color: theme.bodyMedium.color,
fontSize: 14.0, fontSize: 14.0,
), ),
softWrap: true, softWrap: true,
@ -234,26 +251,25 @@ class _MessageWellComponentWidgetState
), ),
); );
} }
} }
class MessageWellState { class MessageWellState {
final List<dynamic> messages; final List<dynamic> messages;
int pageNumber; int pageNumber;
final bool allowScrollInSingleChildScrollView; final bool allowScrollInSingleChildScrollView;
final ScrollController listViewController;
MessageWellState({ MessageWellState({
required this.messages, required this.messages,
this.pageNumber = 1, this.pageNumber = 1,
required this.allowScrollInSingleChildScrollView, required this.allowScrollInSingleChildScrollView,
required this.listViewController,
}); });
MessageWellState copyWith({ MessageWellState copyWith({
List<dynamic>? messages, List<dynamic>? messages,
int? pageNumber, int? pageNumber,
bool? allowScrollInSingleChildScrollView, bool? allowScrollInSingleChildScrollView,
ScrollController? listViewController,
}) { }) {
return MessageWellState( return MessageWellState(
messages: messages ?? this.messages, messages: messages ?? this.messages,
@ -261,7 +277,6 @@ class MessageWellState {
allowScrollInSingleChildScrollView: allowScrollInSingleChildScrollView:
allowScrollInSingleChildScrollView ?? allowScrollInSingleChildScrollView ??
this.allowScrollInSingleChildScrollView, this.allowScrollInSingleChildScrollView,
listViewController: listViewController ?? this.listViewController,
); );
} }
} }
@ -274,17 +289,15 @@ class MessageWellNotifier extends StateNotifier<MessageWellState> {
_totalPageNumber = value; _totalPageNumber = value;
} }
MessageWellNotifier() MessageWellNotifier()
: super(MessageWellState( : super(MessageWellState(
messages: [], messages: [],
allowScrollInSingleChildScrollView: true, allowScrollInSingleChildScrollView: true,
listViewController: ScrollController())) { )) {
state.listViewController.addListener(_scrollListener);
fetchMessages(); fetchMessages();
} }
void fetchMessages() async { void fetchMessages() async {
if (state.pageNumber <= totalPageNumber) { if (state.pageNumber <= totalPageNumber) {
var apiCall = GetMessagesCall(); var apiCall = GetMessagesCall();
var response = await apiCall.call( var response = await apiCall.call(
@ -292,28 +305,20 @@ class MessageWellNotifier extends StateNotifier<MessageWellState> {
userUUID: FFAppState().userUUID.toString(), userUUID: FFAppState().userUUID.toString(),
cliID: FFAppState().cliUUID.toString(), cliID: FFAppState().cliUUID.toString(),
atividade: 'getMensagens', atividade: 'getMensagens',
pageSize: '10', pageSize: '100',
pageNumber: state.pageNumber.toString(), pageNumber: state.pageNumber.toString(),
tipoDestino: 'A', tipoDestino: dropdown.value.values.first,
); );
if (response.statusCode == 200) { if (response.statusCode == 200) {
var messagesData = response.jsonBody['mensagens']; var messagesData = response.jsonBody['mensagens'];
log('inputs: ${FFAppState().devUUID}, ${FFAppState().userUUID}, ${FFAppState().cliUUID}');
log('response: ${response.jsonBody}');
log('response[mensagens]: $messagesData');
log('response[mensagens][0][MSG_TEXTO]: ${messagesData[0]['MSG_TEXTO']}');
var newMessages = [...state.messages, ...messagesData]; var newMessages = [...state.messages, ...messagesData];
var rExp = RegExp(r'\d+')
.allMatches(newMessages.toString())
.map((e) => e.group(0))
.toList();
log('rExp: $rExp');
log('newMessages: $newMessages');
state = state.copyWith(messages: newMessages); state = state.copyWith(messages: newMessages);
log('total_pages :> ${response.jsonBody['total_pages']}'); // var rExp = RegExp(r'\d+')
// .allMatches(newMessages.toString())
// .map((e) => e.group(0))
// .toList();
// Provider.of<MessageCounter>(context, listen: false).setCounter(int.parse(response.jsonBody['total_pages'])); // Provider.of<MessageCounter>(context, listen: false).setCounter(int.parse(response.jsonBody['total_pages']));
totalPageNumber = int.parse(response.jsonBody['total_pages']); // totalPageNumber = int.parse(response.jsonBody['total_pages']);
log('totalPageNumber: $totalPageNumber');
} else { } else {
log('Error fetching messages: ${response.statusCode}'); log('Error fetching messages: ${response.statusCode}');
} }
@ -325,29 +330,9 @@ class MessageWellNotifier extends StateNotifier<MessageWellState> {
List<dynamic> getMessages() { List<dynamic> getMessages() {
return state.messages; return state.messages;
} }
void _scrollListener() {
if (!state.allowScrollInSingleChildScrollView) {
if (state.pageNumber <= totalPageNumber) {
state = state.copyWith(pageNumber: state.pageNumber + 1);
log('state.pageNumber: ${state.pageNumber}');
fetchMessages();
}
}
}
@override
void dispose() {
state.listViewController.removeListener(_scrollListener);
super.dispose();
}
void incrementPageNumber() { void incrementPageNumber() {
log('state.pageNumber: ${state.pageNumber}');
log('total_pages :>: $totalPageNumber');
if (state.pageNumber <= totalPageNumber) { if (state.pageNumber <= totalPageNumber) {
state = state.copyWith(pageNumber: state.pageNumber + 1); state = state.copyWith(pageNumber: state.pageNumber + 1);
} }
} }
} }

View File

@ -0,0 +1,45 @@
import '/flutter_flow/flutter_flow_util.dart';
import 'change_pass_widget.dart'
show PassKeyTemplateWidget;
import 'package:flutter/material.dart';
class PassKeyTemplateComponentModel
extends FlutterFlowModel<PassKeyTemplateWidget> {
/// State fields for stateful widgets in this component.
final formKey = GlobalKey<FormState>();
// State field(s) for keyTextField widget.
FocusNode? keyTextFieldFocusNode1;
FocusNode? keyTextFieldFocusNode2;
TextEditingController? keyTextFieldTextController1;
TextEditingController? keyTextFieldTextController2;
late bool keyTextFieldVisibility1;
late bool keyTextFieldVisibility2;
String? Function(BuildContext, String?)? keyTextFieldTextControllerValidator1;
String? Function(BuildContext, String?)? keyTextFieldTextControllerValidator2;
String? _keyTextFieldTextControllerValidator(
BuildContext context, String? val) {
if (val == null || val.isEmpty) {
return FFLocalizations.of(context).getText(
'f128ajey' /* Field is required */,
);
}
return null;
}
@override
void initState(BuildContext context) {
keyTextFieldVisibility1 = false;
keyTextFieldVisibility2 = false;
keyTextFieldTextControllerValidator1 = _keyTextFieldTextControllerValidator;
keyTextFieldTextControllerValidator2 = _keyTextFieldTextControllerValidator;
}
@override
void dispose() {
keyTextFieldFocusNode1?.dispose();
keyTextFieldFocusNode2?.dispose();
keyTextFieldTextController1?.dispose();
keyTextFieldTextController2?.dispose();
}
}

View File

@ -0,0 +1,458 @@
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/flutter_flow/flutter_flow_widgets.dart';
import 'package:easy_debounce/easy_debounce.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'change_pass_model.dart';
export 'change_pass_model.dart';
class PassKeyTemplateWidget extends StatefulWidget {
const PassKeyTemplateWidget({
super.key,
required this.toggleActionStatus,
});
final Future Function(String key)? toggleActionStatus;
@override
State<PassKeyTemplateWidget> createState() =>
_PassKeyTemplateWidgetState();
}
class _PassKeyTemplateWidgetState
extends State<PassKeyTemplateWidget> {
late PassKeyTemplateComponentModel _model;
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => PassKeyTemplateComponentModel());
_model.keyTextFieldTextController1 ??= TextEditingController();
_model.keyTextFieldFocusNode1 ??= FocusNode();
_model.keyTextFieldFocusNode1!.addListener(() => setState(() {}));
}
@override
void dispose() {
_model.maybeDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Align(
alignment: const AlignmentDirectional(0.0, 1.0),
child: Container(
width: double.infinity,
height: 400.0,
constraints: const BoxConstraints(
maxWidth: 570.0,
),
decoration: BoxDecoration(
color: FlutterFlowTheme.of(context).primaryBackground,
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(0.0),
bottomRight: Radius.circular(0.0),
topLeft: Radius.circular(15.0),
topRight: Radius.circular(15.0),
),
),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// This row exists for when the "app bar" is hidden on desktop, having a way back for the user can work well.
if (responsiveVisibility(
context: context,
phone: false,
tablet: false,
))
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16.0, 0.0, 16.0, 8.0),
child: InkWell(
splashColor: Colors.transparent,
focusColor: Colors.transparent,
hoverColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () async {
context.safePop();
},
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
const Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0.0, 12.0, 0.0, 12.0),
child: Icon(
Icons.arrow_back_rounded,
color: Color(0xFF15161E),
size: 24.0,
),
),
Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(12.0, 0.0, 0.0, 0.0),
child: Text(
'',
style:
FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: 'Plus Jakarta Sans',
color: const Color(0xFF15161E),
fontSize: 14.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts: GoogleFonts.asMap()
.containsKey('Plus Jakarta Sans'),
),
),
),
],
),
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16.0, 0.0, 0.0, 0.0),
child: Text(
FFLocalizations.of(context).getVariableText(
enText: FFAppState().accessPass != '' ? 'CHANGE PASSWORD' : 'INSERT PASSWORD',
ptText: FFAppState().accessPass != '' ? 'ALTERAR SENHA' : 'ADICIONAR SENHA',
),
style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: 'Outfit',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 24.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts: GoogleFonts.asMap().containsKey('Outfit'),
),
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16.0, 4.0, 16.0, 4.0),
child: Text(
FFLocalizations.of(context).getVariableText(
enText: 'Enter your password to continue',
ptText: 'Digite sua senha para continuar'
),
style: FlutterFlowTheme.of(context).labelMedium.override(
fontFamily: 'Plus Jakarta Sans',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 14.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts:
GoogleFonts.asMap().containsKey('Plus Jakarta Sans'),
),
),
),
Form(
key: _model.formKey,
autovalidateMode: AutovalidateMode.always,
child: Column(
children: [
if (FFAppState().accessPass.isNotEmpty)
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16.0, 12.0, 16.0, 0.0),
child: SizedBox(
width: double.infinity,
child: TextFormField(
controller: _model.keyTextFieldTextController1,
focusNode: _model.keyTextFieldFocusNode1,
onChanged: (_) => EasyDebounce.debounce(
'_model.keyTextFieldTextController',
const Duration(milliseconds: 2000),
() => setState(() {}),
),
autofillHints: const [AutofillHints.password],
textCapitalization: TextCapitalization.none,
textInputAction: TextInputAction.done,
obscureText: !_model.keyTextFieldVisibility1,
decoration: InputDecoration(
isDense: true,
labelText: FFLocalizations.of(context).getVariableText(
ptText: 'Senha Antiga',
enText: 'Old Password',
),
labelStyle:
FlutterFlowTheme.of(context).labelMedium.override(
fontFamily: 'Plus Jakarta Sans',
color: FlutterFlowTheme.of(context).primary,
fontSize: 14.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts: GoogleFonts.asMap()
.containsKey('Plus Jakarta Sans'),
),
hintText: FFLocalizations.of(context).getVariableText(
ptText: 'Digite a sua senha antiga.....',
enText: 'Enter your old password.....',
),
hintStyle:
FlutterFlowTheme.of(context).labelMedium.override(
fontFamily: 'Plus Jakarta Sans',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 14.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts: GoogleFonts.asMap()
.containsKey('Plus Jakarta Sans'),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).accent1,
width: 2.0,
),
borderRadius: BorderRadius.circular(12.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).accent3,
width: 2.0,
),
borderRadius: BorderRadius.circular(12.0),
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error,
width: 2.0,
),
borderRadius: BorderRadius.circular(12.0),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error,
width: 2.0,
),
borderRadius: BorderRadius.circular(12.0),
),
filled: true,
fillColor: FlutterFlowTheme.of(context).primaryBackground,
contentPadding: const EdgeInsetsDirectional.fromSTEB(
24.0, 24.0, 20.0, 24.0),
suffixIcon: InkWell(
onTap: () => setState(
() => _model.keyTextFieldVisibility1 =
!_model.keyTextFieldVisibility1,
),
focusNode: FocusNode(skipTraversal: true),
child: Icon(
_model.keyTextFieldVisibility1
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
color: FlutterFlowTheme.of(context).accent1,
size: 22.0,
),
),
),
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: 'Plus Jakarta Sans',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 14.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts: GoogleFonts.asMap()
.containsKey('Plus Jakarta Sans'),
),
maxLength: 4,
maxLengthEnforcement: MaxLengthEnforcement.none,
buildCounter: (context,
{required currentLength,
required isFocused,
maxLength}) =>
null,
keyboardType: TextInputType.number,
cursorColor: FlutterFlowTheme.of(context).primary,
validator: _model.keyTextFieldTextControllerValidator1
.asValidator(context),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp('[0-9]'))
],
),
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16.0, 12.0, 16.0, 0.0),
child: SizedBox(
width: double.infinity,
child: TextFormField(
controller: _model.keyTextFieldTextController2,
focusNode: _model.keyTextFieldFocusNode2,
onChanged: (_) => EasyDebounce.debounce(
'_model.keyTextFieldTextController',
const Duration(milliseconds: 2000),
() => setState(() {}),
),
autofillHints: const [AutofillHints.password],
textCapitalization: TextCapitalization.none,
textInputAction: TextInputAction.done,
obscureText: !_model.keyTextFieldVisibility2,
decoration: InputDecoration(
isDense: true,
labelText: FFLocalizations.of(context).getVariableText(
ptText: FFAppState().accessPass != '' ? 'Nova Senha' : 'Senha',
enText: FFAppState().accessPass != '' ? 'New Password' : 'Password',
),
labelStyle:
FlutterFlowTheme.of(context).labelMedium.override(
fontFamily: 'Plus Jakarta Sans',
color: FlutterFlowTheme.of(context).primary,
fontSize: 14.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts: GoogleFonts.asMap()
.containsKey('Plus Jakarta Sans'),
),
hintText: FFLocalizations.of(context).getVariableText(
enText: FFAppState().accessPass != null ? 'Enter your new password.....' : 'Enter your password.....',
ptText: FFAppState().accessPass != null ? 'Digite a sua nova senha.....' : 'Digite a sua senha.....',
),
hintStyle:
FlutterFlowTheme.of(context).labelMedium.override(
fontFamily: 'Plus Jakarta Sans',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 14.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts: GoogleFonts.asMap()
.containsKey('Plus Jakarta Sans'),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).accent1,
width: 2.0,
),
borderRadius: BorderRadius.circular(12.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).accent3,
width: 2.0,
),
borderRadius: BorderRadius.circular(12.0),
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error,
width: 2.0,
),
borderRadius: BorderRadius.circular(12.0),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: FlutterFlowTheme.of(context).error,
width: 2.0,
),
borderRadius: BorderRadius.circular(12.0),
),
filled: true,
fillColor: FlutterFlowTheme.of(context).primaryBackground,
contentPadding: const EdgeInsetsDirectional.fromSTEB(
24.0, 24.0, 20.0, 24.0),
suffixIcon: InkWell(
onTap: () => setState(
() => _model.keyTextFieldVisibility1 =
!_model.keyTextFieldVisibility1,
),
focusNode: FocusNode(skipTraversal: true),
child: Icon(
_model.keyTextFieldVisibility1
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
color: FlutterFlowTheme.of(context).accent1,
size: 22.0,
),
),
),
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: 'Plus Jakarta Sans',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 14.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts: GoogleFonts.asMap()
.containsKey('Plus Jakarta Sans'),
),
maxLength: 4,
maxLengthEnforcement: MaxLengthEnforcement.none,
buildCounter: (context,
{required currentLength,
required isFocused,
maxLength}) =>
null,
keyboardType: TextInputType.number,
cursorColor: FlutterFlowTheme.of(context).primary,
validator: _model.keyTextFieldTextControllerValidator2
.asValidator(context),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp('[0-9]'))
],
),
),
),
],
),
),
Align(
alignment: const AlignmentDirectional(0.0, 0.0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 24.0, 0.0, 0.0),
child: FFButtonWidget(
onPressed: () async {
if (_model.formKey.currentState == null ||
!_model.formKey.currentState!.validate()) {
return;
}
await widget.toggleActionStatus?.call(
_model.keyTextFieldTextController1.text.isEmpty ? _model.keyTextFieldTextController2.text : _model.keyTextFieldTextController1.text,
);
Navigator.pop(context);
},
text: FFLocalizations.of(context).getVariableText(
ptText: FFAppState().accessPass != '' ? 'Alterar' : 'Adicionar',
enText: FFAppState().accessPass != '' ? 'Change' : 'Add',
),
options: FFButtonOptions(
width: 270.0,
height: 50.0,
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0),
color: const Color(0xFF1AAB5F),
textStyle: FlutterFlowTheme.of(context).titleSmall.override(
fontFamily: 'Plus Jakarta Sans',
color: Colors.white,
fontSize: 16.0,
letterSpacing: 0.0,
fontWeight: FontWeight.w500,
useGoogleFonts: GoogleFonts.asMap()
.containsKey('Plus Jakarta Sans'),
),
elevation: 3.0,
borderSide: const BorderSide(
color: Colors.transparent,
width: 1.0,
),
),
showLoadingIndicator: false,
),
),
),
],
),
),
);
}
}

View File

@ -9,6 +9,7 @@ import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/flutter_flow_util.dart';
import '/actions/actions.dart' as action_blocks; import '/actions/actions.dart' as action_blocks;
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:share_plus/share_plus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@ -862,6 +863,11 @@ class _ViewVisitDetailWidgetState extends State<ViewVisitDetailWidget> {
), ),
onPressed: () { onPressed: () {
log('IconButton pressed ...'); log('IconButton pressed ...');
// Implement share functionality here
Share.share(
'Visita agendada para ${widget.visitStartDate} com término previsto para ${widget.visitEndDate}. Motivo: ${widget.visitReasonStr}. Nível de acesso: ${widget.visitLevelStr}. Observações: ${widget.visitObsStr}.',
);
}, },
), ),
], ],

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:f_r_e_hub/pages/fast_pass_page/fast_pass_page_widget.dart'; import 'package:f_r_e_hub/pages/fast_pass_page/fast_pass_page_widget.dart';
import 'package:f_r_e_hub/pages/message_history_page/message_history_page_widget.dart'; import 'package:f_r_e_hub/pages/message_history_page/message_history_page_widget.dart';
import 'package:f_r_e_hub/pages/preferences_settings_page/preferences_settings_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -78,7 +79,10 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter(
path: '/visitHistoryPage', path: '/visitHistoryPage',
builder: (context, params) => const VisitHistoryPageWidget(), builder: (context, params) => const VisitHistoryPageWidget(),
), ),
FFRoute(name: 'messageHistoryPage', path: '/messageHistoryPage', builder: (context, params) => const MessageHistoryPageWidget()), FFRoute(
name: 'messageHistoryPage',
path: '/messageHistoryPage',
builder: (context, params) => const MessageHistoryPageWidget()),
FFRoute( FFRoute(
name: 'registerVisitorPage', name: 'registerVisitorPage',
path: '/registerVisitorPage', path: '/registerVisitorPage',
@ -138,6 +142,9 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter(
path: '/fastPassPage', path: '/fastPassPage',
builder: (context, params) => /*const*/ FastPassPageWidget(), builder: (context, params) => /*const*/ FastPassPageWidget(),
), ),
FFRoute(name: 'preferencesSettings', path: '/preferencesSettings', builder: (context, params) => const PreferencesPageWidget(
key: Key('preferencesSettings'),
)),
FFRoute( FFRoute(
name: 'peopleOnThePropertyPage', name: 'peopleOnThePropertyPage',
path: '/peopleOnThePropertyPage', path: '/peopleOnThePropertyPage',

View File

@ -0,0 +1,18 @@
import 'package:flutter/foundation.dart';
import 'package:permission_handler/permission_handler.dart';
const kPermissionStateToBool = {
PermissionStatus.granted: true,
PermissionStatus.limited: true,
PermissionStatus.denied: false,
PermissionStatus.restricted: false,
PermissionStatus.permanentlyDenied: false,
};
Future<bool> getPermissionStatus(Permission setting) async {
final status = await setting.status;
return kPermissionStateToBool[status]!;
}
Future<void> requestPermission(Permission setting) async =>
await setting.request();

View File

@ -1,10 +1,3 @@
// import 'package:f_r_e_hub/backend/api_requests/api_calls.dart';
// import 'package:f_r_e_hub/backend/push_notification/pushNotificationService.dart';
// import 'package:f_r_e_hub/components/templates_components/visit_request_template_component/visit_request_template_component_widget.dart';
// import 'package:firebase_messaging/firebase_messaging.dart';
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';

View File

@ -75,6 +75,7 @@ PreferredSizeWidget appBarLiberationHistoryPage(BuildContext context) {
return AppBar( return AppBar(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
@ -103,6 +104,7 @@ PreferredSizeWidget appBarLiberationHistoryPage(BuildContext context) {
), ),
actions: const [], actions: const [],
centerTitle: true, centerTitle: true,
elevation: 0.0,
); );
} }

View File

@ -51,6 +51,7 @@ class _PeopleOnThePropertyPageWidgetState
appBar: AppBar( appBar: AppBar(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,
@ -106,7 +107,6 @@ class _PeopleOnThePropertyPageWidgetState
); );
} }
final columnGetPessoasLocalResponse = snapshot.data!; final columnGetPessoasLocalResponse = snapshot.data!;
return Builder( return Builder(
builder: (context) { builder: (context) {
final getPoepleProperty = PhpGroup.getPessoasLocalCall final getPoepleProperty = PhpGroup.getPessoasLocalCall

View File

@ -0,0 +1,115 @@
import 'package:f_r_e_hub/backend/api_requests/api_calls.dart';
import 'package:f_r_e_hub/components/templates_components/change_passs_qr_code_pass_key_template_component/change_pass_widget.dart';
import 'package:f_r_e_hub/flutter_flow/flutter_flow_theme.dart';
import 'package:f_r_e_hub/flutter_flow/flutter_flow_util.dart';
import 'package:flutter/material.dart';
import 'package:local_auth/local_auth.dart';
class PreferencesPageModel with ChangeNotifier {
final unfocusNode = FocusNode();
final LocalAuthentication auth = LocalAuthentication();
Future<void> toggleFingerprint() async {
FFAppState().checkBiometrics().then((value) => FFAppState().authenticateBiometric().then( (value) => FFAppState().fingerprint = !FFAppState().fingerprint).whenComplete(() => notifyListeners()));
}
void enablePerson(BuildContext context) {
notifyListeners();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(FFAppState().userDevUUID, style: TextStyle(color: FlutterFlowTheme.of(context).info) ),
backgroundColor: FlutterFlowTheme.of(context).primary,
duration: const Duration(seconds: 1),
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
),
);
}
void toggleNotify() {
FFAppState().notify = !FFAppState().notify;
PhpGroup.changeNotifica.call(
userUUID: FFAppState().userUUID,
devUUID: FFAppState().devUUID,
cliID: FFAppState().cliUUID,
atividade: 'updVisitado',
notifica: FFAppState().notify ? 'S' : 'N',
);
notifyListeners();
}
void localLogout(){
PhpGroup.resopndeVinculo.call(
userUUID: FFAppState().userUUID,
devUUID: FFAppState().devUUID,
cliID: FFAppState().cliUUID,
tarefa: 'I',
);
notifyListeners();
}
void deleteAccount(BuildContext context) {
FFAppState().deleteAll();
FFAppState().isLogged = false;
context.goNamed(
'welcomePage',
extra: <String, dynamic>{
kTransitionInfoKey: const TransitionInfo(
hasTransition: true,
transitionType: PageTransitionType.scale,
alignment: Alignment.bottomCenter,
),
},
);
}
Future<void> togglePass(BuildContext context) async {
FFAppState().pass = true;
notifyListeners();
await showModalBottomSheet(
isScrollControlled: true,
backgroundColor: Colors.transparent,
useSafeArea: true,
context: context,
builder: (context) {
return Padding(
padding:
MediaQuery.viewInsetsOf(context),
child:
PassKeyTemplateWidget(
toggleActionStatus: (key) async {
FFAppState().accessPass = key;
notifyListeners();
debugPrint('key: $key');
// PhpGroup.changePass.call(
// userUUID: FFAppState().userUUID,
// devUUID: FFAppState().devUUID,
// cliID: FFAppState().cliUUID,
// atividade: 'updVisitado',
// newSenha: FFAppState().accessPass,
// );
},
),
);
},
);
FFAppState().pass = false;
notifyListeners();
}
@override
void dispose() {
unfocusNode.dispose();
super.dispose();
}
}

View File

@ -0,0 +1,140 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import '/flutter_flow/flutter_flow_icon_button.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import 'preferences_settings_model.dart';
class PreferencesPageWidget extends StatelessWidget {
const PreferencesPageWidget({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<PreferencesPageModel>(
create: (_) => PreferencesPageModel(),
child: Consumer<PreferencesPageModel>(
builder: (context, model, child) => GestureDetector(
onTap: () => model.unfocusNode.canRequestFocus
? FocusScope.of(context).requestFocus(model.unfocusNode)
: FocusScope.of(context).unfocus(),
child: Scaffold(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
appBar: AppBar(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false,
forceMaterialTransparency: true,
leading: FlutterFlowIconButton(
borderColor: Colors.transparent,
borderRadius: 30.0,
borderWidth: 1.0,
buttonSize: 60.0,
icon: Icon(
Icons.keyboard_arrow_left,
color: FlutterFlowTheme.of(context).primaryText,
size: 30.0,
),
onPressed: () async {
context.pop();
},
),
title: Text(
FFLocalizations.of(context).getVariableText(
enText: 'Preferences',
ptText: 'Preferências',
),
style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: 'Nunito',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 17.0,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey('Nunito'),
),
),
centerTitle: true,
elevation: 0.0,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Container(),
Expanded(
flex: 2,
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 12.0,
mainAxisSpacing: 12.0,
childAspectRatio: 1.0,
mainAxisExtent: 100.0,
),
itemCount: 6, // Assuming 4 items for simplicity
padding: const EdgeInsets.symmetric(horizontal: 20.0),
physics: const AlwaysScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return _buildIconButton(context, index, model);
},
),
),
],
),
),
),
),
);
}
Widget _buildIconButton(BuildContext context, int index, PreferencesPageModel model) {
IconData icon;
Function() onPressed =() => {};
bool isEnabled;
switch (index) {
case 0:
icon = Icons.fingerprint;
onPressed = model.toggleFingerprint; // Desabilita se fingerprint for false
isEnabled = FFAppState().fingerprint;
break;
case 1:
icon = Icons.person;
onPressed = () => model.enablePerson(context);
isEnabled = FFAppState().person;
break;
case 2:
icon = Icons.notifications;
onPressed = model.toggleNotify;
isEnabled = FFAppState().notify;
break;
case 3:
icon = Icons.lock_clock_sharp;
// onLongPress = model.togglePass(context, model);
isEnabled = FFAppState().pass;
break;
case 4:
icon = Icons.landscape;
onPressed = model.localLogout;
isEnabled = false;
break;
case 5:
icon = Icons.delete;
onPressed = () => model.deleteAccount(context);
isEnabled = false;
break;
default:
throw Exception('Invalid index: $index');
}
return FlutterFlowIconButton(
icon: Icon(icon, color: isEnabled ? FlutterFlowTheme.of(context).primaryBackground : FlutterFlowTheme.of(context).primary, size: 40.0),
onPressed: index != 3 ? onPressed : () {model.togglePass(context);},
borderRadius: 20.0,
borderWidth: 1.0,
buttonSize: 40.0,
fillColor: isEnabled ? FlutterFlowTheme.of(context).primary : FlutterFlowTheme.of(context).alternate,
disabledColor: FlutterFlowTheme.of(context).alternate,
disabledIconColor: FlutterFlowTheme.of(context).primary,
);
}
}

View File

@ -66,6 +66,7 @@ class _RegisterVisitorPageWidgetState extends State<RegisterVisitorPageWidget> {
appBar: AppBar( appBar: AppBar(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,

View File

@ -165,6 +165,8 @@ PreferredSizeWidget appBarScheduleCompleteVisit(BuildContext context) {
return AppBar( return AppBar(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true,
elevation: 0.0,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,

View File

@ -61,6 +61,7 @@ class _ScheduleProvisionalVisitPageWidgetState
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
appBar: AppBar( appBar: AppBar(
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
forceMaterialTransparency: true,
leading: FlutterFlowIconButton( leading: FlutterFlowIconButton(
borderColor: Colors.transparent, borderColor: Colors.transparent,
borderRadius: 30.0, borderRadius: 30.0,

View File

@ -821,6 +821,46 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "4.0.0"
local_auth:
dependency: "direct main"
description:
name: local_auth
sha256: "280421b416b32de31405b0a25c3bd42dfcef2538dfbb20c03019e02a5ed55ed0"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
local_auth_android:
dependency: transitive
description:
name: local_auth_android
sha256: "33fcebe9c3cf1bb0033bc85caed354c1e75ff7f7670918a571bd3152a2b65bf4"
url: "https://pub.dev"
source: hosted
version: "1.0.42"
local_auth_darwin:
dependency: transitive
description:
name: local_auth_darwin
sha256: e424ebf90d5233452be146d4a7da4bcd7a70278b67791592f3fde1bda8eef9e2
url: "https://pub.dev"
source: hosted
version: "1.3.1"
local_auth_platform_interface:
dependency: transitive
description:
name: local_auth_platform_interface
sha256: "1b842ff177a7068442eae093b64abe3592f816afd2a533c0ebcdbe40f9d2075a"
url: "https://pub.dev"
source: hosted
version: "1.0.10"
local_auth_windows:
dependency: transitive
description:
name: local_auth_windows
sha256: "505ba3367ca781efb1c50d3132e44a2446bccc4163427bc203b9b4d8994d97ea"
url: "https://pub.dev"
source: hosted
version: "1.0.10"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@ -973,6 +1013,62 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.2" version: "4.2.2"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
url: "https://pub.dev"
source: hosted
version: "11.3.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: b29a799ca03be9f999aa6c39f7de5209482d638e6f857f6b93b0875c618b7e54
url: "https://pub.dev"
source: hosted
version: "12.0.7"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0
url: "https://pub.dev"
source: hosted
version: "9.4.5"
permission_handler_html:
dependency: transitive
description:
name: permission_handler_html
sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d"
url: "https://pub.dev"
source: hosted
version: "0.1.1"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20"
url: "https://pub.dev"
source: hosted
version: "4.2.1"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
url: "https://pub.dev"
source: hosted
version: "0.2.1"
persistent_bottom_nav_bar:
dependency: "direct main"
description:
name: persistent_bottom_nav_bar
sha256: "6aa9b97ced1abd92c90cedd1997d34ea0b35c3ded762ac6063baccc299b0c4c5"
url: "https://pub.dev"
source: hosted
version: "6.2.1"
petitparser: petitparser:
dependency: transitive dependency: transitive
description: description:
@ -1053,6 +1149,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.27.7" version: "0.27.7"
share_plus:
dependency: "direct main"
description:
name: share_plus
sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544
url: "https://pub.dev"
source: hosted
version: "9.0.0"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -47,6 +47,7 @@ dependencies:
flutter_animate: 4.5.0 flutter_animate: 4.5.0
flutter_cache_manager: 3.3.2 flutter_cache_manager: 3.3.2
flutter_plugin_android_lifecycle: 2.0.20 flutter_plugin_android_lifecycle: 2.0.20
share_plus: ^9.0.0
flutter_secure_storage: 9.2.2 flutter_secure_storage: 9.2.2
flutter_secure_storage_linux: 1.2.1 flutter_secure_storage_linux: 1.2.1
flutter_secure_storage_macos: 3.1.2 flutter_secure_storage_macos: 3.1.2
@ -64,8 +65,10 @@ dependencies:
image_picker: 1.1.2 image_picker: 1.1.2
image_picker_android: 0.8.12+3 image_picker_android: 0.8.12+3
image_picker_for_web: 3.0.4 image_picker_for_web: 3.0.4
persistent_bottom_nav_bar: ^6.2.1
image_picker_ios: 0.8.12 image_picker_ios: 0.8.12
image_picker_platform_interface: 2.10.0 image_picker_platform_interface: 2.10.0
local_auth: ^2.2.0
intl: ^0.19.0 intl: ^0.19.0
json_path: 0.7.2 json_path: 0.7.2
mime_type: 1.0.0 mime_type: 1.0.0
@ -103,6 +106,7 @@ dependencies:
flutter_bloc: ^8.1.6 flutter_bloc: ^8.1.6
flutter_riverpod: ^2.5.1 flutter_riverpod: ^2.5.1
qr_flutter: ^4.1.0 qr_flutter: ^4.1.0
permission_handler: ^11.3.1
dependency_overrides: dependency_overrides:
http: 1.2.1 http: 1.2.1