Files
crossdesk/apps/ios/CrossDeskMobile/ThumbnailFileStore.swift
T

62 lines
2.2 KiB
Swift

import Foundation
/// Serialize writes and deletions so an in-flight capture cannot recreate a
/// preview after a clear/revocation has finished.
final class ThumbnailFileStore {
let directory: URL
private let queue = DispatchQueue(label: "cn.crossdesk.mobile.thumbnails",
qos: .utility)
init(directory: URL) {
self.directory = directory
}
func url(for fileName: String) -> URL {
directory.appendingPathComponent(fileName, isDirectory: false)
}
func save(fileName: String, makeData: @escaping () -> Data?,
completion: @escaping (String?) -> Void) {
queue.async {
let saved: String? = autoreleasepool {
guard let data = makeData() else { return nil }
do {
try FileManager.default.createDirectory(at: self.directory,
withIntermediateDirectories: true)
var directory = self.directory
var values = URLResourceValues()
values.isExcludedFromBackup = true
try directory.setResourceValues(values)
#if os(iOS)
try data.write(to: self.url(for: fileName),
options: [.atomic, .completeFileProtection])
#else
try data.write(to: self.url(for: fileName), options: .atomic)
#endif
return fileName
} catch {
return nil
}
}
completion(saved)
}
}
func remove(fileName: String) {
queue.async { try? FileManager.default.removeItem(at: self.url(for: fileName)) }
}
func removeAll(completion: @escaping (Bool) -> Void) {
queue.async {
do {
if FileManager.default.fileExists(atPath: self.directory.path) {
try FileManager.default.removeItem(at: self.directory)
}
completion(true)
} catch {
completion(false)
}
}
}
}