2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 13:36:50 +00:00

Barcode camera fix (#270)

* Bug fix for multiple barcode scans

- Do not resume scan until action is performed
- Add in delay before re-starting camera

* Change release notes to 0.10.1

* linting fixes
This commit is contained in:
Oliver 2023-02-22 00:52:26 +11:00 committed by GitHub
parent 5c06e3c9de
commit fb80029c0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 88 additions and 61 deletions

View File

@ -1,10 +1,11 @@
## InvenTree App Release Notes ## InvenTree App Release Notes
--- ---
### 0.11.0 - ### 0.10.1 - February 2023
--- ---
- Add support for attachments on Companies - Add support for attachments on Companies
- Fix duplicate scanning of barcodes
### 0.10.0 - February 2023 ### 0.10.0 - February 2023
--- ---

View File

@ -58,8 +58,6 @@ class BarcodeHandler {
String getOverlayText(BuildContext context) => "Barcode Overlay"; String getOverlayText(BuildContext context) => "Barcode Overlay";
QRViewController? _controller;
Future<void> onBarcodeMatched(Map<String, dynamic> data) async { Future<void> onBarcodeMatched(Map<String, dynamic> data) async {
// Called when the server "matches" a barcode // Called when the server "matches" a barcode
// Override this function // Override this function
@ -78,21 +76,18 @@ class BarcodeHandler {
); );
} }
Future<void> onBarcodeUnhandled(Map<String, dynamic> data) async {
barcodeFailureTone();
// Called when the server returns an unhandled response // Called when the server returns an unhandled response
Future<void> onBarcodeUnhandled(Map<String, dynamic> data) async {
barcodeFailureTone();
showServerError("barcode/", L10().responseUnknown, data.toString()); showServerError("barcode/", L10().responseUnknown, data.toString());
_controller?.resumeCamera();
} }
/* /*
* Base function to capture and process barcode data. * Base function to capture and process barcode data.
*
* Returns true only if the barcode scanner should remain open
*/ */
Future<void> processBarcode(QRViewController? _controller, String barcode, {String url = "barcode/"}) async { Future<void> processBarcode(QRViewController? _controller, String barcode, {String url = "barcode/"}) async {
this._controller = _controller;
debug("Scanned barcode data: '${barcode}'"); debug("Scanned barcode data: '${barcode}'");
@ -122,8 +117,6 @@ class BarcodeHandler {
debug("Barcode scan response" + response.data.toString()); debug("Barcode scan response" + response.data.toString());
_controller?.resumeCamera();
Map<String, dynamic> data = response.asMap(); Map<String, dynamic> data = response.asMap();
// Handle strange response from the server // Handle strange response from the server
@ -188,53 +181,55 @@ class BarcodeScanHandler extends BarcodeHandler {
* Response when a "Part" instance is scanned * Response when a "Part" instance is scanned
*/ */
Future<void> handlePart(int pk) async { Future<void> handlePart(int pk) async {
InvenTreePart().get(pk).then((var part) {
// Dismiss the barcode scanner var part = await InvenTreePart().get(pk);
OneContext().pop();
if (part is InvenTreePart) { if (part is InvenTreePart) {
OneContext().pop();
OneContext().push(MaterialPageRoute(builder: (context) => PartDetailWidget(part))); OneContext().push(MaterialPageRoute(builder: (context) => PartDetailWidget(part)));
} }
});
} }
/* /*
* Response when a "StockItem" instance is scanned * Response when a "StockItem" instance is scanned
*/ */
Future<void> handleStockItem(int pk) async { Future<void> handleStockItem(int pk) async {
InvenTreeStockItem().get(pk).then((var item) {
OneContext().pop(); var item = await InvenTreeStockItem().get(pk);
if (item is InvenTreeStockItem) { if (item is InvenTreeStockItem) {
OneContext().pop();
OneContext().push(MaterialPageRoute( OneContext().push(MaterialPageRoute(
builder: (context) => StockDetailWidget(item))); builder: (context) => StockDetailWidget(item)));
} }
});
} }
/* /*
* Response when a "StockLocation" instance is scanned * Response when a "StockLocation" instance is scanned
*/ */
Future<void> handleStockLocation(int pk) async { Future<void> handleStockLocation(int pk) async {
InvenTreeStockLocation().get(pk).then((var loc) {
var loc = await InvenTreeStockLocation().get(pk);
if (loc is InvenTreeStockLocation) { if (loc is InvenTreeStockLocation) {
OneContext().pop(); OneContext().pop();
OneContext().navigator.push(MaterialPageRoute( OneContext().navigator.push(MaterialPageRoute(
builder: (context) => LocationDisplayWidget(loc))); builder: (context) => LocationDisplayWidget(loc)));
} }
});
} }
/* /*
* Response when a "SupplierPart" instance is scanned * Response when a "SupplierPart" instance is scanned
*/ */
Future<void> handleSupplierPart(int pk) async { Future<void> handleSupplierPart(int pk) async {
InvenTreeSupplierPart().get(pk).then((var supplierpart) {
OneContext().pop(); var supplierpart = await InvenTreeSupplierPart().get(pk);
if (supplierpart is InvenTreeSupplierPart) { if (supplierpart is InvenTreeSupplierPart) {
OneContext().push(MaterialPageRoute(builder: (context) => SupplierPartDetailWidget(supplierpart))); OneContext().pop();
OneContext().push(MaterialPageRoute(
builder: (context) => SupplierPartDetailWidget(supplierpart)));
} }
});
} }
@override @override
@ -270,16 +265,16 @@ class BarcodeScanHandler extends BarcodeHandler {
switch (model) { switch (model) {
case "part": case "part":
handlePart(pk); await handlePart(pk);
return; return;
case "stockitem": case "stockitem":
handleStockItem(pk); await handleStockItem(pk);
return; return;
case "stocklocation": case "stocklocation":
handleStockLocation(pk); await handleStockLocation(pk);
return; return;
case "supplierpart": case "supplierpart":
handleSupplierPart(pk); await handleSupplierPart(pk);
return; return;
default: default:
// Fall through to failure state // Fall through to failure state
@ -339,11 +334,10 @@ class BarcodeScanStockLocationHandler extends BarcodeHandler {
if (result && OneContext.hasContext) { if (result && OneContext.hasContext) {
OneContext().pop(); OneContext().pop();
}
return; return;
} }
} }
}
// If we get to this point, something went wrong during the scan process // If we get to this point, something went wrong during the scan process
barcodeFailureTone(); barcodeFailureTone();
@ -386,15 +380,14 @@ class BarcodeScanStockItemHandler extends BarcodeHandler {
barcodeSuccessTone(); barcodeSuccessTone();
final bool result = await onItemScanned(_item); bool result = await onItemScanned(_item);
if (result && OneContext.hasContext) { if (result && OneContext.hasContext) {
OneContext().pop(); OneContext().pop();
}
return; return;
} }
} }
}
// If we get to this point, something went wrong during the scan process // If we get to this point, something went wrong during the scan process
barcodeFailureTone(); barcodeFailureTone();
@ -410,7 +403,6 @@ class BarcodeScanStockItemHandler extends BarcodeHandler {
// Re-implement this for particular subclass // Re-implement this for particular subclass
return false; return false;
} }
} }
@ -641,6 +633,8 @@ class _QRViewState extends State<InvenTreeQRView> {
bool flash_status = false; bool flash_status = false;
bool currently_processing = false;
Future<void> updateFlashStatus() async { Future<void> updateFlashStatus() async {
final bool? status = await _controller?.getFlashStatus(); final bool? status = await _controller?.getFlashStatus();
@ -658,22 +652,54 @@ class _QRViewState extends State<InvenTreeQRView> {
void reassemble() { void reassemble() {
super.reassemble(); super.reassemble();
if (mounted) {
if (Platform.isAndroid) { if (Platform.isAndroid) {
_controller!.pauseCamera(); _controller!.pauseCamera();
} }
_controller!.resumeCamera(); _controller!.resumeCamera();
} }
}
/* Callback function when the Barcode scanner view is initially created */
void _onViewCreated(BuildContext context, QRViewController controller) { void _onViewCreated(BuildContext context, QRViewController controller) {
_controller = controller; _controller = controller;
controller.scannedDataStream.listen((barcode) { controller.scannedDataStream.listen((barcode) {
handleBarcode(barcode.code);
});
}
/* Handle scanned data */
Future<void> handleBarcode(String? data) async {
// Empty or missing data, or we have navigated away
if (!mounted || data == null || data.isEmpty) {
return;
}
// Currently processing a barcode - return!
if (currently_processing) {
return;
}
setState(() {
currently_processing = true;
});
// Pause camera functionality until we are done processing
_controller?.pauseCamera(); _controller?.pauseCamera();
if (barcode.code != null) { // processBarcode returns true if the scanner window is to remain open
widget._handler.processBarcode(_controller, barcode.code ?? ""); widget._handler.processBarcode(_controller, data).then((value) {
// Re-start the process after some delay
Future.delayed(Duration(milliseconds: 500)).then((value) {
if (mounted) {
_controller?.resumeCamera();
currently_processing = false;
} }
}); });
});
} }
@override @override