// ignore_for_file: use_build_context_synchronously import 'dart:async'; import 'dart:developer'; import 'package:barcode_widget/barcode_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hub/components/templates_components/qr_code_pass_key_template_component/qr_code_pass_key_template_component_widget.dart'; import 'package:hub/features/storage/index.dart'; import 'package:hub/flutter_flow/custom_functions.dart'; import 'package:hub/flutter_flow/flutter_flow_animations.dart'; import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/flutter_flow_widgets.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; import 'package:hub/pages/qr_code_page/qr_code_page_model.dart'; import 'package:hub/shared/utils/biometric_util.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:percent_indicator/circular_percent_indicator.dart'; import 'package:qr_flutter/qr_flutter.dart'; class QrCodePageWidget extends StatefulWidget { const QrCodePageWidget({super.key}); @override State createState() => _QrCodePageWidgetState(); } class _QrCodePageWidgetState extends State with TickerProviderStateMixin { late QrCodePageModel _model; final scaffoldKey = GlobalKey(); final animationsMap = {}; @override void initState() { super.initState(); _model = createModel(context, () => QrCodePageModel()); _model.safeSetState = () => safeSetState(() {}); SchedulerBinding.instance.addPostFrameCallback((_) async { if (animationsMap['barcodeOnActionTriggerAnimation'] != null) { animationsMap['barcodeOnActionTriggerAnimation']!.controller.fling(); } }); animationsMap.addAll({ 'barcodeOnActionTriggerAnimation': AnimationInfo( trigger: AnimationTrigger.onActionTrigger, applyInitialState: true, effectsBuilder: () => [ VisibilityEffect(duration: 1.ms), BlurEffect( curve: Curves.linear, delay: 0.0.ms, duration: 600.0.ms, begin: const Offset(0.0, 0.0), end: const Offset(10.0, 10.0), ), ], ), }); setupAnimations( animationsMap.values.where((anim) => anim.trigger == AnimationTrigger.onActionTrigger || !anim.applyInitialState), this, ); } @override void dispose() { // Removendo o ouvinte antes de chamar super.dispose para evitar vazamentos de memória if (animationsMap['barcodeOnActionTriggerAnimation'] != null) { animationsMap['barcodeOnActionTriggerAnimation']! .controller .removeStatusListener((status) {}); } super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( key: scaffoldKey, backgroundColor: FlutterFlowTheme.of(context).primaryBackground, appBar: buildAppBar(context), body: buildBody(context), ); } Widget buildBody(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; double screenHeight = MediaQuery.of(context).size.height; double smallerDimension = screenWidth < screenHeight ? screenWidth : screenHeight; double dimension = smallerDimension * 0.75; double totalTimeInSeconds = 100.0; LimitedFontSizeUtil.getCalculateFontSize(context, 18, 18, 16); double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context); return SafeArea( // top: true, child: Center( child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ if (_model.isAccess == true && _model.key != null) Padding( padding: const EdgeInsets.fromLTRB(0, 0, 0, 20), child: Text( FFLocalizations.of(context).getVariableText( ptText: 'Use esse QR Code para acesso', enText: 'Use this QR Code for access', ), textAlign: TextAlign.center, style: FlutterFlowTheme.of(context).headlineMedium.override( fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, color: FlutterFlowTheme.of(context).primaryText, fontSize: 16.0, fontWeight: FontWeight.bold, letterSpacing: 0.0, useGoogleFonts: GoogleFonts.asMap().containsKey( FlutterFlowTheme.of(context) .headlineMediumFamily), ), ), ), Stack( children: [ if (_model.isAccess == true && _model.key != null) Align( alignment: const AlignmentDirectional(0.0, 0.0), child: InkWell( onTap: () async { safeSetState(() async { _resetAnimationAndToggleAccess(); }); _model.isFingerprint ? await _showBiometricsAuth(context) : await _showQrCodeBottomSheet(context); }, child: _model.buildQrCode( dimension: dimension, errorCorrectLevel: QrErrorCorrectLevel.M, identifier: _model.userDevUUID, pass: _model.key!, direction: 5, ), ), ), if (_model.isAccess == false && _model.key == null) Align( alignment: const AlignmentDirectional(0, 0), child: BarcodeWidget( data: 'Barcode', barcode: Barcode.qrCode(), width: 300.0, height: 200.0, color: FlutterFlowTheme.of(context).primaryText, backgroundColor: Colors.transparent, errorBuilder: (context, error) => const SizedBox( width: 300.0, height: 200.0, ), drawText: false, ).animateOnActionTrigger( animationsMap['barcodeOnActionTriggerAnimation']!, ), ), if (_model.isAccess == false && _model.key == null) Align( alignment: const AlignmentDirectional(0.0, 0.0), child: InkWell( splashColor: Colors.transparent, focusColor: Colors.transparent, hoverColor: Colors.transparent, highlightColor: Colors.transparent, onLongPress: () async { await _model.qrCodeEncoder( context, key: _model.key, ); setState(() {}); }, child: Container( width: 200.0, height: 200.0, decoration: const BoxDecoration(), child: Align( alignment: const AlignmentDirectional(0.0, 0.0), child: FFButtonWidget( onPressed: () async { _model.isFingerprint ? await _showBiometricsAuth(context) : await _showQrCodeBottomSheet(context); }, text: FFLocalizations.of(context).getVariableText( ptText: 'Gerar QR Code', enText: 'Generate QR Code', ), options: FFButtonOptions( height: 40.0, padding: const EdgeInsetsDirectional.fromSTEB( 24.0, 0.0, 24.0, 0.0), iconPadding: const EdgeInsetsDirectional.fromSTEB( 0.0, 0.0, 0.0, 0.0), color: FlutterFlowTheme.of(context).primary, textStyle: FlutterFlowTheme.of(context) .titleSmall .override( fontFamily: FlutterFlowTheme.of(context) .titleSmallFamily, color: Colors.white, letterSpacing: 0.0, useGoogleFonts: GoogleFonts.asMap() .containsKey( FlutterFlowTheme.of(context) .titleSmallFamily), fontSize: LimitedFontSizeUtil .getCalculateFontSize( context, 12, 12, 10), ), elevation: 3.0, borderSide: const BorderSide( color: Colors.transparent, width: 1.0, ), borderRadius: BorderRadius.circular(8.0), ), ), ), ), ), ), ], ), if (_model.isAccess == true && _model.key != null) Padding( padding: const EdgeInsets.fromLTRB(0, 20, 0, 0), child: Container( width: 300.0, decoration: const BoxDecoration(), child: Visibility( visible: _model.isAccess == true, child: Text( FFLocalizations.of(context).getVariableText( ptText: 'Certifique-se de que o QRCode está visivel para o leitor', enText: 'Make sure the QRCode is visible to the reader', // '6z6kvmhl' /* Certifique-se de que o QRCode ... */, ), textAlign: TextAlign.center, style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily, letterSpacing: 0.0, useGoogleFonts: GoogleFonts.asMap().containsKey( FlutterFlowTheme.of(context) .bodyMediumFamily), fontSize: limitedBodyFontSize, ), ), ), ), ), if (_model.isAccess == true && _model.key != null) Padding( padding: const EdgeInsets.fromLTRB(0, 20, 0, 20), child: Container( width: 250.0, height: 80.0, decoration: BoxDecoration( borderRadius: BorderRadius.circular(100.0), border: Border.all( color: FlutterFlowTheme.of(context).primary, ), ), child: Row( mainAxisSize: MainAxisSize.max, children: [ Expanded( child: Padding( padding: const EdgeInsetsDirectional.fromSTEB( 10.0, 0.0, 0.0, 0.0), child: Text( FFLocalizations.of(context).getVariableText( ptText: 'Expirando QR code em', enText: 'Expiring QR code in', // 'wkjkxd2e' /* Trocando QR code em */, ), textAlign: TextAlign.center, style: FlutterFlowTheme.of(context) .bodyMedium .override( fontFamily: FlutterFlowTheme.of(context) .bodyMediumFamily, letterSpacing: 0.0, fontWeight: FontWeight.w600, useGoogleFonts: GoogleFonts.asMap() .containsKey( FlutterFlowTheme.of(context) .bodyMediumFamily), fontSize: LimitedFontSizeUtil.getNoResizeFont( context, 14), ), ), ), ), Align( alignment: const AlignmentDirectional(0.0, 0.0), child: Padding( padding: const EdgeInsetsDirectional.fromSTEB( 0.0, 0.0, 20.0, 0.0), child: StreamBuilder( stream: getProgressValue(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(); } else if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else if (!snapshot.hasData) { return const Text('No data'); } else { final progress = snapshot.data!; return CircularPercentIndicator( percent: progress, restartAnimation: true, reverse: false, radius: 30.0, lineWidth: 7.0, animation: true, animateFromLastPercent: true, onAnimationEnd: () { _resetAnimationAndToggleAccess(); }, progressColor: FlutterFlowTheme.of(context).primary, backgroundColor: FlutterFlowTheme.of(context) .primaryText, center: Text( '${(progress * totalTimeInSeconds / 5).toStringAsFixed(1)}s', style: FlutterFlowTheme.of(context) .headlineSmall .override( fontFamily: FlutterFlowTheme.of(context) .headlineSmallFamily, fontSize: LimitedFontSizeUtil .getNoResizeFont(context, 14), letterSpacing: 0.0, useGoogleFonts: GoogleFonts.asMap() .containsKey( FlutterFlowTheme.of(context) .headlineSmallFamily), ), ), startAngle: 20.0, ); } }, ), ), ), ], ), ), ), ], ), ), ), ); } Future _showBiometricsAuth(BuildContext context) async { await BiometricHelper.checkBiometrics() .then((value) async => await BiometricHelper.authenticateBiometric().then((value) async { if (value == false) throw Exception('Biometric authentication failed'); final key = await StorageHelper() .get(SecureStorageKey.fingerprintPass.value); if (key == null || key.isEmpty) throw Exception('No key found'); safeSetState(() { if (animationsMap['barcodeOnActionTriggerAnimation'] != null) { animationsMap['barcodeOnActionTriggerAnimation']! .controller .stop(); animationsMap['barcodeOnActionTriggerAnimation']! .controller .reverse(); } _model.isAccess = !_model.isAccess; _model.key = key; }); })) .onError((error, stackTrace) { log('Error', error: error, stackTrace: stackTrace); if (mounted) _showQrCodeBottomSheet(context); }); } Future _showQrCodeBottomSheet(BuildContext context) async { await showModalBottomSheet( isScrollControlled: true, backgroundColor: Colors.transparent, useSafeArea: true, context: context, builder: (context) { return GestureDetector( onTap: () => _model.unfocusNode.canRequestFocus ? FocusScope.of(context).requestFocus(_model.unfocusNode) : FocusScope.of(context).unfocus(), child: Padding( padding: MediaQuery.viewInsetsOf(context), child: QrCodePassKeyTemplateComponentWidget( toggleActionStatus: (key) async { safeSetState(() { if (animationsMap['barcodeOnActionTriggerAnimation'] != null) { animationsMap['barcodeOnActionTriggerAnimation']! .controller .stop(); animationsMap['barcodeOnActionTriggerAnimation']! .controller .reverse(); } _model.isAccess = !_model.isAccess; _model.key = key; }); }, ), ), ); }, ).catchError( (error) => safeSetState(() => _resetAnimationAndToggleAccess())); unawaited( () async { await _model.qrCodeEncoder(context, key: _model.key); safeSetState(() {}); }(), ); } void _resetAnimationAndToggleAccess() { safeSetState(() { animationsMap['barcodeOnActionTriggerAnimation']!.controller.reset(); animationsMap['barcodeOnActionTriggerAnimation']!.controller.forward(); _model.isAccess = !_model.isAccess; _model.key = null; }); } AppBar buildAppBar(BuildContext context) { return AppBar( key: ValueKey('BackNavigationAppBar'), backgroundColor: FlutterFlowTheme.of(context).primaryBackground, automaticallyImplyLeading: false, 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( ptText: 'QRCode de Acesso', enText: 'Access QRCode', ), style: FlutterFlowTheme.of(context).headlineMedium.override( fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, color: FlutterFlowTheme.of(context).primaryText, fontSize: 16.0, fontWeight: FontWeight.bold, letterSpacing: 0.0, useGoogleFonts: GoogleFonts.asMap().containsKey( FlutterFlowTheme.of(context).headlineMediumFamily), ), ), actions: const [], centerTitle: true, elevation: 0.0, ); } }