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 onBarcodeMatched(Map data) async { // Override this function } // Called when the server does not know about a barcode Future onBarcodeUnknown(Map 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 onBarcodeUnhandled(Map 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 processBarcode(String barcode, {String url = "barcode/", Map 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 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); } } }