import 'dart:async'; import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_nfc_kit/flutter_nfc_kit.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; void showNfcReader(BuildContext context, {Function(String?)? onNcfScan}) { showModalBottomSheet( context: context, enableDrag: false, isDismissible: false, barrierColor: Colors.black.withOpacity(0.5), shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), ), backgroundColor: Colors.white, builder: (context) { return NfcLayout(onNcfScan: onNcfScan); }, ); } class NfcLayout extends StatefulWidget { final Function(String? nfcId)? onNcfScan; const NfcLayout({super.key, required this.onNcfScan}); @override _NfcLayoutState createState() => _NfcLayoutState(); } class _NfcLayoutState extends State { bool _reading = false; Widget? mainWidget; String? nfcId; bool _nfcScanning = false; @override void initState() { super.initState(); _startNfcScan(); } Future _startNfcScan() async { if (_nfcScanning) return; _nfcScanning = true; try { NFCTag tag = await FlutterNfcKit.poll( timeout: const Duration(seconds: 20), ); nfcId = tag.id.toUpperCase(); setState(() { _reading = true; // mainWidget = doneNfc(); }); await Future.delayed(const Duration(seconds: 1)); await FlutterNfcKit.finish(); Navigator.pop(context); widget.onNcfScan?.call(nfcId); log("NFC Tag ID: $nfcId"); } catch (e) { if (e.toString().contains("408")) { debugPrint("NFC scan timeout"); } else if (e.toString().contains("cancelled")) { debugPrint("NFC cancelled by user"); } else { debugPrint("NFC error: $e"); "Failed to read NFC card".showToast; } try { await FlutterNfcKit.finish(); } catch (_) {} Navigator.pop(context); } finally { _nfcScanning = false; } } @override Widget build(BuildContext context) { (mainWidget == null && !_reading) ? mainWidget = scanNfc() : mainWidget = doneNfc(); return AnimatedSwitcher(duration: const Duration(milliseconds: 500), child: mainWidget); } Widget scanNfc() { return Container( color: AppColor.background(context), padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom + MediaQuery.of(context).padding.bottom), key: const ValueKey(1), child: Column( mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 30), Text( "Ready To Scan", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 24, color: AppColor.headingTextColor(context), ), ), const SizedBox(height: 30), Image.asset( "assets/images/ic_nfc.png", height: MediaQuery.of(context).size.width / 3, color: AppColor.iconColor(context), width: double.infinity, ), const SizedBox(height: 30), const Text( "Approach an NFC Tag", style: TextStyle(fontSize: 18), ), const SizedBox(height: 30), ButtonTheme( minWidth: MediaQuery.of(context).size.width / 1.2, height: 45.0, buttonColor: Colors.grey[300], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), child: TextButton( onPressed: () async { try { await FlutterNfcKit.finish(); } catch (_) {} Navigator.pop(context); }, child: const Text("CANCEL"), ), ), const SizedBox(height: 30), ], ), ); } Widget doneNfc() { return Container( color: AppColor.background(context), padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom + MediaQuery.of(context).padding.bottom), key: const ValueKey(2), child: Column( mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 30), Text( "Successfully Scanned", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 24, color: AppColor.headingTextColor(context), ), ), const SizedBox(height: 30), Image.asset( "assets/images/ic_done.png", height: MediaQuery.of(context).size.width / 3, width: double.infinity, color: AppColor.iconColor(context), ), const SizedBox(height: 30), const Text( "Approach an NFC Tag", style: TextStyle(fontSize: 18), ), const SizedBox(height: 30), ButtonTheme( minWidth: MediaQuery.of(context).size.width / 1.2, height: 45.0, buttonColor: Colors.grey[300], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), child: TextButton( onPressed: null, child: Text( "DONE", style: TextStyle( color: context.isDark ? AppColor.primary10 : null, ), ), ), ), const SizedBox(height: 30), ], ), ); } } // class NfcLayout extends StatefulWidget { // final Function(String? nfcId)? onNcfScan; // // const NfcLayout({super.key, required this.onNcfScan}); // // @override // _NfcLayoutState createState() => _NfcLayoutState(); // } // // class _NfcLayoutState extends State { // bool _reading = false; // Widget? mainWidget; // String? nfcId; // // @override // void initState() { // super.initState(); // // NfcManager.instance.startSession( // onDiscovered: (NfcTag tag) async { // String? identifier; // // try { // final dynamic tagDynamic = tag; // final Map tagData = Map.from(tagDynamic.data as Map); // // if (Platform.isAndroid) { // if (tagData.containsKey('nfca')) { // final nfcaData = tagData['nfca'] as Map; // if (nfcaData.containsKey('identifier')) { // final List idBytes = List.from(nfcaData['identifier'] as List); // identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); // } // } // } else { // if (tagData.containsKey('mifare')) { // final mifareData = tagData['mifare'] as Map; // if (mifareData.containsKey('identifier')) { // final List idBytes = List.from(mifareData['identifier'] as List); // identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); // } // } // } // } catch (e) { // print('Error reading NFC tag: $e'); // } // // nfcId = identifier; // // setState(() { // _reading = true; // mainWidget = doneNfc(); // }); // // Future.delayed(const Duration(seconds: 1), () { // NfcManager.instance.stopSession(); // Navigator.pop(context); // widget.onNcfScan!(nfcId!); // }); // }, // pollingOptions: {NfcPollingOption.iso14443}, // ).catchError((err) { // print(err); // }); // } // // @override // Widget build(BuildContext context) { // (mainWidget == null && !_reading) ? mainWidget = scanNfc() : mainWidget = doneNfc(); // return AnimatedSwitcher(duration: Duration(milliseconds: 500), child: mainWidget); // } // // Widget scanNfc() { // return Container( // color: AppColor.background(context), // key: const ValueKey(1), // child: Column( // mainAxisSize: MainAxisSize.min, // children: [ // const SizedBox( // height: 30, // ), // Text( // "Ready To Scan", // style: TextStyle( // fontWeight: FontWeight.bold, // fontSize: 24, // color:AppColor.headingTextColor(context) // ), // ), // const SizedBox( // height: 30, // ), // Image.asset( // "assets/images/ic_nfc.png", // height: MediaQuery.of(context).size.width / 3, // color: AppColor.iconColor(context), // width: double.infinity, // ), // const SizedBox( // height: 30, // ), // const Text( // "Approach an NFC Tag", // style: TextStyle( // fontSize: 18, // ), // ), // const SizedBox( // height: 30, // ), // ButtonTheme( // minWidth: MediaQuery.of(context).size.width / 1.2, // height: 45.0, // buttonColor: Colors.grey[300], // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(6), // ), // child: TextButton( // onPressed: () { // NfcManager.instance.stopSession(); // Navigator.pop(context); // }, // // elevation: 0, // child: const Text("CANCEL"), // ), // ), // const SizedBox( // height: 30, // ), // ], // ), // ); // } // // Widget doneNfc() { // return Container( // color: AppColor.background(context), // key: ValueKey(2), // child: Column( // mainAxisSize: MainAxisSize.min, // children: [ // const SizedBox( // height: 30, // ), // Text( // "Successfully Scanned", // style: TextStyle( // fontWeight: FontWeight.bold, // fontSize: 24, // color:AppColor.headingTextColor(context) // ), // ), // const SizedBox( // height: 30, // ), // Image.asset( // // "assets/icons/nfc/ic_done.png", // "assets/images/ic_done.png", // height: MediaQuery.of(context).size.width / 3, // width: double.infinity, // color: AppColor.iconColor(context), // ), // const SizedBox( // height: 30, // ), // const Text( // "Approach an NFC Tag", // style: TextStyle( // fontSize: 18, // ), // ), // const SizedBox( // height: 30, // ), // ButtonTheme( // minWidth: MediaQuery.of(context).size.width / 1.2, // height: 45.0, // buttonColor: Colors.grey[300], // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(6), // ), // child: TextButton( // // onPressed: () { // // _stream?.cancel(); // // widget.onNcfScan(nfcId); // // Navigator.pop(context); // // }, // onPressed: null, // // elevation: 0, // child: Text("DONE",style: TextStyle(color: context.isDark?AppColor.primary10:null),), // ), // ), // const SizedBox( // height: 30, // ), // ], // ), // ); // } // }