mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-25 09:41:02 +00:00
Fix the upload of heavy avatar or header image (#2103)
* Compressor: allows custom parameters for compressing image (maxSize, maxHeight, maxWidth) * Account: configures the maximum image size for uploading avatar and header
This commit is contained in:
parent
02a8cb12e9
commit
aaeb9eaa36
2 changed files with 66 additions and 17 deletions
|
@ -51,17 +51,19 @@ import SwiftUI
|
|||
didSet {
|
||||
if let item = mediaPickers.first {
|
||||
Task {
|
||||
if let data = await getItemImageData(item: item) {
|
||||
if isChangingAvatar {
|
||||
_ = await uploadAvatar(data: data)
|
||||
if let data = await getItemImageData(item: item, for: .avatar) {
|
||||
_ = await uploadAvatar(data: data)
|
||||
}
|
||||
isChangingAvatar = false
|
||||
} else if isChangingHeader {
|
||||
_ = await uploadHeader(data: data)
|
||||
if let data = await getItemImageData(item: item, for: .header) {
|
||||
_ = await uploadHeader(data: data)
|
||||
}
|
||||
isChangingHeader = false
|
||||
}
|
||||
await fetchAccount()
|
||||
isChangingAvatar = false
|
||||
isChangingHeader = false
|
||||
mediaPickers = []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,16 +142,48 @@ import SwiftUI
|
|||
}
|
||||
}
|
||||
|
||||
private func getItemImageData(item: PhotosPickerItem) async -> Data? {
|
||||
private func getItemImageData(item: PhotosPickerItem, for type: ItemType) async -> Data? {
|
||||
guard let imageFile = try? await item.loadTransferable(type: StatusEditor.ImageFileTranseferable.self) else { return nil }
|
||||
|
||||
let compressor = StatusEditor.Compressor()
|
||||
|
||||
guard let compressedData = await compressor.compressImageFrom(url: imageFile.url),
|
||||
let image = UIImage(data: compressedData),
|
||||
let uploadData = try? await compressor.compressImageForUpload(image)
|
||||
else { return nil }
|
||||
let uploadData = try? await compressor.compressImageForUpload(
|
||||
image,
|
||||
maxSize: 2 * 1024 * 1024, // 2MB
|
||||
maxHeight: type.maxHeight,
|
||||
maxWidth: type.maxWidth
|
||||
)
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return uploadData
|
||||
}
|
||||
}
|
||||
|
||||
extension EditAccountViewModel {
|
||||
private enum ItemType {
|
||||
case avatar
|
||||
case header
|
||||
|
||||
var maxHeight: CGFloat {
|
||||
switch self {
|
||||
case .avatar:
|
||||
400
|
||||
case .header:
|
||||
500
|
||||
}
|
||||
}
|
||||
|
||||
var maxWidth: CGFloat {
|
||||
switch self {
|
||||
case .avatar:
|
||||
400
|
||||
case .header:
|
||||
1500
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,30 +57,45 @@ public extension StatusEditor {
|
|||
}
|
||||
}
|
||||
|
||||
public func compressImageForUpload(_ image: UIImage) async throws -> Data {
|
||||
public func compressImageForUpload(
|
||||
_ image: UIImage,
|
||||
maxSize: Int = 10 * 1024 * 1024,
|
||||
maxHeight: Double = 5000,
|
||||
maxWidth: Double = 5000
|
||||
) async throws -> Data {
|
||||
var image = image
|
||||
if image.size.height > 5000 || image.size.width > 5000 {
|
||||
image = image.resized(to: .init(width: image.size.width / 4,
|
||||
height: image.size.height / 4))
|
||||
|
||||
if image.size.height > maxHeight || image.size.width > maxWidth {
|
||||
let heightFactor = image.size.height / maxHeight
|
||||
let widthFactor = image.size.width / maxWidth
|
||||
let maxFactor = max(heightFactor, widthFactor)
|
||||
|
||||
image = image.resized(to: .init(width: image.size.width / maxFactor,
|
||||
height: image.size.height / maxFactor))
|
||||
}
|
||||
|
||||
guard var imageData = image.jpegData(compressionQuality: 0.8) else {
|
||||
throw CompressorError.noData
|
||||
}
|
||||
|
||||
let maxSize = 10 * 1024 * 1024
|
||||
|
||||
var compressionQualityFactor: CGFloat = 0.8
|
||||
if imageData.count > maxSize {
|
||||
while imageData.count > maxSize {
|
||||
while imageData.count > maxSize && compressionQualityFactor >= 0 {
|
||||
guard let compressedImage = UIImage(data: imageData),
|
||||
let compressedData = compressedImage.jpegData(compressionQuality: 0.8)
|
||||
let compressedData = compressedImage.jpegData(compressionQuality: compressionQualityFactor)
|
||||
else {
|
||||
throw CompressorError.noData
|
||||
}
|
||||
|
||||
imageData = compressedData
|
||||
compressionQualityFactor -= 0.1
|
||||
}
|
||||
}
|
||||
|
||||
if imageData.count > maxSize && compressionQualityFactor <= 0 {
|
||||
throw CompressorError.noData
|
||||
}
|
||||
|
||||
return imageData
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue