Add image compression and improve document edit UI
- Add Swift ImageCompression helper to enforce 200KB limit on iOS - Update iOS views to use compression for all image uploads - Fix iOS EditDocumentView to show success only after all uploads complete - Add AsyncImage thumbnails to Android EditDocumentScreen - Fix Android success message visibility with delay before state reset - Add proper error handling for failed image uploads - Add resetUpdateState on error for consistency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -375,7 +375,8 @@ struct AddDocumentView: View {
|
||||
var typesList: [String] = []
|
||||
|
||||
for (index, image) in selectedImages.enumerated() {
|
||||
if let imageData = image.jpegData(compressionQuality: 0.8) {
|
||||
// Compress image to meet size requirements
|
||||
if let imageData = ImageCompression.compressImage(image) {
|
||||
bytesList.append(KotlinByteArray(data: imageData))
|
||||
namesList.append("image_\(index).jpg")
|
||||
typesList.append("image/jpeg")
|
||||
|
||||
@@ -413,7 +413,8 @@ struct EditDocumentView: View {
|
||||
let documentApi = DocumentApi(client: ApiClient_iosKt.createHttpClient())
|
||||
|
||||
for (index, image) in newImages.enumerated() {
|
||||
if let imageData = image.jpegData(compressionQuality: 0.8) {
|
||||
// Compress image to meet size requirements
|
||||
if let imageData = ImageCompression.compressImage(image) {
|
||||
let result = try await documentApi.uploadDocumentImage(
|
||||
token: token,
|
||||
documentId: documentId.int32Value,
|
||||
@@ -424,11 +425,20 @@ struct EditDocumentView: View {
|
||||
)
|
||||
|
||||
if result is ApiResultError {
|
||||
print("Failed to upload image \(index)")
|
||||
let error = result as! ApiResultError
|
||||
throw NSError(domain: "DocumentUpload", code: -1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Failed to upload image \(index): \(error.message)"])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All operations completed successfully
|
||||
await MainActor.run {
|
||||
alertMessage = "Document updated successfully"
|
||||
showAlert = true
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
alertMessage = "Error saving document: \(error.localizedDescription)"
|
||||
|
||||
45
iosApp/iosApp/Helpers/ImageCompression.swift
Normal file
45
iosApp/iosApp/Helpers/ImageCompression.swift
Normal file
@@ -0,0 +1,45 @@
|
||||
import UIKit
|
||||
import ComposeApp
|
||||
|
||||
/// Helper class for compressing images to meet size requirements
|
||||
class ImageCompression {
|
||||
/// Maximum image size in bytes (200KB)
|
||||
/// Change this value to adjust the size limit for all image uploads
|
||||
static let maxImageSizeBytes = 200 * 1024 // 200KB
|
||||
|
||||
/// Initial JPEG compression quality
|
||||
private static let initialQuality: CGFloat = 0.85
|
||||
|
||||
/// Minimum JPEG compression quality
|
||||
private static let minQuality: CGFloat = 0.20
|
||||
|
||||
/// Compress an image to JPEG format with size limit
|
||||
/// - Parameter image: The UIImage to compress
|
||||
/// - Returns: Compressed image data as Data, or nil if compression fails
|
||||
static func compressImage(_ image: UIImage) -> Data? {
|
||||
var quality = initialQuality
|
||||
var compressedData: Data?
|
||||
|
||||
// Iteratively reduce quality until we meet the size requirement
|
||||
while quality >= minQuality {
|
||||
compressedData = image.jpegData(compressionQuality: quality)
|
||||
|
||||
if let data = compressedData, data.count <= maxImageSizeBytes {
|
||||
break
|
||||
}
|
||||
|
||||
// Reduce quality by 5%
|
||||
quality -= 0.05
|
||||
}
|
||||
|
||||
// If we still don't have data or it's still too large, return the last attempt
|
||||
return compressedData ?? image.jpegData(compressionQuality: minQuality)
|
||||
}
|
||||
|
||||
/// Compress multiple images
|
||||
/// - Parameter images: Array of UIImages to compress
|
||||
/// - Returns: Array of compressed image data
|
||||
static func compressImages(_ images: [UIImage]) -> [Data] {
|
||||
return images.compactMap { compressImage($0) }
|
||||
}
|
||||
}
|
||||
@@ -314,7 +314,8 @@ struct CompleteTaskView: View {
|
||||
|
||||
// If there are images, upload with images
|
||||
if !selectedImages.isEmpty {
|
||||
let imageDataArray = selectedImages.compactMap { $0.jpegData(compressionQuality: 0.8) }
|
||||
// Compress images to meet size requirements
|
||||
let imageDataArray = ImageCompression.compressImages(selectedImages)
|
||||
let imageByteArrays = imageDataArray.map { KotlinByteArray(data: $0) }
|
||||
let fileNames = (0..<imageDataArray.count).map { "image_\($0).jpg" }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user