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 { // Called when the server returns an unhandled response
Future<void> onBarcodeUnhandled(Map<String, dynamic> data) async {
barcodeFailureTone(); barcodeFailureTone();
// Called when the server returns an unhandled response
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
OneContext().pop();
if (part is InvenTreePart) { var part = await InvenTreePart().get(pk);
OneContext().push(MaterialPageRoute(builder: (context) => PartDetailWidget(part)));
} if (part is InvenTreePart) {
}); OneContext().pop();
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) {
var item = await InvenTreeStockItem().get(pk);
if (item is InvenTreeStockItem) {
OneContext().pop(); OneContext().pop();
if (item is InvenTreeStockItem) { 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) {
if (loc is InvenTreeStockLocation) { var loc = await InvenTreeStockLocation().get(pk);
OneContext().pop();
OneContext().navigator.push(MaterialPageRoute( if (loc is InvenTreeStockLocation) {
builder: (context) => LocationDisplayWidget(loc))); OneContext().pop();
} OneContext().navigator.push(MaterialPageRoute(
}); 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();
if (supplierpart is InvenTreeSupplierPart) { var supplierpart = await InvenTreeSupplierPart().get(pk);
OneContext().push(MaterialPageRoute(builder: (context) => SupplierPartDetailWidget(supplierpart)));
} if (supplierpart is InvenTreeSupplierPart) {
}); OneContext().pop();
OneContext().push(MaterialPageRoute(
builder: (context) => SupplierPartDetailWidget(supplierpart)));
}
} }
@override @override
@ -270,19 +265,19 @@ 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
break; break;
} }
} }
@ -339,9 +334,8 @@ class BarcodeScanStockLocationHandler extends BarcodeHandler {
if (result && OneContext.hasContext) { if (result && OneContext.hasContext) {
OneContext().pop(); OneContext().pop();
return;
} }
return;
} }
} }
@ -386,13 +380,12 @@ 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;
} }
} }
@ -410,7 +403,6 @@ class BarcodeScanStockItemHandler extends BarcodeHandler {
// Re-implement this for particular subclass // Re-implement this for particular subclass
return false; return false;
} }
} }
@ -480,10 +472,10 @@ class StockLocationScanInItemsHandler extends BarcodeScanStockItemHandler {
} }
} }
showSnackIcon( showSnackIcon(
result ? L10().barcodeScanIntoLocationSuccess : L10().barcodeScanIntoLocationFailure, result ? L10().barcodeScanIntoLocationSuccess : L10().barcodeScanIntoLocationFailure,
success: result success: result
); );
// We always return false here, to ensure the barcode scan dialog remains open // We always return false here, to ensure the barcode scan dialog remains open
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,21 +652,53 @@ class _QRViewState extends State<InvenTreeQRView> {
void reassemble() { void reassemble() {
super.reassemble(); super.reassemble();
if (Platform.isAndroid) { if (mounted) {
_controller!.pauseCamera(); if (Platform.isAndroid) {
} _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?.pauseCamera();
if (barcode.code != null) { controller.scannedDataStream.listen((barcode) {
widget._handler.processBarcode(_controller, barcode.code ?? ""); 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();
// processBarcode returns true if the scanner window is to remain open
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;
}
});
}); });
} }