Files
App/ios/WatchRunner Watch App/Views/AttachmentView.swift

110 lines
5.2 KiB
Swift

//
// AttachmentImageView.swift
// WatchRunner Watch App
//
// Created by LittleSheep on 2025/10/29.
//
import SwiftUI
import AVKit
import AVFoundation
struct AttachmentView: View {
let attachment: SnCloudFile
@EnvironmentObject var appState: AppState
@StateObject private var imageLoader = ImageLoader()
var body: some View {
Group {
if let mimeType = attachment.mimeType {
if mimeType.starts(with: "image") {
if let serverUrl = appState.serverUrl, let imageUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl) {
NavigationLink(
destination: ImageViewer(imageUrl: imageUrl).environmentObject(appState)
) {
if imageLoader.isLoading {
ProgressView()
} else if let image = imageLoader.image {
image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: .infinity)
.cornerRadius(8)
} else if let errorMessage = imageLoader.errorMessage {
Text("Failed to load attachment: \(errorMessage)")
.font(.caption)
.foregroundColor(.red)
.cornerRadius(8)
} else {
Text("File: \(attachment.id)")
.cornerRadius(8)
}
}
.buttonStyle(PlainButtonStyle())
} else {
Text("Image URL not available.")
}
} else if mimeType.starts(with: "video") {
if let serverUrl = appState.serverUrl, let videoUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl) {
NavigationLink(destination: VideoPlayerView(videoUrl: videoUrl)) {
if imageLoader.isLoading {
ProgressView()
} else if let image = imageLoader.image {
ZStack {
image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: .infinity)
.cornerRadius(8)
Image(systemName: "play.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 36, height: 36)
.foregroundColor(.white)
.shadow(color: .black.opacity(0.6), radius: 4, x: 0, y: 2)
}
} else if imageLoader.errorMessage != nil {
Image(systemName: "play.rectangle.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: .infinity)
.foregroundColor(.gray)
.cornerRadius(8)
} else {
ProgressView()
.cornerRadius(8)
}
}
.buttonStyle(PlainButtonStyle())
} else {
Text("Video URL not available.")
}
} else if mimeType.starts(with: "audio") {
if let serverUrl = appState.serverUrl, let audioUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl) {
AudioPlayerView(audioUrl: audioUrl)
} else {
Text("Cannot play audio: URL not available.")
}
} else {
Text("Unsupported media type: \(mimeType)")
}
} else {
Text("File: \(attachment.id) (No MIME type)")
}
}
.task(id: attachment.id) {
if let serverUrl = appState.serverUrl, let attachmentUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl), let token = appState.token {
if attachment.mimeType?.starts(with: "image") == true {
await imageLoader.loadImage(from: attachmentUrl, token: token)
}
if attachment.mimeType?.starts(with: "video") == true {
let thumbnailUrl = attachmentUrl
.appending(queryItems: [URLQueryItem(name: "thumbnail", value: "true")]) // Construct thumbnail URL
await imageLoader.loadImage(from: thumbnailUrl, token: token)
}
}
}
}
}