Improve error handling (#45)
continuous-integration/drone/push Build is passing Details

Improve error handling

Co-authored-by: Jonas Franz <info@jonasfranz.software>
Reviewed-on: #45
Reviewed-by: konrad <konrad@kola-entertainments.de>
This commit is contained in:
JonasFranz 2020-06-17 16:51:23 +00:00 committed by konrad
parent 6c0762d458
commit 8993999a68
4 changed files with 53 additions and 5 deletions

View File

@ -53,8 +53,15 @@ class Client {
dynamic _handleResponse(http.Response response) {
if (response.statusCode < 200 ||
response.statusCode > 400 ||
response.statusCode >= 400 ||
json == null) {
if (response.statusCode ~/ 100 == 4) {
Map<String, dynamic> error = _decoder.convert(response.body);
throw new InvalidRequestApiException(
response.statusCode,
response.request.url.toString(),
error["message"] ?? "Unknown Error");
}
throw new ApiException(
response.statusCode, response.request.url.toString());
}
@ -62,6 +69,17 @@ class Client {
}
}
class InvalidRequestApiException extends ApiException {
final String message;
InvalidRequestApiException(int errorCode, String path, this.message)
: super(errorCode, path);
@override
String toString() {
return this.message;
}
}
class ApiException implements Exception {
final int errorCode;
final String path;

View File

@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
class ErrorDialog extends StatelessWidget {
final dynamic error;
ErrorDialog({this.error});
@override
Widget build(BuildContext context) {
return AlertDialog(
content: Text(error.toString()),
actions: <Widget>[
FlatButton(
child: Text('Close'),
onPressed: () => Navigator.of(context).maybePop(),
)
],
);
}
}

View File

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:sentry/sentry.dart';
import 'package:vikunja_app/constants.dart';
@ -9,6 +10,11 @@ import 'package:vikunja_app/pages/user/login.dart';
import 'package:vikunja_app/theme/theme.dart';
void main() {
if (!kReleaseMode) {
// only log errors in release mode
_startApp();
return;
}
var sentry = new SentryClient(dsn: SENTRY_DSN);
FlutterError.onError = (details, {bool forceReport = false}) {
@ -26,9 +32,7 @@ void main() {
};
runZoned(
() => runApp(VikunjaGlobal(
child: new VikunjaApp(home: HomePage()),
login: new VikunjaApp(home: LoginPage()))),
_startApp,
onError: (Object error, StackTrace stackTrace) {
try {
sentry.captureException(
@ -44,6 +48,10 @@ void main() {
);
}
_startApp() => runApp(VikunjaGlobal(
child: new VikunjaApp(home: HomePage()),
login: new VikunjaApp(home: LoginPage())));
class VikunjaApp extends StatelessWidget {
final Widget home;

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:after_layout/after_layout.dart';
import 'package:vikunja_app/components/AddDialog.dart';
import 'package:vikunja_app/components/ErrorDialog.dart';
import 'package:vikunja_app/pages/namespace/namespace.dart';
import 'package:vikunja_app/pages/namespace/namespace_edit.dart';
import 'package:vikunja_app/pages/placeholder.dart';
@ -162,7 +163,8 @@ class HomePageState extends State<HomePage> with AfterLayoutMixin<HomePage> {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('The namespace was created successfully!'),
));
});
}).catchError((error) => showDialog(
context: context, builder: (context) => ErrorDialog(error: error)));
}
Future<void> _loadNamespaces() {