diff --git a/lib/api.dart b/lib/api.dart index 99b42424..edb2687b 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -341,7 +341,7 @@ class InvenTreeAPI { response = await get("", expectedStatusCode: 200); if (!response.successful()) { - showStatusCodeError(response.statusCode); + showStatusCodeError(apiUrl, response.statusCode); return false; } @@ -351,6 +351,7 @@ class InvenTreeAPI { if (!data.containsKey("server") || !data.containsKey("version") || !data.containsKey("instance")) { showServerError( + apiUrl, L10().missingData, L10().serverMissingData, ); @@ -378,6 +379,7 @@ class InvenTreeAPI { message += "Ensure your InvenTree server version is up to date!"; showServerError( + apiUrl, L10().serverOld, message, ); @@ -401,12 +403,13 @@ class InvenTreeAPI { case 401: case 403: showServerError( + apiUrl, L10().serverAuthenticationError, L10().invalidUsernamePassword, ); break; default: - showStatusCodeError(response.statusCode); + showStatusCodeError(apiUrl, response.statusCode); break; } @@ -417,6 +420,7 @@ class InvenTreeAPI { if (!data.containsKey("token")) { showServerError( + apiUrl, L10().tokenMissing, L10().tokenMissingFromResponse, ); @@ -631,12 +635,12 @@ class InvenTreeAPI { Uri? _uri = Uri.tryParse(makeUrl(url)); if (_uri == null) { - showServerError(L10().invalidHost, L10().invalidHostDetails); + showServerError(url, L10().invalidHost, L10().invalidHostDetails); return; } if (_uri.host.isEmpty) { - showServerError(L10().invalidHost, L10().invalidHostDetails); + showServerError(url, L10().invalidHost, L10().invalidHostDetails); return; } @@ -644,7 +648,7 @@ class InvenTreeAPI { final bool strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) as bool; - var client = createClient(strictHttps: strictHttps); + var client = createClient(url, strictHttps: strictHttps); // Attempt to open a connection to the server try { @@ -658,20 +662,20 @@ class InvenTreeAPI { } on SocketException catch (error) { debug("SocketException at ${url}: ${error.toString()}"); - showServerError(L10().connectionRefused, error.toString()); + showServerError(url, L10().connectionRefused, error.toString()); return; } on TimeoutException { print("TimeoutException at ${url}"); - showTimeoutError(); + showTimeoutError(url); return; } on HandshakeException catch (error) { print("HandshakeException at ${url}:"); debug(error.toString()); - showServerError(L10().serverCertificateError, error.toString()); + showServerError(url, L10().serverCertificateError, error.toString()); return; } catch (error, stackTrace) { print("Server error at ${url}: ${error.toString()}"); - showServerError(L10().serverError, error.toString()); + showServerError(url, L10().serverError, error.toString()); sentryReportError( "api.downloadFile : client.openUrl", error, stackTrace, @@ -693,16 +697,16 @@ class InvenTreeAPI { OpenFile.open(local_path); } } else { - showStatusCodeError(response.statusCode); + showStatusCodeError(url, response.statusCode); } } on SocketException catch (error) { - showServerError(L10().connectionRefused, error.toString()); + showServerError(url, L10().connectionRefused, error.toString()); } on TimeoutException { - showTimeoutError(); + showTimeoutError(url); } catch (error, stackTrace) { print("Error downloading image:"); print(error.toString()); - showServerError(L10().downloadError, error.toString()); + showServerError(url, L10().downloadError, error.toString()); sentryReportError( "api.downloadFile : client.closeRequest", error, stackTrace, @@ -767,11 +771,12 @@ class InvenTreeAPI { ); } } on SocketException catch (error) { - showServerError(L10().connectionRefused, error.toString()); + showServerError(url, L10().connectionRefused, error.toString()); response.error = "SocketException"; response.errorDetail = error.toString(); } on FormatException { showServerError( + url, L10().formatException, L10().formatExceptionJson + ":\n${jsondata}" ); @@ -786,10 +791,10 @@ class InvenTreeAPI { ); } on TimeoutException { - showTimeoutError(); + showTimeoutError(url); response.error = "TimeoutException"; } catch (error, stackTrace) { - showServerError(L10().serverError, error.toString()); + showServerError(url, L10().serverError, error.toString()); sentryReportError( "api.uploadFile", error, stackTrace @@ -845,7 +850,7 @@ class InvenTreeAPI { ); } - HttpClient createClient({bool strictHttps = false}) { + HttpClient createClient(String url, {bool strictHttps = false}) { var client = HttpClient(); @@ -853,6 +858,7 @@ class InvenTreeAPI { if (strictHttps) { showServerError( + url, L10().serverCertificateError, L10().serverCertificateInvalid, ); @@ -897,12 +903,12 @@ class InvenTreeAPI { Uri? _uri = Uri.tryParse(_url); if (_uri == null) { - showServerError(L10().invalidHost, L10().invalidHostDetails); + showServerError(url, L10().invalidHost, L10().invalidHostDetails); return null; } if (_uri.host.isEmpty) { - showServerError(L10().invalidHost, L10().invalidHostDetails); + showServerError(url, L10().invalidHost, L10().invalidHostDetails); return null; } @@ -910,7 +916,7 @@ class InvenTreeAPI { final bool strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) as bool; - var client = createClient(strictHttps: strictHttps); + var client = createClient(url, strictHttps: strictHttps); // Attempt to open a connection to the server try { @@ -925,25 +931,25 @@ class InvenTreeAPI { return _request; } on SocketException catch (error) { print("SocketException at ${url}: ${error.toString()}"); - showServerError(L10().connectionRefused, error.toString()); + showServerError(url, L10().connectionRefused, error.toString()); return null; } on TimeoutException { print("TimeoutException at ${url}"); - showTimeoutError(); + showTimeoutError(url); return null; } on CertificateException catch (error) { print("CertificateException at ${url}:"); print(error.toString()); - showServerError(L10().serverCertificateError, error.toString()); + showServerError(url, L10().serverCertificateError, error.toString()); return null; } on HandshakeException catch (error) { print("HandshakeException at ${url}:"); print(error.toString()); - showServerError(L10().serverCertificateError, error.toString()); + showServerError(url, L10().serverCertificateError, error.toString()); return null; } catch (error, stackTrace) { print("Server error at ${url}: ${error.toString()}"); - showServerError(L10().serverError, error.toString()); + showServerError(url, L10().serverError, error.toString()); sentryReportError( "api.apiRequest : openUrl", error, stackTrace, @@ -975,6 +981,8 @@ class InvenTreeAPI { url: request.uri.toString() ); + String url = request.uri.toString(); + try { HttpClientResponse? _response = await request.close().timeout(Duration(seconds: 10)); @@ -982,7 +990,7 @@ class InvenTreeAPI { // If the server returns a server error code, alert the user if (_response.statusCode >= 500) { - showStatusCodeError(_response.statusCode); + showStatusCodeError(url, _response.statusCode); sentryReportMessage( "Server error", @@ -1001,31 +1009,31 @@ class InvenTreeAPI { if (ignoreResponse) { response.data = {}; } else { - response.data = await responseToJson(_response) ?? {}; + response.data = await responseToJson(url, _response) ?? {}; } if (statusCode != null) { // Expected status code not returned if (statusCode != _response.statusCode) { - showStatusCodeError(_response.statusCode); + showStatusCodeError(url, _response.statusCode); } } } } on SocketException catch (error) { - showServerError(L10().connectionRefused, error.toString()); + showServerError(url, L10().connectionRefused, error.toString()); response.error = "SocketException"; response.errorDetail = error.toString(); } on CertificateException catch (error) { print("CertificateException at ${request.uri.toString()}:"); print(error.toString()); - showServerError(L10().serverCertificateError, error.toString()); + showServerError(url, L10().serverCertificateError, error.toString()); } on TimeoutException { - showTimeoutError(); + showTimeoutError(url); response.error = "TimeoutException"; } catch (error, stackTrace) { - showServerError(L10().serverError, error.toString()); + showServerError(url, L10().serverError, error.toString()); sentryReportError("api.completeRequest", error, stackTrace); response.error = "UnknownError"; response.errorDetail = error.toString(); @@ -1038,7 +1046,7 @@ class InvenTreeAPI { /* * Convert a HttpClientResponse response object to JSON */ - dynamic responseToJson(HttpClientResponse response) async { + dynamic responseToJson(String url, HttpClientResponse response) async { String body = await response.transform(utf8.decoder).join(); @@ -1058,6 +1066,7 @@ class InvenTreeAPI { ); showServerError( + url, L10().formatException, L10().formatExceptionJson + ":\n${body}" ); diff --git a/lib/api_form.dart b/lib/api_form.dart index 04a51dde..23b8e753 100644 --- a/lib/api_form.dart +++ b/lib/api_form.dart @@ -1288,7 +1288,7 @@ class _APIFormWidgetState extends State { final response = await _submit(data); if (!response.isValid()) { - showServerError(L10().serverError, L10().responseInvalid); + showServerError(url, L10().serverError, L10().responseInvalid); return; } diff --git a/lib/barcode.dart b/lib/barcode.dart index 85702e0e..29beebb7 100644 --- a/lib/barcode.dart +++ b/lib/barcode.dart @@ -81,7 +81,7 @@ class BarcodeHandler { barcodeFailureTone(); // Called when the server returns an unhandled response - showServerError(L10().responseUnknown, data.toString()); + showServerError("barcode/", L10().responseUnknown, data.toString()); _controller?.resumeCamera(); } @@ -440,6 +440,7 @@ class UniqueBarcodeHandler extends BarcodeHandler { if (!data.containsKey("hash")) { showServerError( + "barcode/", L10().missingData, L10().barcodeMissingHash, ); diff --git a/lib/inventree/model.dart b/lib/inventree/model.dart index 550bc2f5..5d55e9f1 100644 --- a/lib/inventree/model.dart +++ b/lib/inventree/model.dart @@ -270,6 +270,7 @@ class InvenTreeModel { ); showServerError( + url, L10().serverError, L10().errorDelete, ); @@ -299,6 +300,7 @@ class InvenTreeModel { ); showServerError( + url, L10().serverError, L10().errorFetch, ); @@ -367,6 +369,7 @@ class InvenTreeModel { ); showServerError( + url, L10().serverError, L10().errorFetch, ); @@ -408,6 +411,7 @@ class InvenTreeModel { ); showServerError( + URL, L10().serverError, L10().errorCreate, ); diff --git a/lib/widget/dialogs.dart b/lib/widget/dialogs.dart index 5fbe20b1..a81415c1 100644 --- a/lib/widget/dialogs.dart +++ b/lib/widget/dialogs.dart @@ -7,6 +7,7 @@ import "package:inventree/l10.dart"; import "package:inventree/preferences.dart"; import "package:inventree/widget/snacks.dart"; + Future confirmationDialog(String title, String text, {IconData icon = FontAwesomeIcons.questionCircle, String? acceptText, String? rejectText, Function? onAccept, Function? onReject}) async { String _accept = acceptText ?? L10().ok; @@ -50,30 +51,6 @@ Future confirmationDialog(String title, String text, {IconData icon = Font } -Future showInfoDialog(String title, String description, {IconData icon = FontAwesomeIcons.info, String? info, Function()? onDismissed}) async { - - String _info = info ?? L10().info; - - OneContext().showDialog( - builder: (BuildContext context) => SimpleDialog( - title: ListTile( - title: Text(_info), - leading: FaIcon(icon), - ), - children: [ - ListTile( - title: Text(title), - subtitle: Text(description) - ) - ] - ) - ).then((value) { - if (onDismissed != null) { - onDismissed(); - } - }); -} - Future showErrorDialog(String title, String description, {IconData icon = FontAwesomeIcons.exclamationCircle, String? error, Function? onDismissed}) async { String _error = error ?? L10().error; @@ -98,7 +75,19 @@ Future showErrorDialog(String title, String description, {IconData icon = }); } -Future showServerError(String title, String description) async { +/* + * Display a message indicating the nature of a server / API error + */ +Future showServerError(String url, String title, String description) async { + + if (!OneContext.hasContext) { + return; + } + + // We ignore error messages for certain URLs + if (url.contains("notifications")) { + return; + } if (title.isEmpty) { title = L10().serverError; @@ -126,7 +115,10 @@ Future showServerError(String title, String description) async { ); } -Future showStatusCodeError(int status) async { +/* + * Displays an error indicating that the server returned an unexpected status code + */ +Future showStatusCodeError(String url, int status) async { String msg = L10().responseInvalid; String extra = "${L10().statusCode}: ${status}"; @@ -173,68 +165,16 @@ Future showStatusCodeError(int status) async { } showServerError( + url, msg, extra, ); } -Future showTimeoutError() async { - await showServerError(L10().timeout, L10().noResponse); + +/* + * Displays a message indicating that the server timed out on a certain request + */ +Future showTimeoutError(String url) async { + await showServerError(url, L10().timeout, L10().noResponse); } - -void showFormDialog(String title, {String? acceptText, String? cancelText, GlobalKey? key, List? fields, Function? callback}) { - - - String _accept = acceptText ?? L10().save; - String _cancel = cancelText ?? L10().cancel; - - List _fields = fields ?? []; - - OneContext().showDialog( - builder: (BuildContext context) { - return AlertDialog( - title: Text(title), - actions: [ - TextButton( - child: Text(_cancel), - onPressed: () { - // Close the form - Navigator.pop(context); - } - ), - TextButton( - child: Text(_accept), - onPressed: () { - - var _key = key; - - if (_key != null && _key.currentState != null) { - if (_key.currentState!.validate()) { - _key.currentState!.save(); - - Navigator.pop(context); - - // Callback - if (callback != null) { - callback(); - } - } - } - } - ) - ], - content: Form( - key: key, - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: _fields - ) - ) - ) - ); - } - ); -} \ No newline at end of file