Adds the Flutter inventory app source, cleaned up for a shared repo: generic package name, no hardcoded ERP endpoints (moved to gitignored local config), no dead auth code, no debug logging of session data.
183 lines
6.7 KiB
Dart
183 lines
6.7 KiB
Dart
import 'dart:io';
|
|
import 'dart:ui' show ImageFilter;
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart';
|
|
import 'package:inventory_app/constants.dart';
|
|
|
|
class QRViewExample extends StatefulWidget {
|
|
const QRViewExample({super.key});
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _QRViewExampleState();
|
|
}
|
|
|
|
class _QRViewExampleState extends State<QRViewExample> {
|
|
Barcode? result;
|
|
QRViewController? controller;
|
|
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
|
|
|
|
@override
|
|
void reassemble() {
|
|
super.reassemble();
|
|
if (Platform.isAndroid) {
|
|
controller!.pauseCamera();
|
|
}
|
|
controller!.resumeCamera();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: Column(
|
|
children: <Widget>[
|
|
Expanded(flex: 4, child: _buildQrView(context)),
|
|
Expanded(
|
|
flex: 1,
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12),
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadius.circular(20),
|
|
child: BackdropFilter(
|
|
filter: ImageFilter.blur(sigmaX: 12, sigmaY: 12),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
Colors.white.withOpacity(0.08),
|
|
Colors.white.withOpacity(0.04),
|
|
],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
borderRadius: BorderRadius.circular(20),
|
|
border: Border.all(color: Colors.white.withOpacity(0.12)),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.15),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 4),
|
|
),
|
|
],
|
|
),
|
|
child: FittedBox(
|
|
fit: BoxFit.contain,
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: <Widget>[
|
|
if (result != null)
|
|
Text(
|
|
'Barcode Type: ${describeEnum(result!.format)} Data: ${result!.code}',
|
|
style: kTextFormFieldStyle(),
|
|
)
|
|
else
|
|
Text('Scan a code', style: kTextFormFieldStyle()),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: <Widget>[
|
|
_glassButton(
|
|
child: FutureBuilder(
|
|
future: controller?.getFlashStatus(),
|
|
builder: (context, snapshot) =>
|
|
Text('Flash: ${snapshot.data}'),
|
|
),
|
|
onPressed: () async {
|
|
await controller?.toggleFlash();
|
|
setState(() {});
|
|
},
|
|
),
|
|
_glassButton(
|
|
child: FutureBuilder(
|
|
future: controller?.getCameraInfo(),
|
|
builder: (context, snapshot) =>
|
|
snapshot.data != null
|
|
? Text('Camera facing ${describeEnum(snapshot.data!)}')
|
|
: const Text('loading'),
|
|
),
|
|
onPressed: () async {
|
|
await controller?.flipCamera();
|
|
setState(() {});
|
|
},
|
|
),
|
|
],
|
|
),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: <Widget>[
|
|
_glassButton(
|
|
child: const Text('pause', style: TextStyle(fontSize: 20)),
|
|
onPressed: () async => controller?.pauseCamera(),
|
|
),
|
|
_glassButton(
|
|
child: const Text('resume', style: TextStyle(fontSize: 20)),
|
|
onPressed: () async => controller?.resumeCamera(),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _glassButton({required Widget child, required VoidCallback onPressed}) {
|
|
return Container(
|
|
margin: const EdgeInsets.all(8),
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
elevation: 0,
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
backgroundColor: Colors.white.withOpacity(0.06),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12),
|
|
side: BorderSide(color: Colors.white.withOpacity(0.12)),
|
|
),
|
|
),
|
|
onPressed: onPressed,
|
|
child: child,
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildQrView(BuildContext context) {
|
|
final scanArea =
|
|
(MediaQuery.of(context).size.width < 500 ||
|
|
MediaQuery.of(context).size.height < 500)
|
|
? 300.0
|
|
: 450.0;
|
|
return QRView(
|
|
key: qrKey,
|
|
onQRViewCreated: _onQRViewCreated,
|
|
overlay: QrScannerOverlayShape(
|
|
borderColor: Colors.blue,
|
|
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) {
|
|
setState(() => result = scanData);
|
|
Get.back(result: result!.code);
|
|
});
|
|
}
|
|
|
|
void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) {
|
|
if (!p) Get.snackbar("Permission", 'no Permission');
|
|
}
|
|
}
|