1
0
mirror of https://github.com/go-vikunja/app synced 2024-06-02 18:49:47 +00:00
app-mirror-github/lib/api/client.dart

215 lines
6.4 KiB
Dart
Raw Normal View History

2018-09-17 13:35:57 +00:00
import 'dart:async';
import 'dart:convert';
import 'dart:core';
import 'dart:io';
import 'package:flutter/material.dart';
2018-09-17 13:35:57 +00:00
import 'package:http/http.dart' as http;
2021-06-04 09:34:25 +00:00
import 'package:vikunja_app/api/response.dart';
import 'package:vikunja_app/components/string_extension.dart';
import 'package:vikunja_app/global.dart';
2018-09-17 13:35:57 +00:00
2022-08-24 21:45:12 +00:00
import '../main.dart';
class Client {
2023-05-16 19:08:58 +00:00
GlobalKey<ScaffoldMessengerState>? global_scaffold_key;
2018-09-17 13:35:57 +00:00
final JsonDecoder _decoder = new JsonDecoder();
final JsonEncoder _encoder = new JsonEncoder();
2022-09-03 15:43:16 +00:00
String _token = '';
String _base = '';
2022-08-26 05:49:43 +00:00
bool authenticated = false;
bool ignoreCertificates = false;
bool showSnackBar = true;
2018-09-17 13:35:57 +00:00
2022-09-03 15:43:16 +00:00
String get base => _base;
String get token => _token;
2022-08-26 05:49:43 +00:00
String? post_body;
bool operator ==(dynamic otherClient) {
return otherClient._token == _token;
}
2023-05-16 23:22:59 +00:00
Client(this.global_scaffold_key,
{String? token, String? base, bool authenticated = false}) {
configure(token: token, base: base, authenticated: authenticated);
}
2022-08-27 21:04:43 +00:00
void reload_ignore_certs(bool? val) {
ignoreCertificates = val ?? false;
2022-08-24 21:45:12 +00:00
HttpOverrides.global = new IgnoreCertHttpOverrides(ignoreCertificates);
if (global_scaffold_key == null ||
global_scaffold_key!.currentContext == null) return;
VikunjaGlobal.of(global_scaffold_key!.currentContext!)
.settingsManager
.setIgnoreCertificates(ignoreCertificates);
2022-08-24 21:45:12 +00:00
}
get _headers => {
2022-09-03 15:43:16 +00:00
'Authorization': _token != '' ? 'Bearer $_token' : '',
2023-05-16 20:11:45 +00:00
'Content-Type': 'application/json',
'User-Agent': 'Vikunja Mobile App'
2018-09-17 13:35:57 +00:00
};
get headers => _headers;
@override
int get hashCode => _token.hashCode;
2022-08-26 05:49:43 +00:00
void configure({String? token, String? base, bool? authenticated}) {
if (token != null) _token = token;
if (base != null) {
base = base.replaceAll(" ", "");
if (base.endsWith("/")) base = base.substring(0, base.length - 1);
2022-08-27 21:04:43 +00:00
_base = base.endsWith('/api/v1') ? base : '$base/api/v1';
}
if (authenticated != null) this.authenticated = authenticated;
}
void reset() {
2022-09-03 15:43:16 +00:00
_token = _base = '';
authenticated = false;
}
Future<Response?> get(String url,
2022-08-26 05:49:43 +00:00
[Map<String, List<String>>? queryParameters]) {
Uri uri = Uri.tryParse('${this.base}$url')!;
// why are we doing it like this? because Uri doesnt have setters. wtf.
uri = Uri(
scheme: uri.scheme,
userInfo: uri.userInfo,
host: uri.host,
port: uri.port,
path: uri.path,
//queryParameters: {...uri.queryParameters, ...?queryParameters},
queryParameters: queryParameters,
fragment: uri.fragment);
return http
.get(uri, headers: _headers)
.then(_handleResponse)
.onError((error, stackTrace) => _handleError(error, stackTrace));
2022-08-24 21:45:12 +00:00
}
2018-09-17 13:35:57 +00:00
Future<Response?> delete(String url) {
return http
.delete(
'${this.base}$url'.toUri()!,
headers: _headers,
)
.then(_handleResponse)
.onError((error, stackTrace) => _handleError(error, stackTrace));
}
Future<Response?> post(String url, {dynamic body}) {
return http
.post(
'${this.base}$url'.toUri()!,
headers: _headers,
body: _encoder.convert(body),
)
.then(_handleResponse)
.onError((error, stackTrace) => _handleError(error, stackTrace));
2018-09-17 13:35:57 +00:00
}
Future<Response?> put(String url, {dynamic body}) {
return http
.put(
'${this.base}$url'.toUri()!,
headers: _headers,
body: _encoder.convert(body),
)
.then(_handleResponse)
.onError((error, stackTrace) => _handleError(error, stackTrace));
}
Response? _handleError(Object? e, StackTrace? st) {
if (global_scaffold_key == null) return null;
2022-08-24 21:45:12 +00:00
SnackBar snackBar = SnackBar(
content: Text("Error on request: " + e.toString()),
action: SnackBarAction(
label: "Clear",
onPressed: () => global_scaffold_key!.currentState?.clearSnackBars()),
);
2023-05-16 19:08:58 +00:00
global_scaffold_key!.currentState?.showSnackBar(snackBar);
2023-05-16 20:11:45 +00:00
return null;
}
2022-08-24 21:45:12 +00:00
Map<String, String> headersToMap(HttpHeaders headers) {
Map<String, String> map = {};
headers.forEach((name, values) {
map[name] = values[0].toString();
});
return map;
}
2023-05-16 19:08:58 +00:00
Error? _handleResponseErrors(http.Response response) {
if (response.statusCode < 200 || response.statusCode >= 400) {
2022-08-08 20:23:34 +00:00
Map<String, dynamic> error;
error = _decoder.convert(response.body);
2023-05-16 19:08:58 +00:00
final SnackBar snackBar = SnackBar(
content:
Text("Error code " + response.statusCode.toString() + " received."),
action: globalNavigatorKey.currentContext == null
? null
: SnackBarAction(
label: ("Details"),
onPressed: () {
showDialog(
context: globalNavigatorKey.currentContext!,
builder: (BuildContext context) => 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_scaffold_key != null && showSnackBar)
2023-05-16 19:08:58 +00:00
global_scaffold_key!.currentState?.showSnackBar(snackBar);
else
print("error on request: ${error["message"]}");
2018-09-17 13:35:57 +00:00
}
2023-05-16 19:08:58 +00:00
return null;
2018-09-17 13:35:57 +00:00
}
Response? _handleResponse(http.Response response) {
2023-05-16 19:08:58 +00:00
Error? error = _handleResponseErrors(response);
return Response(
_decoder.convert(response.body), response.statusCode, response.headers);
}
2018-09-17 13:35:57 +00:00
}
class InvalidRequestApiException extends ApiException {
final String message;
2021-06-04 09:34:25 +00:00
InvalidRequestApiException(int errorCode, String path, this.message)
: super(errorCode, path);
@override
String toString() {
return this.message;
}
}
2018-09-17 13:35:57 +00:00
class ApiException implements Exception {
final int errorCode;
final String path;
2021-06-04 09:34:25 +00:00
2018-09-17 13:35:57 +00:00
ApiException(this.errorCode, this.path);
@override
String toString() {
return "Can't fetch data from server. (Error-Code: $errorCode)";
}
}