feat: Enhance image handling in task reporting and commenting with compression and content type detection

This commit is contained in:
Vaibhav Surve 2025-06-12 18:00:31 +05:30
parent 3a449441fa
commit 1f784d96f4
2 changed files with 117 additions and 43 deletions

View File

@ -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(

View File

@ -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 //