diff --git a/lib/api.dart b/lib/api.dart index 51a414c3..e69f7564 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -332,10 +332,6 @@ class InvenTreeAPI { if (!address.endsWith("/")) { address = address + "/"; } - /* TODO: Better URL validation - * - If not a valid URL, return error - * - If no port supplied, append a default port - */ _BASE_URL = address; diff --git a/lib/barcode.dart b/lib/barcode.dart index 4fd23f38..8781f2d1 100644 --- a/lib/barcode.dart +++ b/lib/barcode.dart @@ -77,7 +77,7 @@ class BarcodeHandler { body: { "barcode": barcode, }, - expectedStatusCode: 200 + expectedStatusCode: null, // Do not show an error on "unexpected code" ); _controller?.resumeCamera(); @@ -90,7 +90,7 @@ class BarcodeHandler { // We want to know about this one! await sentryReportMessage( - "BarcodeHandler.processBarcode returned strange value", + "BarcodeHandler.processBarcode returned unexpected value", context: { "data": response.data?.toString() ?? "null", "barcode": barcode, @@ -99,9 +99,10 @@ class BarcodeHandler { "valid": response.isValid().toString(), "error": response.error, "errorDetail": response.errorDetail, + "overlayText": getOverlayText(context), } ); - } else if (data.containsKey("error")) { + } else if ((response.statusCode >= 400) || data.containsKey("error")) { onBarcodeUnknown(context, data); } else if (data.containsKey("success")) { onBarcodeMatched(context, data); diff --git a/lib/inventree/model.dart b/lib/inventree/model.dart index 1d13d175..decb7aaa 100644 --- a/lib/inventree/model.dart +++ b/lib/inventree/model.dart @@ -233,6 +233,32 @@ class InvenTreeModel { return {}; } + Future reportModelError(String title, APIResponse response, {Map context = const {}}) async { + + String dataString = response.data?.toString() ?? "null"; + + if (dataString.length > 500) { + dataString = dataString.substring(0, 500); + } + + // Add some default context data + + context["url"] = response.url.toString(); + context["statusCode"] = response.statusCode.toString(); + context["responseData"] = dataString; + context["valid"] = response.isValid().toString(); + context["error"] = response.error; + context["errorDetail"] = response.errorDetail; + context["isNull"] = response.data == null ? "true" : "false"; + context["dataType"] = response.data?.runtimeType.toString() ?? "null"; + context["model"] = URL; + + await sentryReportMessage( + title, + context: context, + ); + } + /// Delete the instance on the remote server /// Returns true if the operation was successful, else false Future delete() async { @@ -240,18 +266,10 @@ class InvenTreeModel { if (!response.isValid() || response.data == null || (response.data is! Map)) { - if (response.statusCode > 0) { - await sentryReportMessage( - "InvenTreeModel.delete() returned invalid response", - context: { - "url": url, - "statusCode": response.statusCode.toString(), - "data": response.data?.toString() ?? "null", - "error": response.error, - "errorDetail": response.errorDetail, - } - ); - } + reportModelError( + "InvenTreeModel.delete() returned invalid response", + response, + ); showServerError( L10().serverError, @@ -274,20 +292,13 @@ class InvenTreeModel { if (!response.isValid() || response.data == null || (response.data is! Map)) { - // Report error - if (response.statusCode > 0) { - await sentryReportMessage( - "InvenTreeModel.reload() returned invalid response", - context: { - "url": url, - "statusCode": response.statusCode.toString(), - "data": response.data?.toString() ?? "null", - "valid": response.isValid().toString(), - "error": response.error, - "errorDetail": response.errorDetail, - }, - ); - } + reportModelError( + "InvenTreeModel.reload() returned invalid response", + response, + context: { + "pk": pk.toString(), + } + ); showServerError( L10().serverError, @@ -347,19 +358,15 @@ class InvenTreeModel { if (!response.isValid() || response.data == null || response.data is! Map) { - if (response.statusCode > 0) { - await sentryReportMessage( - "InvenTreeModel.get() returned invalid response", - context: { - "url": url, - "statusCode": response.statusCode.toString(), - "data": response.data?.toString() ?? "null", - "valid": response.isValid().toString(), - "error": response.error, - "errorDetail": response.errorDetail, - } - ); - } + // Report error + reportModelError( + "InvenTreeModel.getModel() returned invalid response", + response, + context: { + "filters": filters.toString(), + "pk": pk, + } + ); showServerError( L10().serverError, @@ -394,26 +401,19 @@ class InvenTreeModel { // Invalid response returned from server if (!response.isValid() || response.data == null || response.data is! Map) { - if (response.statusCode > 0) { - await sentryReportMessage( - "InvenTreeModel.create() returned invalid response", - context: { - "url": url, - "statusCode": response.statusCode.toString(), - "data": response.data?.toString() ?? "null", - "valid": response.isValid().toString(), - "error": response.error, - "errorDetail": response.errorDetail, - } - ); - } + reportModelError( + "InvenTreeModel.create() returned invalid response", + response, + context: { + "pk": pk.toString(), + } + ); showServerError( L10().serverError, L10().errorCreate, ); - return null; } diff --git a/lib/settings/login.dart b/lib/settings/login.dart index 5c29e162..a998af41 100644 --- a/lib/settings/login.dart +++ b/lib/settings/login.dart @@ -240,6 +240,8 @@ class _ProfileEditState extends State { String username = ""; String password = ""; + bool _obscured = true; + @override Widget build(BuildContext context) { return Scaffold( @@ -379,10 +381,18 @@ class _ProfileEditState extends State { labelText: L10().password, labelStyle: TextStyle(fontWeight: FontWeight.bold), hintText: L10().enterPassword, + suffixIcon: IconButton( + icon: _obscured ? FaIcon(FontAwesomeIcons.eye) : FaIcon(FontAwesomeIcons.solidEyeSlash), + onPressed: () { + setState(() { + _obscured = !_obscured; + }); + }, + ), ), initialValue: profile?.password ?? "", keyboardType: TextInputType.visiblePassword, - obscureText: true, + obscureText: _obscured, onSaved: (value) { password = value ?? ""; }, diff --git a/lib/widget/home.dart b/lib/widget/home.dart index 23153a89..64c566de 100644 --- a/lib/widget/home.dart +++ b/lib/widget/home.dart @@ -180,6 +180,10 @@ class _InvenTreeHomePageState extends State { */ Future _refreshNotifications() async { + if (!InvenTreeAPI().isConnected()) { + return; + } + final notifications = await InvenTreeNotification().list(); setState(() { diff --git a/lib/widget/submit_feedback.dart b/lib/widget/submit_feedback.dart deleted file mode 100644 index 34392926..00000000 --- a/lib/widget/submit_feedback.dart +++ /dev/null @@ -1,90 +0,0 @@ -import "package:flutter/material.dart"; -import "package:font_awesome_flutter/font_awesome_flutter.dart"; -import "package:inventree/inventree/sentry.dart"; -import "package:inventree/widget/snacks.dart"; - -import "package:inventree/l10.dart"; - -class SubmitFeedbackWidget extends StatefulWidget { - - @override - _SubmitFeedbackState createState() => _SubmitFeedbackState(); - -} - - -class _SubmitFeedbackState extends State { - - final _formkey = GlobalKey(); - - String message = ""; - - @override - Widget build(BuildContext context) { - - return Scaffold( - appBar: AppBar( - title: Text(L10().submitFeedback), - actions: [ - IconButton( - icon: FaIcon(FontAwesomeIcons.paperPlane), - onPressed: () async { - if (_formkey.currentState!.validate()) { - _formkey.currentState!.save(); - - // Upload - bool result = await sentryReportMessage(message); - - if (result) { - showSnackIcon( - L10().feedbackSuccess, - success: true, - ); - } else { - showSnackIcon( - L10().feedbackError, - success: false - ); - } - - // Exit - Navigator.of(context).pop(); - } - }, - ) - ], - ), - body: Form( - key: _formkey, - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextFormField( - decoration: InputDecoration( - labelText: L10().feedback, - labelStyle: TextStyle(fontWeight: FontWeight.bold), - ), - maxLines: null, - keyboardType: TextInputType.multiline, - validator: (value) { - if (value == null || value.trim().isEmpty) { - return L10().valueCannotBeEmpty; - } - - return null; - }, - onSaved: (value) { - if (value != null) { - message = value; - } - }, - ), - ], - ) - ) - ) - ); - } - -} \ No newline at end of file