651 lines
20 KiB
Dart
651 lines
20 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:developer';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:onufitness/constants/api_endpoints.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:file_picker/file_picker.dart';
|
|
import 'package:onufitness/controller/update_acces_token_controller.dart';
|
|
import 'package:onufitness/routes/route_constant.dart';
|
|
import 'package:onufitness/services/local_storage_services/shared_services.dart';
|
|
import 'package:http_parser/http_parser.dart';
|
|
import 'package:mime/mime.dart';
|
|
import 'package:onufitness/services/notification_services/notification_service.dart';
|
|
|
|
class ApiBase {
|
|
static void handleAccountDeleted() {
|
|
Get.defaultDialog(
|
|
title: "Account Deactivated",
|
|
middleText:
|
|
"Your account has been deactivated by the administrator. You will now be logged out.",
|
|
textConfirm: "OK",
|
|
confirmTextColor: Colors.white,
|
|
barrierDismissible: false,
|
|
onConfirm: () async {
|
|
await SharedServices.logout();
|
|
await NotificationService().deleteDeviceToken();
|
|
Get.offNamedUntil(RouteConstant.loginFirstScreen, (route) => false);
|
|
},
|
|
);
|
|
}
|
|
|
|
//.............................................................................
|
|
static url({required String extendedURL}) {
|
|
log("${ApiUrl.baseUrl}$extendedURL");
|
|
return Uri.parse("${ApiUrl.baseUrl}$extendedURL");
|
|
}
|
|
|
|
//.............................................................................
|
|
static Future<http.Response> getRequest({
|
|
required String extendedURL,
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
}) async {
|
|
var client = http.Client();
|
|
Map<String, String> newHeaders = {};
|
|
Map<String, String> contentType = {'Content-Type': 'application/json'};
|
|
newHeaders.addAll(contentType);
|
|
|
|
// Add the Authorization header if needed
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
|
|
}
|
|
|
|
log("URL : ${ApiUrl.baseUrl}$extendedURL");
|
|
|
|
http.Response response = await client.get(
|
|
url(extendedURL: extendedURL.trim()),
|
|
headers: sendHeaders ? newHeaders : null,
|
|
);
|
|
|
|
// It Token Expired, then api call for update the token.....................
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return getRequest(
|
|
extendedURL: extendedURL,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
);
|
|
}
|
|
}
|
|
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
//.............................................................................
|
|
static Future<http.Response> postRequest({
|
|
required String extendedURL,
|
|
required Object body,
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
}) async {
|
|
var client = http.Client();
|
|
|
|
Map<String, String> newHeaders = {};
|
|
Map<String, String> contentType = {'Content-Type': 'application/json'};
|
|
|
|
newHeaders.addAll(contentType);
|
|
|
|
// Add the Authorization header if needed
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
|
|
}
|
|
log("URL : ${ApiUrl.baseUrl}$extendedURL");
|
|
|
|
http.Response response = await client.post(
|
|
url(extendedURL: extendedURL),
|
|
headers: newHeaders, // Always send headers for POST requests
|
|
body: jsonEncode(body),
|
|
);
|
|
|
|
// It Token Expired, then api call for update the token.....................
|
|
// 401 is the status code of UnAuthorize user................................
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return postRequest(
|
|
extendedURL: extendedURL,
|
|
body: body,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
);
|
|
}
|
|
}
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
return response;
|
|
}
|
|
|
|
//.............................................................................
|
|
static Future<http.Response> putRequest({
|
|
required String extendedURL,
|
|
required Object body,
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
}) async {
|
|
var client = http.Client();
|
|
|
|
Map<String, String> newHeaders = {};
|
|
Map<String, String> contentType = {'Content-Type': 'application/json'};
|
|
newHeaders.addAll(contentType);
|
|
|
|
// Add the Authorization header if needed
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
|
|
}
|
|
log("URL : ${ApiUrl.baseUrl}$extendedURL");
|
|
|
|
http.Response response = await client.put(
|
|
url(extendedURL: extendedURL),
|
|
headers: newHeaders, // Always send headers for PUT requests
|
|
body: jsonEncode(body),
|
|
);
|
|
|
|
// It Token Expired, then api call for update the token.....................
|
|
// 401 is the status code of UnAuthorize user................................
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return putRequest(
|
|
extendedURL: extendedURL,
|
|
body: body,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
);
|
|
}
|
|
}
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
return response;
|
|
}
|
|
|
|
//.............................................................................
|
|
static Future<http.Response> patchRequest({
|
|
required String extendedURL,
|
|
Object? body,
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
}) async {
|
|
var client = http.Client();
|
|
Map<String, String> newHeaders = {};
|
|
Map<String, String> contentType = {'Content-Type': 'application/json'};
|
|
newHeaders.addAll(contentType);
|
|
|
|
// Add the Authorization header if needed
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
|
|
}
|
|
log("URL : ${ApiUrl.baseUrl}$extendedURL");
|
|
|
|
http.Response response = await client.patch(
|
|
url(extendedURL: extendedURL),
|
|
headers: newHeaders, // Always send headers for Patch requests
|
|
body: jsonEncode(body),
|
|
);
|
|
|
|
// It Token Expired, then api call for update the token.....................
|
|
// 401 is the status code of UnAuthorize user................................
|
|
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return patchRequest(
|
|
extendedURL: extendedURL,
|
|
body: body,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
);
|
|
}
|
|
}
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
return response;
|
|
}
|
|
|
|
//.............................................................................
|
|
static Future<http.Response> deleteRequest({
|
|
required String extendedURL,
|
|
required Object body,
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
}) async {
|
|
var client = http.Client();
|
|
Map<String, String> newHeaders = {};
|
|
Map<String, String> contentType = {'Content-Type': 'application/json'};
|
|
newHeaders.addAll(contentType);
|
|
|
|
// Add the Authorization header if needed
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
|
|
}
|
|
log("URL : ${ApiUrl.baseUrl}$extendedURL");
|
|
|
|
http.Response response = await client.delete(
|
|
url(extendedURL: extendedURL),
|
|
headers: newHeaders, // Always send headers for Delete requests
|
|
body: jsonEncode(body),
|
|
);
|
|
|
|
// It Token Expired, then api call for update the token.....................
|
|
// 401 is the status code of UnAuthorize user................................
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return deleteRequest(
|
|
extendedURL: extendedURL,
|
|
body: body,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
);
|
|
}
|
|
}
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
return response;
|
|
}
|
|
|
|
//.............................................................................
|
|
static Future<http.Response> postSingleFileRequest({
|
|
required String extendedURL,
|
|
required XFile file,
|
|
Map<String, dynamic>? body,
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
required String fileNameKey,
|
|
}) async {
|
|
try {
|
|
final uri = url(extendedURL: extendedURL);
|
|
var request = http.MultipartRequest('POST', uri);
|
|
Map<String, String> newHeaders = {};
|
|
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
|
|
}
|
|
|
|
request.headers.addAll(newHeaders);
|
|
|
|
if (body != null) {
|
|
request.fields.addAll(
|
|
body.map((key, value) => MapEntry(key, value.toString())),
|
|
);
|
|
}
|
|
request.files.add(
|
|
await http.MultipartFile.fromPath(fileNameKey, file.path),
|
|
);
|
|
|
|
var streamedResponse = await request.send();
|
|
var response = await http.Response.fromStream(streamedResponse);
|
|
|
|
log('Upload response status: ${response.statusCode}');
|
|
log('Upload response body: ${response.body}');
|
|
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return postSingleFileRequest(
|
|
extendedURL: extendedURL,
|
|
body: body,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
file: file,
|
|
fileNameKey: fileNameKey,
|
|
);
|
|
}
|
|
}
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
return response;
|
|
} catch (e, stackTrace) {
|
|
log("Error uploading image: $e");
|
|
log("StackTrace: $stackTrace");
|
|
return http.Response('Error uploading image', 500);
|
|
}
|
|
}
|
|
|
|
//.............................................................................
|
|
static Future<http.Response> postMultipleFiles({
|
|
required String extendedURL,
|
|
required List<XFile> files,
|
|
Map<String, dynamic>? body,
|
|
required String fileNameKey,
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
}) async {
|
|
try {
|
|
var request = http.MultipartRequest(
|
|
'POST',
|
|
url(extendedURL: extendedURL),
|
|
);
|
|
|
|
Map<String, String> newHeaders = {};
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
|
|
}
|
|
|
|
request.headers.addAll(newHeaders);
|
|
|
|
// Add body fields if any
|
|
if (body != null) {
|
|
request.fields.addAll(
|
|
body.map((key, value) => MapEntry(key, value.toString())),
|
|
);
|
|
}
|
|
|
|
// 🔽 Add each file with proper MIME type
|
|
for (var file in files) {
|
|
final mimeType =
|
|
lookupMimeType(file.path) ?? 'application/octet-stream';
|
|
final mimeSplit = mimeType.split('/');
|
|
|
|
request.files.add(
|
|
await http.MultipartFile.fromPath(
|
|
fileNameKey,
|
|
file.path,
|
|
contentType: MediaType(mimeSplit[0], mimeSplit[1]),
|
|
filename: file.name,
|
|
),
|
|
);
|
|
|
|
log("Added file: ${file.name}, MimeType: $mimeType");
|
|
}
|
|
|
|
var streamedResponse = await request.send();
|
|
var response = await http.Response.fromStream(streamedResponse);
|
|
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return postMultipleFiles(
|
|
extendedURL: extendedURL,
|
|
body: body,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
files: files,
|
|
fileNameKey: fileNameKey,
|
|
);
|
|
}
|
|
}
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
return response;
|
|
} catch (e, stackTrace) {
|
|
log("Error uploading files: $e");
|
|
log("StackTrace: $stackTrace");
|
|
return http.Response('Error uploading files', 500);
|
|
}
|
|
}
|
|
|
|
//.........post Video Image and Documents with Mime Type..........................................................................................................
|
|
|
|
static Future<http.Response> postAnyFileWithMimeType({
|
|
required String extendedURL,
|
|
XFile? file, // Made file optional
|
|
Map<String, dynamic>? body,
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
String? fileNameKey, // Made fileNameKey optional since file is optional
|
|
}) async {
|
|
try {
|
|
final uri = url(extendedURL: extendedURL);
|
|
var request = http.MultipartRequest('POST', uri);
|
|
Map<String, String> newHeaders = {};
|
|
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
|
|
}
|
|
|
|
request.headers.addAll(newHeaders);
|
|
|
|
if (body != null) {
|
|
request.fields.addAll(
|
|
body.map((key, value) => MapEntry(key, value.toString())),
|
|
);
|
|
}
|
|
|
|
// ✅ Only add file if it's provided...........................................
|
|
|
|
if (file != null && fileNameKey != null) {
|
|
final mimeType =
|
|
lookupMimeType(file.path) ?? 'application/octet-stream';
|
|
final mimeSplit = mimeType.split('/');
|
|
|
|
request.files.add(
|
|
await http.MultipartFile.fromPath(
|
|
fileNameKey,
|
|
file.path,
|
|
contentType: MediaType(mimeSplit[0], mimeSplit[1]),
|
|
filename: file.name,
|
|
),
|
|
);
|
|
log("File Name : ${file.name}");
|
|
log("Mime Type : $mimeType");
|
|
}
|
|
|
|
var streamedResponse = await request.send();
|
|
var response = await http.Response.fromStream(streamedResponse);
|
|
|
|
log('Upload response status: ${response.statusCode}');
|
|
log('Upload response body: ${response.body}');
|
|
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return await postAnyFileWithMimeType(
|
|
extendedURL: extendedURL,
|
|
body: body,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
file: file,
|
|
fileNameKey: fileNameKey,
|
|
);
|
|
}
|
|
}
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
return response;
|
|
} catch (e, stackTrace) {
|
|
log("Error uploading: $e");
|
|
log("StackTrace: $stackTrace");
|
|
return http.Response('Error uploading', 500);
|
|
}
|
|
}
|
|
|
|
//............................................................................
|
|
// NEW METHOD: Post with multiple files having different field names
|
|
//............................................................................
|
|
static Future<http.Response> postMultipleIndivisualFiles({
|
|
required String extendedURL,
|
|
Map<String, dynamic>? body,
|
|
Map<String, dynamic>?
|
|
files, // Map of fieldName -> file (PlatformFile or XFile)
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
}) async {
|
|
try {
|
|
var request = http.MultipartRequest(
|
|
'POST',
|
|
url(extendedURL: extendedURL),
|
|
);
|
|
|
|
Map<String, String> newHeaders = {};
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
|
|
}
|
|
|
|
request.headers.addAll(newHeaders);
|
|
|
|
// Add body fields if any
|
|
if (body != null) {
|
|
request.fields.addAll(
|
|
body.map((key, value) => MapEntry(key, value.toString())),
|
|
);
|
|
}
|
|
|
|
// Add files with different field names
|
|
if (files != null) {
|
|
for (var entry in files.entries) {
|
|
final fieldName = entry.key;
|
|
final file = entry.value;
|
|
|
|
if (file != null) {
|
|
String filePath;
|
|
String fileName;
|
|
|
|
// Handle both PlatformFile and XFile
|
|
if (file is PlatformFile) {
|
|
filePath = file.path!;
|
|
fileName = file.name;
|
|
} else if (file is XFile) {
|
|
filePath = file.path;
|
|
fileName = file.name;
|
|
} else {
|
|
log("Unsupported file type for field: $fieldName");
|
|
continue;
|
|
}
|
|
|
|
final mimeType =
|
|
lookupMimeType(filePath) ?? 'application/octet-stream';
|
|
final mimeSplit = mimeType.split('/');
|
|
|
|
request.files.add(
|
|
await http.MultipartFile.fromPath(
|
|
fieldName,
|
|
filePath,
|
|
contentType: MediaType(mimeSplit[0], mimeSplit[1]),
|
|
filename: fileName,
|
|
),
|
|
);
|
|
|
|
log(
|
|
"Added file: $fileName to field: $fieldName, MimeType: $mimeType",
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
var streamedResponse = await request.send();
|
|
var response = await http.Response.fromStream(streamedResponse);
|
|
|
|
log('Upload response status: ${response.statusCode}');
|
|
log('Upload response body: ${response.body}');
|
|
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return postMultipleIndivisualFiles(
|
|
extendedURL: extendedURL,
|
|
body: body,
|
|
files: files,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
);
|
|
}
|
|
}
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
return response;
|
|
} catch (e, stackTrace) {
|
|
log("Error uploading files: $e");
|
|
log("StackTrace: $stackTrace");
|
|
return http.Response('Error uploading files', 500);
|
|
}
|
|
}
|
|
|
|
// Update File Patch Request...............................................................................
|
|
|
|
static Future<http.Response> patchAnyFileWithMimeType({
|
|
required String extendedURL,
|
|
XFile? file, // Made file optional
|
|
Map<String, dynamic>? body,
|
|
String? token,
|
|
bool sendHeaders = true,
|
|
String? fileNameKey, // Made fileNameKey optional since file is optional
|
|
}) async {
|
|
try {
|
|
final uri = url(extendedURL: extendedURL);
|
|
var request = http.MultipartRequest('PATCH', uri);
|
|
Map<String, String> newHeaders = {};
|
|
|
|
if (sendHeaders && SharedServices.isLoggedIn()) {
|
|
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
|
|
}
|
|
|
|
request.headers.addAll(newHeaders);
|
|
|
|
if (body != null) {
|
|
request.fields.addAll(
|
|
body.map((key, value) => MapEntry(key, value.toString())),
|
|
);
|
|
}
|
|
|
|
// ✅ Only add file if it's provided...........................................
|
|
|
|
if (file != null && fileNameKey != null) {
|
|
final mimeType =
|
|
lookupMimeType(file.path) ?? 'application/octet-stream';
|
|
final mimeSplit = mimeType.split('/');
|
|
|
|
request.files.add(
|
|
await http.MultipartFile.fromPath(
|
|
fileNameKey,
|
|
file.path,
|
|
contentType: MediaType(mimeSplit[0], mimeSplit[1]),
|
|
filename: file.name,
|
|
),
|
|
);
|
|
log("File Name : ${file.name}");
|
|
log("Mime Type : $mimeType");
|
|
}
|
|
|
|
var streamedResponse = await request.send();
|
|
var response = await http.Response.fromStream(streamedResponse);
|
|
if (response.statusCode == 401) {
|
|
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
|
|
if (isSuccess) {
|
|
return await postAnyFileWithMimeType(
|
|
extendedURL: extendedURL,
|
|
body: body,
|
|
sendHeaders: sendHeaders,
|
|
token: token,
|
|
file: file,
|
|
fileNameKey: fileNameKey,
|
|
);
|
|
}
|
|
}
|
|
// ✅Handle account deleted (403)
|
|
if (response.statusCode == 403) {
|
|
handleAccountDeleted();
|
|
}
|
|
return response;
|
|
} catch (e, stackTrace) {
|
|
log("Error uploading: $e");
|
|
log("StackTrace: $stackTrace");
|
|
return http.Response('Error uploading', 500);
|
|
}
|
|
}
|
|
}
|