Add image deletion and main selection
This commit is contained in:
@ -597,6 +597,76 @@ final class Database: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func setMainImage(_ version: Int, for capId: Int) async -> Cap? {
|
||||
guard hasServerAuthentication else {
|
||||
log("No authorization to set main image")
|
||||
return nil
|
||||
}
|
||||
guard var cap = cap(for: capId) else {
|
||||
log("No cap \(capId) to set main image")
|
||||
return nil
|
||||
}
|
||||
guard version < cap.imageCount else {
|
||||
log("Invalid main image \(version) for \(capId) with only \(cap.imageCount) images")
|
||||
return nil
|
||||
}
|
||||
cap.mainImage = version
|
||||
let finalCap = cap
|
||||
DispatchQueue.main.async {
|
||||
self.caps[capId] = finalCap
|
||||
log("Set main image \(version) for \(capId)")
|
||||
}
|
||||
return finalCap
|
||||
}
|
||||
|
||||
func delete(image: CapImage) async -> Bool {
|
||||
guard hasServerAuthentication else {
|
||||
log("No authorization to set main image")
|
||||
return false
|
||||
}
|
||||
guard var cap = cap(for: image.cap) else {
|
||||
log("No cap \(image.cap) to set main image")
|
||||
return false
|
||||
}
|
||||
guard image.version < cap.imageCount else {
|
||||
log("Invalid main image \(image.version) for \(cap.id) with only \(cap.imageCount) images")
|
||||
return false
|
||||
}
|
||||
|
||||
let url = serverUrl
|
||||
.appendingPathComponent("delete/\(cap.id)/\(image.version)")
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
request.addValue(serverAuthenticationKey, forHTTPHeaderField: "key")
|
||||
do {
|
||||
let (data, response) = try await URLSession.shared.data(for: request)
|
||||
guard let httpResponse = response as? HTTPURLResponse else {
|
||||
log("Unexpected response deleting image \(image.version) of cap \(cap.id): \(response)")
|
||||
return false
|
||||
}
|
||||
guard httpResponse.statusCode == 200 else {
|
||||
log("Failed to delete image \(image.version) of cap \(cap.id): Response \(httpResponse.statusCode)")
|
||||
return false
|
||||
}
|
||||
let newCap: Cap
|
||||
do {
|
||||
newCap = try JSONDecoder().decode(Cap.self, from: data)
|
||||
} catch {
|
||||
log("Invalid response data deleting image \(image.version) of cap \(cap.id): \(data)")
|
||||
return false
|
||||
}
|
||||
// Delete cached images
|
||||
images.removeCachedImages(for: cap.id)
|
||||
// Update cap
|
||||
caps[newCap.id] = newCap
|
||||
log("Deleted image \(image.version) of cap \(cap.id)")
|
||||
return true
|
||||
} catch {
|
||||
log("Failed to delete image \(image.version) of cap \(cap.id): \(error)")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Classification
|
||||
|
||||
/// The compiled recognition model on disk
|
||||
|
@ -106,6 +106,30 @@ final class ImageCache {
|
||||
return saveImage(image, at: downloadedImageUrl)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func removeCachedImages(for cap: Int) -> Bool {
|
||||
let prefix = String(format: "%04d-", cap)
|
||||
let files: [URL]
|
||||
do {
|
||||
files = try fm.contentsOfDirectory(atPath: folder.path)
|
||||
.filter { $0.hasPrefix(prefix) }
|
||||
.map { folder.appendingPathComponent($0) }
|
||||
} catch {
|
||||
log("Failed to get image cache file list: \(error)")
|
||||
return false
|
||||
}
|
||||
var isSuccessful = true
|
||||
for url in files {
|
||||
do {
|
||||
try fm.removeItem(at: url)
|
||||
} catch {
|
||||
isSuccessful = false
|
||||
log("Failed to remove image \(url.lastPathComponent) from cache: \(error)")
|
||||
}
|
||||
}
|
||||
return isSuccessful
|
||||
}
|
||||
|
||||
private func loadRemoteImage(_ image: CapImage) async -> URL? {
|
||||
let remoteURL = remoteImageUrl(image)
|
||||
return await loadRemoteImage(at: remoteURL)
|
||||
|
Reference in New Issue
Block a user