1
0
mirror of https://github.com/go-vikunja/app synced 2024-05-29 00:36:49 +00:00

added proper error management

This commit is contained in:
Benimautner 2023-05-16 21:08:58 +02:00
parent 0ab24284f6
commit bf28b57525
5 changed files with 47 additions and 57 deletions

View File

@ -12,7 +12,8 @@ import '../main.dart';
class Client {
GlobalKey<ScaffoldMessengerState>? global;
GlobalKey<ScaffoldMessengerState>? global_scaffold_key;
GlobalKey<NavigatorState>? navigator_key;
final JsonDecoder _decoder = new JsonDecoder();
final JsonEncoder _encoder = new JsonEncoder();
String _token = '';
@ -31,7 +32,7 @@ class Client {
return otherClient._token == _token;
}
Client(this.global,
Client(this.global_scaffold_key, this.navigator_key,
{String? token, String? base, bool authenticated = false}) {
configure(token: token, base: base, authenticated: authenticated);
}
@ -39,9 +40,9 @@ class Client {
void reload_ignore_certs(bool? val) {
ignoreCertificates = val ?? false;
HttpOverrides.global = new IgnoreCertHttpOverrides(ignoreCertificates);
if(global == null || global!.currentContext == null) return;
if(global_scaffold_key == null || global_scaffold_key!.currentContext == null) return;
VikunjaGlobal
.of(global!.currentContext!)
.of(global_scaffold_key!.currentContext!)
.settingsManager
.setIgnoreCertificates(ignoreCertificates);
}
@ -77,7 +78,8 @@ class Client {
Future<Response?> get(String url,
[Map<String, List<String>>? queryParameters]) {
return http.get('${this.base}$url'.toUri()!, headers: _headers)
.then(_handleResponse).catchError((Object? obj) {print(obj);});
.then(_handleResponse).onError((error, stackTrace) =>
_handleError(error, stackTrace));
}
Future<Response?> delete(String url) {
@ -111,11 +113,11 @@ class Client {
}
Response? _handleError(Object? e, StackTrace? st) {
if(global == null) return null;
if(global_scaffold_key == null) return null;
SnackBar snackBar = SnackBar(
content: Text("Error on request: " + e.toString()),
action: SnackBarAction(label: "Clear", onPressed: () => global!.currentState?.clearSnackBars()),);
global!.currentState?.showSnackBar(snackBar);
action: SnackBarAction(label: "Clear", onPressed: () => global_scaffold_key!.currentState?.clearSnackBars()),);
global_scaffold_key!.currentState?.showSnackBar(snackBar);
}
Map<String, String> headersToMap(HttpHeaders headers) {
@ -126,69 +128,50 @@ class Client {
return map;
}
/*
Future<Response> _handleResponseF(HttpClientRequest request) {
_headers.forEach((k, v) => request.headers.set(k, v));
if(post_body != "") {
request.write(post_body);
post_body = "";
}
return request.close().then((response) {
final completer = Completer<String>();
final contents = StringBuffer();
response.transform(utf8.decoder).listen((data) {
contents.write(data);
}, onDone: () => completer.complete(contents.toString()));
return completer.future.then((body) {
Response res = Response(json.decode(body), response.statusCode, headersToMap(response.headers));
_handleResponseErrors(res);
return res;
});
});
//return Response(body, statusCode, headers)
}*/
void _handleResponseErrors(http.Response response) {
Error? _handleResponseErrors(http.Response response) {
if(response.statusCode == 412)
return;
return Error("Login failed!");
if (response.statusCode < 200 ||
response.statusCode >= 400) {
Map<String, dynamic> error;
error = _decoder.convert(response.body);
if (response.statusCode ~/ 100 == 4) {
/*throw new InvalidRequestApiException(
response.statusCode,
"",
error["message"] ?? "Unknown Error");
*/
}
final SnackBar snackBar = SnackBar(
content: Text(
"Error code " + response.statusCode.toString() + " received."),
action: SnackBarAction(
label: ("Show Details"),
label: ("Details"),
onPressed: () {
Builder(
showDialog(
context: navigator_key!.currentContext!,
builder: (BuildContext context) =>
Dialog(
child: Text(error["message"]),
AlertDialog(
title: Text("Error ${response.statusCode}"),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text("Message: ${error["message"]}", textAlign: TextAlign.start,),
Text("Url: ${response.request!.url.toString()}"),
],
)
)
);
},
),
);
if(global != null)
global!.currentState?.showSnackBar(snackBar);
if(global_scaffold_key != null)
global_scaffold_key!.currentState?.showSnackBar(snackBar);
else
print("error on request: ${error["message"]}");
}
return null;
}
Response? _handleResponse(http.Response response) {
_handleResponseErrors(response);
Error? error = _handleResponseErrors(response);
return Response(
_decoder.convert(response.body), response.statusCode, response.headers);
}

View File

@ -1,10 +1,16 @@
// This is a wrapper class to be able to return the headers up to the provider
// to properly handle things like pagination with it.
class Error {
Error(this.message);
final String message;
}
class Response {
Response(this.body, this.statusCode, this.headers, {this.error = false});
Response(this.body, this.statusCode, this.headers, {this.error});
final dynamic body;
final int statusCode;
final Map<String, String> headers;
final bool error;
final Error? error;
}

View File

@ -20,7 +20,7 @@ class UserAPIService extends APIService implements UserService {
}
var response = await client.post('/login', body: body);
var token = response?.body["token"];
if(token == null || response == null || response.error)
if(token == null || response == null || response.error != null)
return Future.value(UserTokenPair(null, null,
error: response != null ? response.body["code"] : 0,
errorString: response != null ? response.body["message"] : "Login error"));

View File

@ -52,8 +52,9 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
Client get client => _client;
final GlobalKey<ScaffoldMessengerState> snackbarKey =
GlobalKey<ScaffoldMessengerState>();
final snackbarKey = GlobalKey<ScaffoldMessengerState>();
final navigatorKey = GlobalKey<NavigatorState>();
UserManager get userManager => new UserManager(_storage);
@ -104,7 +105,7 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
@override
void initState() {
super.initState();
_client = Client(snackbarKey);
_client = Client(snackbarKey, navigatorKey);
settingsManager.getIgnoreCertificates().then((value) => client.reload_ignore_certs(value == "1"));
_newUserService = UserAPIService(client);
_loadCurrentUser();
@ -148,8 +149,8 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
void logoutUser(BuildContext context) async {
// _storage.deleteAll().then((_) {
var userId = await _storage.read(key: "currentUser");
_storage.delete(key: userId!); //delete token
_storage.delete(key: "${userId}_base");
await _storage.delete(key: userId!); //delete token
await _storage.delete(key: "${userId}_base");
Navigator.pop(context);
setState(() {
client.reset();
@ -157,7 +158,7 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
});
/* }).catchError((err) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('An error occured while logging out!'),
content: Text('An error occurred while logging out!'),
));
});*/
}

View File

@ -34,7 +34,7 @@ void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
print("Native called background task: $task"); //simpleTask will be emitted here.
if (task == "update-tasks" && inputData != null) {
Client client = Client(null,
Client client = Client(null, null,
token: inputData["client_token"],
base: inputData["client_base"],
authenticated: true);