2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-27 04:56:48 +00:00
inventree-app/lib/barcode/handler.dart
Oliver d4cff1a5b9
Barcode scanner updates (#562)
* Add BUILDING.md

* Replace scaning library

- Out with qr_code_scanner
- In with flutter_zxing

* Update specs for jdk / kotlin / gradle

- NFI what this all means?

* Refactor barcode scanning widget

* Refactor barcode overlay

* Add handlers

* Update release notes

* Fix AppBar color

* Enhance attachment widget

* remove unused import

* Improved icon

* Select theme from main drawer
2024-12-06 00:08:04 +11:00

124 lines
3.4 KiB
Dart

import "package:flutter/material.dart";
import "package:flutter_tabler_icons/flutter_tabler_icons.dart";
import "package:inventree/api.dart";
import "package:inventree/helpers.dart";
import "package:inventree/l10.dart";
import "package:inventree/barcode/tones.dart";
import "package:inventree/inventree/sentry.dart";
import "package:inventree/widget/dialogs.dart";
import "package:inventree/widget/snacks.dart";
/* Generic class which "handles" a barcode, by communicating with the InvenTree server,
* and handling match / unknown / error cases.
*
* Override functionality of this class to perform custom actions,
* based on the response returned from the InvenTree server
*/
class BarcodeHandler {
BarcodeHandler();
// Return the text to display on the barcode overlay
// Note: Will be overridden by child classes
String getOverlayText(BuildContext context) => "Barcode Overlay";
// Called when the server "matches" a barcode
Future<void> onBarcodeMatched(Map<String, dynamic> data) async {
// Override this function
}
// Called when the server does not know about a barcode
Future<void> onBarcodeUnknown(Map<String, dynamic> data) async {
// Override this function
barcodeFailureTone();
showSnackIcon(
(data["error"] ?? L10().barcodeNoMatch) as String,
success: false,
icon: Icons.qr_code,
);
}
// Called when the server returns an unhandled response
Future<void> onBarcodeUnhandled(Map<String, dynamic> data) async {
barcodeFailureTone();
showServerError("barcode/", L10().responseUnknown, data.toString());
}
/*
* Base function to capture and process barcode data.
*
* Returns true only if the barcode scanner should remain open
*/
Future<void> processBarcode(String barcode,
{String url = "barcode/",
Map<String, dynamic> extra_data = const {}}) async {
debug("Scanned barcode data: '${barcode}'");
barcode = barcode.trim();
// Empty barcode is invalid
if (barcode.isEmpty) {
barcodeFailureTone();
showSnackIcon(
L10().barcodeError,
icon: TablerIcons.exclamation_circle,
success: false
);
return;
}
var response = await InvenTreeAPI().post(
url,
body: {
"barcode": barcode,
...extra_data,
},
expectedStatusCode: null, // Do not show an error on "unexpected code"
);
debug("Barcode scan response" + response.data.toString());
Map<String, dynamic> data = response.asMap();
// Handle strange response from the server
if (!response.isValid() || !response.isMap()) {
onBarcodeUnknown({});
showSnackIcon(L10().serverError, success: false);
// We want to know about this one!
await sentryReportMessage(
"BarcodeHandler.processBarcode returned unexpected value",
context: {
"data": response.data?.toString() ?? "null",
"barcode": barcode,
"url": url,
"statusCode": response.statusCode.toString(),
"valid": response.isValid().toString(),
"error": response.error,
"errorDetail": response.errorDetail,
"className": "${this}",
}
);
} else if (data.containsKey("success")) {
await onBarcodeMatched(data);
} else if ((response.statusCode >= 400) || data.containsKey("error")) {
await onBarcodeUnknown(data);
} else {
await onBarcodeUnhandled(data);
}
}
}