Files
furumi_macos/furumi_macos/ImageView.swift
T
Ultradesu 2f8cff528c init
2026-06-08 16:50:16 +01:00

72 lines
1.9 KiB
Swift

//
// ImageView.swift
// furumi_macos
//
import SwiftUI
struct ImageView: View {
let urlString: String?
let width: CGFloat
let height: CGFloat
let systemPlaceholder: String
@Environment(AuthManager.self) private var authManager
@State private var loadedImage: Image?
var body: some View {
Group {
if let loadedImage {
loadedImage
.resizable()
.scaledToFill()
.sized(width: width, height: height)
.clipped()
.clipShape(RoundedRectangle(cornerRadius: 10))
} else {
placeholder
.sized(width: width, height: height)
}
}
.task(id: urlString) {
await loadImage()
}
}
private func loadImage() async {
loadedImage = nil
guard let urlString, let url = URL(string: urlString) else { return }
var req = URLRequest(url: url, cachePolicy: .returnCacheDataElseLoad)
if let auth = authManager.session?.tokens.authorizationHeader {
req.setValue(auth, forHTTPHeaderField: "Authorization")
}
guard let (data, _) = try? await URLSession.shared.data(for: req),
let nsImage = NSImage(data: data) else { return }
loadedImage = Image(nsImage: nsImage)
}
@ViewBuilder
private var placeholder: some View {
ZStack {
RoundedRectangle(cornerRadius: 10)
.fill(Color.secondary.opacity(0.12))
Image(systemName: systemPlaceholder)
.foregroundColor(.accentColor)
}
}
}
private extension View {
@ViewBuilder
func sized(width: CGFloat, height: CGFloat) -> some View {
if width.isFinite {
self.frame(width: width, height: height)
} else {
self.frame(maxWidth: .infinity, minHeight: height, maxHeight: height)
}
}
}