|
|
|
|
@ -2,10 +2,13 @@ import 'dart:async';
|
|
|
|
|
import 'dart:convert';
|
|
|
|
|
import 'dart:io';
|
|
|
|
|
|
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
|
import 'package:http/http.dart';
|
|
|
|
|
import 'package:http/io_client.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/app_state/app_state.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/classes/utils.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/config/routes.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/exceptions/api_exception.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/main.dart';
|
|
|
|
|
// ignore_for_file: avoid_annotating_with_dynamic
|
|
|
|
|
@ -13,18 +16,14 @@ import 'package:mohem_flutter_app/main.dart';
|
|
|
|
|
typedef FactoryConstructor<U> = U Function(dynamic);
|
|
|
|
|
|
|
|
|
|
class APIError {
|
|
|
|
|
int? errorCode;
|
|
|
|
|
dynamic errorCode;
|
|
|
|
|
int? errorType;
|
|
|
|
|
String? errorMessage;
|
|
|
|
|
int? errorStatusCode;
|
|
|
|
|
|
|
|
|
|
APIError(this.errorCode, this.errorMessage, this.errorType, this.errorStatusCode);
|
|
|
|
|
|
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
|
|
|
'errorCode': errorCode,
|
|
|
|
|
'errorMessage': errorMessage,
|
|
|
|
|
'errorType': errorType,
|
|
|
|
|
'ErrorStatusCode': errorStatusCode
|
|
|
|
|
};
|
|
|
|
|
Map<String, dynamic> toJson() => {'errorCode': errorCode, 'errorMessage': errorMessage, 'errorType': errorType, 'ErrorStatusCode': errorStatusCode};
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
String toString() {
|
|
|
|
|
@ -46,22 +45,22 @@ APIException _throwAPIException(Response response) {
|
|
|
|
|
APIError? apiError;
|
|
|
|
|
if (response.body != null && response.body.isNotEmpty) {
|
|
|
|
|
var jsonError = jsonDecode(response.body);
|
|
|
|
|
apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'],jsonError['ErrorStatusCode']);
|
|
|
|
|
apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'], jsonError['ErrorStatusCode']);
|
|
|
|
|
}
|
|
|
|
|
return APIException(APIException.BAD_REQUEST, error: apiError);
|
|
|
|
|
case 401:
|
|
|
|
|
return APIException(APIException.UNAUTHORIZED);
|
|
|
|
|
return const APIException(APIException.UNAUTHORIZED);
|
|
|
|
|
case 403:
|
|
|
|
|
return APIException(APIException.FORBIDDEN);
|
|
|
|
|
return const APIException(APIException.FORBIDDEN);
|
|
|
|
|
case 404:
|
|
|
|
|
return APIException(APIException.NOT_FOUND);
|
|
|
|
|
return const APIException(APIException.NOT_FOUND);
|
|
|
|
|
case 500:
|
|
|
|
|
return APIException(APIException.INTERNAL_SERVER_ERROR);
|
|
|
|
|
return const APIException(APIException.INTERNAL_SERVER_ERROR);
|
|
|
|
|
case 444:
|
|
|
|
|
var downloadUrl = response.headers["location"];
|
|
|
|
|
return APIException(APIException.UPGRADE_REQUIRED, arguments: downloadUrl);
|
|
|
|
|
default:
|
|
|
|
|
return APIException(APIException.OTHER);
|
|
|
|
|
return const APIException(APIException.OTHER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -72,8 +71,16 @@ class ApiClient {
|
|
|
|
|
|
|
|
|
|
factory ApiClient() => _instance;
|
|
|
|
|
|
|
|
|
|
Future<U> postJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, T jsonObject,
|
|
|
|
|
{String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false}) async {
|
|
|
|
|
Future<U> postJsonForObject<T, U>(
|
|
|
|
|
FactoryConstructor<U> factoryConstructor,
|
|
|
|
|
String url,
|
|
|
|
|
T jsonObject, {
|
|
|
|
|
String? token,
|
|
|
|
|
Map<String, dynamic>? queryParameters,
|
|
|
|
|
Map<String, String>? headers,
|
|
|
|
|
int retryTimes = 0,
|
|
|
|
|
bool isFormData = false,
|
|
|
|
|
}) async {
|
|
|
|
|
var _headers = {'Accept': 'application/json'};
|
|
|
|
|
if (headers != null && headers.isNotEmpty) {
|
|
|
|
|
_headers.addAll(headers);
|
|
|
|
|
@ -102,6 +109,9 @@ class ApiClient {
|
|
|
|
|
|
|
|
|
|
if (jsonData["ErrorMessage"] == null) {
|
|
|
|
|
return factoryConstructor(jsonData);
|
|
|
|
|
} else if (jsonData["MessageStatus"] == 2 && jsonData["IsOTPMaxLimitExceed"] == true) {
|
|
|
|
|
await Utils.performLogout(AppRoutes.navigatorKey.currentContext, null);
|
|
|
|
|
throw const APIException(APIException.UNAUTHORIZED, error: null);
|
|
|
|
|
} else {
|
|
|
|
|
APIError? apiError;
|
|
|
|
|
apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage'], jsonData['ErrorType'] ?? 0, jsonData['ErrorStatusCode']);
|
|
|
|
|
@ -116,8 +126,15 @@ class ApiClient {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<Response> postJsonForResponse<T>(String url, T jsonObject,
|
|
|
|
|
{String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false}) async {
|
|
|
|
|
Future<Response> postJsonForResponse<T>(
|
|
|
|
|
String url,
|
|
|
|
|
T jsonObject, {
|
|
|
|
|
String? token,
|
|
|
|
|
Map<String, dynamic>? queryParameters,
|
|
|
|
|
Map<String, String>? headers,
|
|
|
|
|
int retryTimes = 0,
|
|
|
|
|
bool isFormData = false,
|
|
|
|
|
}) async {
|
|
|
|
|
String? requestBody;
|
|
|
|
|
late Map<String, String> stringObj;
|
|
|
|
|
if (jsonObject != null) {
|
|
|
|
|
@ -152,9 +169,9 @@ class ApiClient {
|
|
|
|
|
var queryString = new Uri(queryParameters: queryParameters).query;
|
|
|
|
|
url = url + '?' + queryString;
|
|
|
|
|
}
|
|
|
|
|
var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 120));
|
|
|
|
|
var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(const Duration(seconds: 120));
|
|
|
|
|
|
|
|
|
|
if (response. statusCode >= 200 && response.statusCode < 300) {
|
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
|
|
|
return response;
|
|
|
|
|
} else {
|
|
|
|
|
throw _throwAPIException(response);
|
|
|
|
|
@ -162,7 +179,7 @@ class ApiClient {
|
|
|
|
|
} on SocketException catch (e) {
|
|
|
|
|
if (retryTimes > 0) {
|
|
|
|
|
print('will retry after 3 seconds...');
|
|
|
|
|
await Future.delayed(Duration(seconds: 3));
|
|
|
|
|
await Future.delayed(const Duration(seconds: 3));
|
|
|
|
|
return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
|
|
|
|
|
} else {
|
|
|
|
|
throw APIException(APIException.OTHER, arguments: e);
|
|
|
|
|
@ -170,7 +187,7 @@ class ApiClient {
|
|
|
|
|
} on HttpException catch (e) {
|
|
|
|
|
if (retryTimes > 0) {
|
|
|
|
|
print('will retry after 3 seconds...');
|
|
|
|
|
await Future.delayed(Duration(seconds: 3));
|
|
|
|
|
await Future.delayed(const Duration(seconds: 3));
|
|
|
|
|
return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
|
|
|
|
|
} else {
|
|
|
|
|
throw APIException(APIException.OTHER, arguments: e);
|
|
|
|
|
@ -180,7 +197,7 @@ class ApiClient {
|
|
|
|
|
} on ClientException catch (e) {
|
|
|
|
|
if (retryTimes > 0) {
|
|
|
|
|
print('will retry after 3 seconds...');
|
|
|
|
|
await Future.delayed(Duration(seconds: 3));
|
|
|
|
|
await Future.delayed(const Duration(seconds: 3));
|
|
|
|
|
return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
|
|
|
|
|
} else {
|
|
|
|
|
throw APIException(APIException.OTHER, arguments: e);
|
|
|
|
|
@ -219,7 +236,7 @@ class ApiClient {
|
|
|
|
|
var queryString = new Uri(queryParameters: queryParameters).query;
|
|
|
|
|
url = url + '?' + queryString;
|
|
|
|
|
}
|
|
|
|
|
var response = await _get(Uri.parse(url), headers: _headers).timeout(Duration(seconds: 60));
|
|
|
|
|
var response = await _get(Uri.parse(url), headers: _headers).timeout(const Duration(seconds: 60));
|
|
|
|
|
|
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
|
|
|
return response;
|
|
|
|
|
@ -229,7 +246,7 @@ class ApiClient {
|
|
|
|
|
} on SocketException catch (e) {
|
|
|
|
|
if (retryTimes > 0) {
|
|
|
|
|
print('will retry after 3 seconds...');
|
|
|
|
|
await Future.delayed(Duration(seconds: 3));
|
|
|
|
|
await Future.delayed(const Duration(seconds: 3));
|
|
|
|
|
return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
|
|
|
|
|
} else {
|
|
|
|
|
throw APIException(APIException.OTHER, arguments: e);
|
|
|
|
|
@ -237,7 +254,7 @@ class ApiClient {
|
|
|
|
|
} on HttpException catch (e) {
|
|
|
|
|
if (retryTimes > 0) {
|
|
|
|
|
print('will retry after 3 seconds...');
|
|
|
|
|
await Future.delayed(Duration(seconds: 3));
|
|
|
|
|
await Future.delayed(const Duration(seconds: 3));
|
|
|
|
|
return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
|
|
|
|
|
} else {
|
|
|
|
|
throw APIException(APIException.OTHER, arguments: e);
|
|
|
|
|
@ -247,7 +264,7 @@ class ApiClient {
|
|
|
|
|
} on ClientException catch (e) {
|
|
|
|
|
if (retryTimes > 0) {
|
|
|
|
|
print('will retry after 3 seconds...');
|
|
|
|
|
await Future.delayed(Duration(seconds: 3));
|
|
|
|
|
await Future.delayed(const Duration(seconds: 3));
|
|
|
|
|
return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
|
|
|
|
|
} else {
|
|
|
|
|
throw APIException(APIException.OTHER, arguments: e);
|
|
|
|
|
|