feat: Enhance image handling in task reporting and commenting with compression and content type detection
This commit is contained in:
parent
3a449441fa
commit
1f784d96f4
@ -10,6 +10,7 @@ import 'package:marco/controller/task_planing/daily_task_planing_controller.dart
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'dart:io';
|
||||
import 'dart:convert';
|
||||
import 'package:marco/helpers/widgets/my_image_compressor.dart';
|
||||
|
||||
final Logger logger = Logger();
|
||||
|
||||
@ -136,14 +137,27 @@ class ReportTaskController extends MyController {
|
||||
isLoading.value = true;
|
||||
List<Map<String, dynamic>>? imageData;
|
||||
if (images != null && images.isNotEmpty) {
|
||||
imageData = await Future.wait(images.map((file) async {
|
||||
final bytes = await file.readAsBytes();
|
||||
final base64Image = base64Encode(bytes);
|
||||
return {
|
||||
"fileName": file.path.split('/').last,
|
||||
"fileData": base64Image,
|
||||
};
|
||||
}));
|
||||
if (images != null && images.isNotEmpty) {
|
||||
final imageFutures = images.map((file) async {
|
||||
final compressedBytes = await compressImageToUnder100KB(file);
|
||||
if (compressedBytes == null) return null;
|
||||
|
||||
final base64Image = base64Encode(compressedBytes);
|
||||
final fileName = file.path.split('/').last;
|
||||
final contentType = _getContentTypeFromFileName(fileName);
|
||||
|
||||
return {
|
||||
"fileName": fileName,
|
||||
"base64Data": base64Image,
|
||||
"contentType": contentType,
|
||||
"fileSize": compressedBytes.lengthInBytes,
|
||||
"description": "Image uploaded for task report",
|
||||
};
|
||||
}).toList();
|
||||
|
||||
final results = await Future.wait(imageFutures);
|
||||
imageData = results.whereType<Map<String, dynamic>>().toList();
|
||||
}
|
||||
}
|
||||
|
||||
final success = await ApiService.reportTask(
|
||||
@ -180,6 +194,23 @@ class ReportTaskController extends MyController {
|
||||
}
|
||||
}
|
||||
|
||||
String _getContentTypeFromFileName(String fileName) {
|
||||
final ext = fileName.split('.').last.toLowerCase();
|
||||
switch (ext) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
return 'image/jpeg';
|
||||
case 'png':
|
||||
return 'image/png';
|
||||
case 'webp':
|
||||
return 'image/webp';
|
||||
case 'gif':
|
||||
return 'image/gif';
|
||||
default:
|
||||
return 'application/octet-stream';
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> commentTask({
|
||||
required String projectId,
|
||||
required String comment,
|
||||
@ -200,22 +231,37 @@ class ReportTaskController extends MyController {
|
||||
try {
|
||||
isLoading.value = true;
|
||||
List<Map<String, dynamic>>? imageData;
|
||||
|
||||
if (images != null && images.isNotEmpty) {
|
||||
imageData = await Future.wait(images.map((file) async {
|
||||
final bytes = await file.readAsBytes();
|
||||
final base64Image = base64Encode(bytes);
|
||||
final imageFutures = images.map((file) async {
|
||||
final compressedBytes = await compressImageToUnder100KB(file);
|
||||
if (compressedBytes == null) return null;
|
||||
|
||||
final base64Image = base64Encode(compressedBytes);
|
||||
final fileName = file.path.split('/').last;
|
||||
final contentType = _getContentTypeFromFileName(fileName);
|
||||
|
||||
return {
|
||||
"fileName": file.path.split('/').last,
|
||||
"fileData": base64Image,
|
||||
"fileName": fileName,
|
||||
"base64Data": base64Image,
|
||||
"contentType": contentType,
|
||||
"fileSize": compressedBytes.lengthInBytes,
|
||||
"description": "Image uploaded for task comment",
|
||||
};
|
||||
}));
|
||||
}).toList();
|
||||
|
||||
final results = await Future.wait(imageFutures);
|
||||
imageData = results.whereType<Map<String, dynamic>>().toList();
|
||||
}
|
||||
|
||||
final success = await ApiService.commentTask(
|
||||
id: projectId,
|
||||
comment: commentField,
|
||||
images: imageData,
|
||||
);
|
||||
).timeout(const Duration(seconds: 30), onTimeout: () {
|
||||
logger.e("Request timed out.");
|
||||
throw Exception("Request timed out.");
|
||||
});
|
||||
|
||||
if (success) {
|
||||
showAppSnackbar(
|
||||
@ -223,7 +269,6 @@ class ReportTaskController extends MyController {
|
||||
message: "Task commented successfully!",
|
||||
type: SnackbarType.success,
|
||||
);
|
||||
|
||||
await taskController.fetchTaskData(projectId);
|
||||
} else {
|
||||
showAppSnackbar(
|
||||
|
@ -95,7 +95,10 @@ class ApiService {
|
||||
}
|
||||
|
||||
static Future<http.Response?> _postRequest(
|
||||
String endpoint, dynamic body) async {
|
||||
String endpoint,
|
||||
dynamic body, {
|
||||
Duration customTimeout = timeout,
|
||||
}) async {
|
||||
String? token = await _getToken();
|
||||
if (token == null) return null;
|
||||
|
||||
@ -108,7 +111,7 @@ class ApiService {
|
||||
try {
|
||||
final response = await http
|
||||
.post(uri, headers: _headers(token), body: jsonEncode(body))
|
||||
.timeout(timeout);
|
||||
.timeout(customTimeout);
|
||||
|
||||
_log("Response Status: ${response.statusCode}");
|
||||
return response;
|
||||
@ -117,6 +120,7 @@ class ApiService {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Attendence Screen API Calls =====
|
||||
|
||||
static Future<List<dynamic>?> getProjects() async {
|
||||
@ -354,22 +358,35 @@ class ApiService {
|
||||
if (images != null && images.isNotEmpty) "images": images,
|
||||
};
|
||||
|
||||
final response = await _postRequest(ApiEndpoints.reportTask, body);
|
||||
String? token = await _getToken();
|
||||
if (token == null) return false;
|
||||
|
||||
if (response == null) {
|
||||
_log("Error: No response from server.");
|
||||
return false;
|
||||
final uri = Uri.parse("${ApiEndpoints.baseUrl}${ApiEndpoints.reportTask}");
|
||||
|
||||
_log("POST $uri");
|
||||
_log("Headers: ${_headers(token)}");
|
||||
_log("Body: $body");
|
||||
|
||||
try {
|
||||
final response = await http
|
||||
.post(uri, headers: _headers(token), body: jsonEncode(body))
|
||||
.timeout(const Duration(seconds: 30));
|
||||
|
||||
_log("Response Status: ${response.statusCode}");
|
||||
|
||||
final json = jsonDecode(response.body);
|
||||
|
||||
if (response.statusCode == 200 && json['success'] == true) {
|
||||
Get.back();
|
||||
return true;
|
||||
} else {
|
||||
_log("Failed to report task: ${json['message'] ?? 'Unknown error'}");
|
||||
}
|
||||
} catch (e) {
|
||||
_log("HTTP POST Exception (reportTask): $e");
|
||||
}
|
||||
|
||||
final json = jsonDecode(response.body);
|
||||
|
||||
if (response.statusCode == 200 && json['success'] == true) {
|
||||
Get.back();
|
||||
return true;
|
||||
} else {
|
||||
_log("Failed to report task: ${json['message'] ?? 'Unknown error'}");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static Future<bool> commentTask({
|
||||
@ -384,21 +401,33 @@ class ApiService {
|
||||
if (images != null && images.isNotEmpty) "images": images,
|
||||
};
|
||||
|
||||
final response = await _postRequest(ApiEndpoints.commentTask, body);
|
||||
String? token = await _getToken();
|
||||
if (token == null) return false;
|
||||
|
||||
if (response == null) {
|
||||
_log("Error: No response from server.");
|
||||
return false;
|
||||
final uri = Uri.parse("${ApiEndpoints.baseUrl}${ApiEndpoints.commentTask}");
|
||||
|
||||
_log("POST $uri");
|
||||
_log("Headers: ${_headers(token)}");
|
||||
_log("Body: $body");
|
||||
|
||||
try {
|
||||
final response = await http
|
||||
.post(uri, headers: _headers(token), body: jsonEncode(body))
|
||||
.timeout(const Duration(seconds: 30));
|
||||
|
||||
_log("Response Status: ${response.statusCode}");
|
||||
|
||||
final json = jsonDecode(response.body);
|
||||
if (response.statusCode == 200 && json['success'] == true) {
|
||||
return true;
|
||||
} else {
|
||||
_log("Failed to comment task: ${json['message'] ?? 'Unknown error'}");
|
||||
}
|
||||
} catch (e) {
|
||||
_log("HTTP POST Exception (commentTask): $e");
|
||||
}
|
||||
|
||||
final json = jsonDecode(response.body);
|
||||
|
||||
if (response.statusCode == 200 && json['success'] == true) {
|
||||
return true;
|
||||
} else {
|
||||
_log("Failed to comment task: ${json['message'] ?? 'Unknown error'}");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Daily Task Planing //
|
||||
|
Loading…
x
Reference in New Issue
Block a user