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:
parent
5c06e3c9de
commit
fb80029c0e
@ -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
|
||||||
---
|
---
|
||||||
|
146
lib/barcode.dart
146
lib/barcode.dart
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user