wake-ios/wake/View/Examples/MediaDemo.swift
2025-09-01 19:42:32 +08:00

191 lines
7.8 KiB
Swift

import SwiftUI
struct MediaUploadDemo: View {
@StateObject private var uploadManager = MediaUploadManager()
@State private var showMediaPicker = false
@State private var showUploadAlert = false
@State private var isUploading = false
var body: some View {
NavigationView {
VStack(spacing: 20) {
//
Button(action: {
showMediaPicker = true
}) {
Label("添加图片或视频", systemImage: "plus.circle.fill")
.font(.headline)
.frame(maxWidth: .infinity)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
.padding(.horizontal)
.sheet(isPresented: $showMediaPicker) {
MediaPicker(
selectedMedia: Binding(
get: { uploadManager.selectedMedia },
set: { newMedia in
uploadManager.clearAllMedia()
uploadManager.addMedia(newMedia)
}
),
imageSelectionLimit: 1,
videoSelectionLimit: 0,
allowedMediaTypes: .imagesOnly,
selectionMode: .single,
onDismiss: {
showMediaPicker = false
if !uploadManager.selectedMedia.isEmpty {
// Start upload logic here
}
}
)
}
//
if uploadManager.selectedMedia.isEmpty {
VStack(spacing: 16) {
Image(systemName: "photo.on.rectangle.angled")
.font(.system(size: 60))
.foregroundColor(.gray)
Text("暂无媒体文件")
.font(.headline)
.foregroundColor(.gray)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
} else {
ScrollView {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 120), spacing: 10)], spacing: 10) {
ForEach(0..<uploadManager.selectedMedia.count, id: \.self) { index in
MediaItemView(
media: uploadManager.selectedMedia[index],
status: uploadManager.uploadStatus["\(index)"] ?? .pending
)
.onTapGesture {
//
if case .video = uploadManager.selectedMedia[index] {
//
print("Play video at index \(index)")
}
}
}
}
.padding()
}
}
//
if isUploading {
VStack {
//
if let progress = uploadManager.uploadStatus.values.compactMap({ status -> Double? in
if case .uploading(let progress) = status { return progress }
return nil
}).first {
ProgressView(value: progress, total: 1.0)
.padding(.horizontal)
Text("上传中 \(Int(progress * 100))%")
.font(.subheadline)
.foregroundColor(.gray)
} else {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
.scaleEffect(1.5)
Text("正在准备上传...")
.font(.subheadline)
.foregroundColor(.gray)
.padding(.top, 8)
}
}
.frame(maxWidth: .infinity)
.padding()
}
}
.alert(isPresented: $showUploadAlert) {
Alert(
title: Text(uploadManager.isAllUploaded ? "上传完成" : "上传状态"),
message: Text(uploadManager.isAllUploaded ?
"所有文件上传完成!" :
"正在处理上传..."),
dismissButton: .default(Text("确定"))
)
}
.onChange(of: uploadManager.uploadStatus) { _ in
//
let allFinished = uploadManager.uploadStatus.values.allSatisfy { status in
if case .completed = status { return true }
if case .failed = status { return true }
return false
}
if allFinished && !uploadManager.uploadStatus.isEmpty {
isUploading = false
showUploadAlert = true
}
}
}
}
}
//
struct MediaItemView: View {
let media: MediaType
let status: MediaUploadStatus
var body: some View {
ZStack(alignment: .bottom) {
//
if let thumbnail = media.thumbnail {
Image(uiImage: thumbnail)
.resizable()
.scaledToFill()
.frame(width: 120, height: 120)
.cornerRadius(8)
.clipped()
//
if media.isVideo {
Image(systemName: "play.circle.fill")
.font(.system(size: 30))
.foregroundColor(.white)
.shadow(radius: 5)
}
//
VStack {
Spacer()
if case .uploading(let progress) = status {
ProgressView(value: progress, total: 1.0)
.progressViewStyle(LinearProgressViewStyle())
.frame(height: 4)
.padding(.horizontal, 4)
} else if case .completed = status {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
.padding(4)
.background(Circle().fill(Color.white))
} else if case .failed = status {
Image(systemName: "exclamationmark.circle.fill")
.foregroundColor(.red)
.padding(4)
.background(Circle().fill(Color.white))
}
}
.padding(4)
}
}
.frame(width: 120, height: 120)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color.gray.opacity(0.3), lineWidth: 1)
)
}
}
//
#Preview {
MediaUploadDemo()
.environmentObject(AuthState.shared)
}