| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  | import 'dart:async'; | 
					
						
							|  |  |  | import 'dart:io'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							|  |  |  | import 'package:image/image.dart' as img; | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  | import 'package:image_picker/image_picker.dart'; | 
					
						
							|  |  |  | import 'package:qr_code_scanner/qr_code_scanner.dart'; | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  | import 'package:zxing2/qrcode.dart'; | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-24 23:33:00 +08:00
										 |  |  | import '../../common.dart'; | 
					
						
							| 
									
										
										
										
											2024-02-25 13:29:06 +08:00
										 |  |  | import '../../models/platform_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  | import '../widgets/dialog.dart'; | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class ScanPage extends StatefulWidget { | 
					
						
							|  |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |   State<ScanPage> createState() => _ScanPageState(); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _ScanPageState extends State<ScanPage> { | 
					
						
							|  |  |  |   QRViewController? controller; | 
					
						
							|  |  |  |   final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // In order to get hot reload to work we need to pause the camera if the platform
 | 
					
						
							|  |  |  |   // is android, or resume the camera if the platform is iOS.
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void reassemble() { | 
					
						
							|  |  |  |     super.reassemble(); | 
					
						
							|  |  |  |     if (isAndroid) { | 
					
						
							|  |  |  |       controller!.pauseCamera(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     controller!.resumeCamera(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return Scaffold( | 
					
						
							|  |  |  |         appBar: AppBar( | 
					
						
							|  |  |  |           title: const Text('Scan QR'), | 
					
						
							|  |  |  |           actions: [ | 
					
						
							|  |  |  |             IconButton( | 
					
						
							|  |  |  |                 color: Colors.white, | 
					
						
							|  |  |  |                 icon: Icon(Icons.image_search), | 
					
						
							|  |  |  |                 iconSize: 32.0, | 
					
						
							|  |  |  |                 onPressed: () async { | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |                   final ImagePicker picker = ImagePicker(); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |                   final XFile? file = | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |                       await picker.pickImage(source: ImageSource.gallery); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |                   if (file != null) { | 
					
						
							|  |  |  |                     var image = img.decodeNamedImage( | 
					
						
							| 
									
										
										
										
											2023-05-11 14:26:59 +08:00
										 |  |  |                         file.path, File(file.path).readAsBytesSync())!; | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     LuminanceSource source = RGBLuminanceSource( | 
					
						
							|  |  |  |                         image.width, | 
					
						
							|  |  |  |                         image.height, | 
					
						
							|  |  |  |                         image | 
					
						
							| 
									
										
										
										
											2023-05-11 14:26:59 +08:00
										 |  |  |                             .getBytes(order: img.ChannelOrder.abgr) | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |                             .buffer | 
					
						
							|  |  |  |                             .asInt32List()); | 
					
						
							|  |  |  |                     var bitmap = BinaryBitmap(HybridBinarizer(source)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     var reader = QRCodeReader(); | 
					
						
							|  |  |  |                     try { | 
					
						
							|  |  |  |                       var result = reader.decode(bitmap); | 
					
						
							| 
									
										
										
										
											2024-02-25 13:29:06 +08:00
										 |  |  |                       if (result.text.startsWith(bind.mainUriPrefixSync())) { | 
					
						
							| 
									
										
										
										
											2023-12-03 22:33:52 +08:00
										 |  |  |                         handleUriLink(uriString: result.text); | 
					
						
							|  |  |  |                       } else { | 
					
						
							|  |  |  |                         showServerSettingFromQr(result.text); | 
					
						
							|  |  |  |                       } | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |                     } catch (e) { | 
					
						
							| 
									
										
										
										
											2022-08-15 14:39:31 +08:00
										 |  |  |                       showToast('No QR code found'); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |                     } | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                 }), | 
					
						
							|  |  |  |             IconButton( | 
					
						
							|  |  |  |                 color: Colors.yellow, | 
					
						
							|  |  |  |                 icon: Icon(Icons.flash_on), | 
					
						
							|  |  |  |                 iconSize: 32.0, | 
					
						
							|  |  |  |                 onPressed: () async { | 
					
						
							|  |  |  |                   await controller?.toggleFlash(); | 
					
						
							|  |  |  |                 }), | 
					
						
							|  |  |  |             IconButton( | 
					
						
							|  |  |  |               color: Colors.white, | 
					
						
							|  |  |  |               icon: Icon(Icons.switch_camera), | 
					
						
							|  |  |  |               iconSize: 32.0, | 
					
						
							|  |  |  |               onPressed: () async { | 
					
						
							|  |  |  |                 await controller?.flipCamera(); | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         body: _buildQrView(context)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Widget _buildQrView(BuildContext context) { | 
					
						
							|  |  |  |     // For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
 | 
					
						
							|  |  |  |     var scanArea = (MediaQuery.of(context).size.width < 400 || | 
					
						
							|  |  |  |             MediaQuery.of(context).size.height < 400) | 
					
						
							|  |  |  |         ? 150.0 | 
					
						
							|  |  |  |         : 300.0; | 
					
						
							|  |  |  |     // To ensure the Scanner view is properly sizes after rotation
 | 
					
						
							|  |  |  |     // we need to listen for Flutter SizeChanged notification and update controller
 | 
					
						
							|  |  |  |     return QRView( | 
					
						
							|  |  |  |       key: qrKey, | 
					
						
							|  |  |  |       onQRViewCreated: _onQRViewCreated, | 
					
						
							|  |  |  |       overlay: QrScannerOverlayShape( | 
					
						
							|  |  |  |           borderColor: Colors.red, | 
					
						
							|  |  |  |           borderRadius: 10, | 
					
						
							|  |  |  |           borderLength: 30, | 
					
						
							|  |  |  |           borderWidth: 10, | 
					
						
							|  |  |  |           cutOutSize: scanArea), | 
					
						
							|  |  |  |       onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void _onQRViewCreated(QRViewController controller) { | 
					
						
							|  |  |  |     setState(() { | 
					
						
							|  |  |  |       this.controller = controller; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     controller.scannedDataStream.listen((scanData) { | 
					
						
							|  |  |  |       if (scanData.code != null) { | 
					
						
							|  |  |  |         showServerSettingFromQr(scanData.code!); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) { | 
					
						
							|  |  |  |     if (!p) { | 
					
						
							| 
									
										
										
										
											2022-08-15 14:39:31 +08:00
										 |  |  |       showToast('No permission'); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     controller?.dispose(); | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void showServerSettingFromQr(String data) async { | 
					
						
							| 
									
										
										
										
											2022-08-16 21:27:21 +08:00
										 |  |  |     closeConnection(); | 
					
						
							| 
									
										
										
										
											2022-04-18 17:01:45 +08:00
										 |  |  |     await controller?.pauseCamera(); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |     if (!data.startsWith('config=')) { | 
					
						
							| 
									
										
										
										
											2022-08-15 14:39:31 +08:00
										 |  |  |       showToast('Invalid QR code'); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     try { | 
					
						
							| 
									
										
										
										
											2022-12-21 15:41:07 +09:00
										 |  |  |       final sc = ServerConfig.decode(data.substring(7)); | 
					
						
							| 
									
										
										
										
											2022-04-18 17:01:45 +08:00
										 |  |  |       Timer(Duration(milliseconds: 60), () { | 
					
						
							| 
									
										
										
										
											2022-12-21 16:24:01 +09:00
										 |  |  |         showServerSettingsWithValue(sc, gFFI.dialogManager); | 
					
						
							| 
									
										
										
										
											2022-04-18 17:01:45 +08:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |     } catch (e) { | 
					
						
							| 
									
										
										
										
											2022-08-15 14:39:31 +08:00
										 |  |  |       showToast('Invalid QR code'); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |