import Foundation import SwiftUI final class FileResource: ObservableObject { unowned let content: Content let type: FileType /// Globally unique id @Published var id: String @Published var germanDescription: String @Published var englishDescription: String @Published var size: CGSize = .zero init(content: Content, id: String, en: String, de: String) { self.content = content self.id = id self.type = FileType(fileExtension: id.fileExtension) self.englishDescription = en self.germanDescription = de } /** Only for bundle images */ init(resourceImage: String, type: ImageFileType) { self.content = .mock // TODO: Add images to mock self.type = .image(type) self.id = resourceImage self.englishDescription = "A test image included in the bundle" self.germanDescription = "Ein Testbild aus dem Bundle" } func getDescription(for language: ContentLanguage) -> String { switch language { case .english: return englishDescription case .german: return germanDescription } } // MARK: Text func textContent() -> String { do { return try content.storage.fileContent(for: id) } catch { print("Failed to load text of file \(id): \(error)") return "" } } // MARK: Images var aspectRatio: CGFloat { guard size.height > 0 else { return 0 } return size.width / size.height } var imageToDisplay: Image { let imageData: Data do { imageData = try content.storage.fileData(for: id) } catch { print("Failed to load data for image \(id): \(error)") return failureImage } guard let loadedImage = NSImage(data: imageData) else { print("Failed to create image \(id)") return failureImage } if self.size == .zero && loadedImage.size != .zero { DispatchQueue.main.async { self.size = loadedImage.size } } return .init(nsImage: loadedImage) } private var failureImage: Image { Image(systemSymbol: .exclamationmarkTriangle) } } extension FileResource: Identifiable { } extension FileResource: Equatable { static func == (lhs: FileResource, rhs: FileResource) -> Bool { lhs.id == rhs.id } } extension FileResource: Hashable { func hash(into hasher: inout Hasher) { hasher.combine(id) } } extension FileResource: Comparable { static func < (lhs: FileResource, rhs: FileResource) -> Bool { lhs.id < rhs.id } }