110 lines
5.2 KiB
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|