92 lines
2.9 KiB
Swift
92 lines
2.9 KiB
Swift
import UIKit
|
|
|
|
// MARK: - PendingAttachment
|
|
|
|
/// Represents an attachment selected by the user but not yet sent.
|
|
/// Used in the attachment preview strip above the compositor.
|
|
///
|
|
/// Desktop parity: the `attachments` state array in `DialogInput.tsx` before
|
|
/// `prepareAttachmentsToSend()` processes and uploads them.
|
|
struct PendingAttachment: Identifiable, Sendable {
|
|
|
|
/// Random 8-character alphanumeric ID (matches desktop's `generateRandomKey(8)`).
|
|
let id: String
|
|
|
|
/// Attachment type — `.image` or `.file` for user-initiated sends.
|
|
let type: AttachmentType
|
|
|
|
/// Raw image/file data (pre-compression for images).
|
|
let data: Data
|
|
|
|
/// Thumbnail for preview (images only). `nil` for files.
|
|
let thumbnail: UIImage?
|
|
|
|
/// Original file name (files only). `nil` for images.
|
|
let fileName: String?
|
|
|
|
/// File size in bytes (files only). `nil` for images.
|
|
let fileSize: Int?
|
|
|
|
// MARK: - Factory
|
|
|
|
/// Creates a PendingAttachment from a UIImage (compressed to JPEG).
|
|
static func fromImage(_ image: UIImage) -> PendingAttachment {
|
|
let id = generateRandomId()
|
|
// Resize to max 1280px on longest side for mobile optimization
|
|
let resized = resizeImage(image, maxDimension: 1280)
|
|
let data = resized.jpegData(compressionQuality: 0.8) ?? Data()
|
|
let thumbnail = resizeImage(image, maxDimension: 200)
|
|
|
|
return PendingAttachment(
|
|
id: id,
|
|
type: .image,
|
|
data: data,
|
|
thumbnail: thumbnail,
|
|
fileName: nil,
|
|
fileSize: nil
|
|
)
|
|
}
|
|
|
|
/// Creates a PendingAttachment from file data + metadata.
|
|
static func fromFile(data: Data, fileName: String) -> PendingAttachment {
|
|
return PendingAttachment(
|
|
id: generateRandomId(),
|
|
type: .file,
|
|
data: data,
|
|
thumbnail: nil,
|
|
fileName: fileName,
|
|
fileSize: data.count
|
|
)
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
/// Generates a random 8-character ID (desktop: `generateRandomKey(8)`).
|
|
private static func generateRandomId() -> String {
|
|
let chars = "abcdefghijklmnopqrstuvwxyz0123456789"
|
|
return String((0..<8).map { _ in chars.randomElement()! })
|
|
}
|
|
|
|
/// Resizes image so longest side is at most `maxDimension`.
|
|
private static func resizeImage(_ image: UIImage, maxDimension: CGFloat) -> UIImage {
|
|
let size = image.size
|
|
let maxSide = max(size.width, size.height)
|
|
guard maxSide > maxDimension else { return image }
|
|
|
|
let scale = maxDimension / maxSide
|
|
let newSize = CGSize(width: size.width * scale, height: size.height * scale)
|
|
|
|
let renderer = UIGraphicsImageRenderer(size: newSize)
|
|
return renderer.image { _ in
|
|
image.draw(in: CGRect(origin: .zero, size: newSize))
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Constants
|
|
|
|
extension PendingAttachment {
|
|
/// Desktop parity: `MAX_ATTACHMENTS_IN_MESSAGE = 5`.
|
|
static let maxAttachmentsPerMessage = 5
|
|
}
|