ContactImageStore.swift
67 lignes · 2609 octets
import UIKit struct ImageStoreError: Error, CustomStringConvertible { let message: String var description: String { "ImageStoreError: \(message)" } } /// Port of android `data/ContactImageStore.kt`. /// Layout: <Application Support>/contacts/<contactId>/<name> (Android used /// filesDir with the same relative scheme). final class ContactImageStore: ContactImageStoring { private let root: URL init(rootDirectory: URL? = nil) { if let rootDirectory { root = rootDirectory } else { let base = FileManager.default.urls( for: .applicationSupportDirectory, in: .userDomainMask )[0] root = base.appendingPathComponent("contacts", isDirectory: true) } } private func dir(_ id: Int64) -> URL { let url = root.appendingPathComponent(String(id), isDirectory: true) try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) return url } @discardableResult func saveJpeg(contactId: Int64, name: String, image: UIImage, quality: CGFloat = 0.9) throws -> String { guard let data = image.jpegData(compressionQuality: quality) else { throw ImageStoreError(message: "JPEG encoding failed for \(name)") } return try saveBytes(contactId: contactId, name: name, bytes: data) } /// Writes raw bytes (e.g. an image downloaded from the server). @discardableResult func saveBytes(contactId: Int64, name: String, bytes: Data) throws -> String { let file = dir(contactId).appendingPathComponent(name) try bytes.write(to: file, options: .atomic) return file.path } func deleteAll(contactId: Int64) { try? FileManager.default.removeItem( at: root.appendingPathComponent(String(contactId), isDirectory: true) ) } /// Copies re-encoding after EXIF correction, so the stored file is already /// upright (Kotlin `copyImage`). func copyImage(fromPath: String?, toContactId: Int64, name: String) -> String? { guard let fromPath, fromPath.isNotBlank else { return nil } let src = URL(fileURLWithPath: fromPath) var isDirectory: ObjCBool = false guard FileManager.default.fileExists(atPath: src.path, isDirectory: &isDirectory), !isDirectory.boolValue else { return nil } guard let oriented = ImageOrientation.fromFile(src)?.bitmap else { return nil } return try? saveJpeg(contactId: toContactId, name: name, image: oriented) } }
GitRust