ChWebsiteApp/CHDataManagement/Model/ImageResource.swift
2024-12-06 22:07:22 +01:00

120 lines
2.7 KiB
Swift

import SwiftUI
final class ImageResource: ObservableObject {
@Published
var type: ImageType
/// Globally unique id
@Published
var id: String
@Published
var germanDescription: String
@Published
var englishDescription: String
@Published
var size: CGSize = .zero
var aspectRatio: CGFloat {
guard size.height > 0 else {
return 0
}
return size.width / size.height
}
private let source: ImageSource
init(type: ImageType, uniqueId: String, en: String, de: String, fileUrl: URL) {
self.type = type
self.id = uniqueId
self.source = .file(fileUrl)
self.englishDescription = en
self.germanDescription = de
}
init(resourceName: String, type: ImageType) {
self.type = type
self.id = resourceName
self.source = .resource(resourceName)
self.englishDescription = "A test image included in the bundle"
self.germanDescription = "Ein Test-Image aus dem Bundle"
}
private enum ImageSource {
case file(URL)
case resource(String)
}
func getDescription(for language: ContentLanguage) -> String {
switch language {
case .english: return englishDescription
case .german: return germanDescription
}
}
}
extension ImageResource: Identifiable {
}
extension ImageResource: Comparable {
static func < (lhs: ImageResource, rhs: ImageResource) -> Bool {
lhs.id < rhs.id
}
}
extension ImageResource: Equatable {
static func == (lhs: ImageResource, rhs: ImageResource) -> Bool {
lhs.id == rhs.id
}
}
extension ImageResource: Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
extension ImageResource {
var imageToDisplay: Image {
switch source {
case .file(let url):
return image(at: url)
case .resource(let name):
return .init(name)
}
}
private func image(at url: URL) -> Image {
let imageData: Data
do {
imageData = try Data(contentsOf: url)
} catch {
print("Failed to load image data from \(url.path): \(error)")
return failureImage
}
guard let loadedImage = NSImage(data: imageData) else {
print("Failed to create image from \(url.path)")
return failureImage
}
if self.size == .zero && loadedImage.size != .zero {
DispatchQueue.main.async {
self.size = loadedImage.size
}
}
return .init(nsImage: loadedImage)
}
private var failureImage: SwiftUI.Image {
Image(systemSymbol: .exclamationmarkTriangle)
}
}