feat: 暂提
This commit is contained in:
parent
2a9ef552fa
commit
e2c4f5d882
@ -98,15 +98,22 @@ struct MediaUploadView: View {
|
||||
selectedMedia: $uploadManager.selectedMedia,
|
||||
imageSelectionLimit: 20,
|
||||
videoSelectionLimit: 5,
|
||||
onDismiss: handleMediaPickerDismiss,
|
||||
onDismiss: {
|
||||
// 只处理界面相关的逻辑
|
||||
showMediaPicker = false
|
||||
},
|
||||
onUploadProgress: { index, progress in
|
||||
// 更新单个文件的上传进度
|
||||
print("File \(index) upload progress: \(progress * 100)%")
|
||||
}
|
||||
)
|
||||
}
|
||||
.onChange(of: uploadManager.selectedMedia) { newMedia in
|
||||
handleMediaChange(newMedia)
|
||||
print("onChange1111111", uploadManager.selectedMedia)
|
||||
// 在这里处理媒体变化
|
||||
if !newMedia.isEmpty {
|
||||
// 当有新的媒体时开始上传
|
||||
uploadManager.startUpload()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,6 +121,8 @@ struct MediaUploadView: View {
|
||||
|
||||
private func handleMediaPickerDismiss() {
|
||||
self.uploadManager.startUpload()
|
||||
print("handleMediaPickerDismiss1111111", uploadManager.selectedMedia)
|
||||
|
||||
// showMediaPicker = false
|
||||
|
||||
// // 确保选择器完全关闭后再开始上传
|
||||
@ -174,28 +183,88 @@ struct MainUploadArea: View {
|
||||
.fontWeight(.bold)
|
||||
.foregroundColor(.black)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding()
|
||||
|
||||
if let media = selectedMedia {
|
||||
MediaPreview(media: media, uploadManager: uploadManager)
|
||||
.frame(width: 225, height: 225)
|
||||
.onTapGesture { showMediaPicker = true }
|
||||
.padding(.bottom, 10)
|
||||
.padding(.horizontal)
|
||||
|
||||
if !uploadManager.selectedMedia.isEmpty {
|
||||
// 显示媒体预览网格
|
||||
ScrollView {
|
||||
LazyVGrid(columns: [
|
||||
GridItem(.flexible(), spacing: 16),
|
||||
GridItem(.flexible(), spacing: 16)
|
||||
], spacing: 16) {
|
||||
ForEach(0..<uploadManager.selectedMedia.count, id: \.self) { index in
|
||||
VStack(spacing: 8) {
|
||||
// 媒体预览
|
||||
MediaPreview(
|
||||
media: uploadManager.selectedMedia[index],
|
||||
uploadManager: uploadManager
|
||||
)
|
||||
.frame(height: 150)
|
||||
.cornerRadius(12)
|
||||
.shadow(radius: 2)
|
||||
|
||||
// 上传进度条
|
||||
if let status = uploadManager.uploadStatus["\(index)"] {
|
||||
switch status {
|
||||
case .uploading(let progress):
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("Uploading: \(Int(progress * 100))%")
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
ProgressView(value: progress, total: 1.0)
|
||||
.progressViewStyle(LinearProgressViewStyle())
|
||||
.tint(Color.themePrimary)
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
case .completed:
|
||||
HStack {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
.foregroundColor(.green)
|
||||
Text("Uploaded")
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
case .failed:
|
||||
HStack {
|
||||
Image(systemName: "exclamationmark.triangle.fill")
|
||||
.foregroundColor(.red)
|
||||
Text("Upload failed")
|
||||
.font(.caption)
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.frame(maxHeight: 400)
|
||||
} else {
|
||||
// 没有选择媒体时显示上传提示
|
||||
UploadPromptView(showMediaPicker: $showMediaPicker)
|
||||
}
|
||||
if !uploadManager.selectedMedia.isEmpty {
|
||||
ThumbnailScrollView(
|
||||
uploadManager: uploadManager,
|
||||
selectedIndices: $selectedIndices,
|
||||
selectedMedia: $selectedMedia
|
||||
)
|
||||
.id("thumbnailScroll\(uploadManager.selectedMedia.count)")
|
||||
|
||||
// 添加更多按钮
|
||||
Button(action: { showMediaPicker = true }) {
|
||||
HStack {
|
||||
Image(systemName: "plus.circle.fill")
|
||||
Text("Add More")
|
||||
}
|
||||
.font(.headline)
|
||||
.foregroundColor(.white)
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.themePrimary)
|
||||
.cornerRadius(10)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
}
|
||||
.background(Color.white)
|
||||
.cornerRadius(16)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,13 +312,14 @@ struct ThumbnailScrollView: View {
|
||||
ThumbnailView(
|
||||
media: media,
|
||||
isSelected: selectedIndex == index,
|
||||
showCheckmark: true
|
||||
) {
|
||||
// Directly update the selection without animation for immediate response
|
||||
selectedIndex = index
|
||||
selectedMedia = media
|
||||
selectedIndices = [index]
|
||||
}
|
||||
showCheckmark: true,
|
||||
uploadManager: uploadManager,
|
||||
onTap: {
|
||||
selectedIndex = index
|
||||
selectedMedia = media
|
||||
selectedIndices = [index]
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
AddMoreButton(showMediaPicker: .constant(true))
|
||||
@ -274,11 +344,14 @@ struct ThumbnailView: View {
|
||||
let media: MediaType
|
||||
let isSelected: Bool
|
||||
let showCheckmark: Bool
|
||||
let uploadManager: MediaUploadManager?
|
||||
let onTap: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Button(action: onTap) {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
Button(action: onTap) {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
// Main thumbnail content
|
||||
ZStack {
|
||||
Group {
|
||||
if let thumbnail = media.thumbnail {
|
||||
Image(uiImage: thumbnail)
|
||||
@ -297,34 +370,64 @@ struct ThumbnailView: View {
|
||||
.stroke(isSelected ? Color.themePrimary : Color.clear, lineWidth: 2)
|
||||
)
|
||||
|
||||
// Selection checkmark
|
||||
if isSelected && showCheckmark {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
.font(.system(size: 20))
|
||||
.foregroundColor(.white)
|
||||
.background(Circle().fill(Color.themePrimary))
|
||||
.offset(x: 6, y: -6) // Adjusted offset to ensure visibility
|
||||
.zIndex(1) // Ensure checkmark is above video icon
|
||||
}
|
||||
|
||||
// Video icon
|
||||
if media.isVideo {
|
||||
Image(systemName: "video.fill")
|
||||
.font(.caption)
|
||||
.foregroundColor(.white)
|
||||
.padding(4)
|
||||
.background(Color.black.opacity(0.6))
|
||||
.clipShape(Circle())
|
||||
.padding(4)
|
||||
.offset(x: -4, y: 4) // Slight adjustment for better positioning
|
||||
// Upload progress border
|
||||
if let uploadManager = uploadManager,
|
||||
let index = uploadManager.selectedMedia.firstIndex(where: { $0 == media }) {
|
||||
let status = uploadManager.uploadStatus["\(index)"]
|
||||
if case .uploading(let progress) = status, progress > 0 && progress < 1 {
|
||||
ZStack {
|
||||
Circle()
|
||||
.stroke(
|
||||
Color.themePrimary.opacity(0.3),
|
||||
style: StrokeStyle(lineWidth: 2, lineCap: .round)
|
||||
)
|
||||
.rotationEffect(.degrees(-90))
|
||||
.padding(2)
|
||||
|
||||
Circle()
|
||||
.trim(from: 0, to: progress)
|
||||
.stroke(
|
||||
Color.themePrimary,
|
||||
style: StrokeStyle(lineWidth: 2, lineCap: .round)
|
||||
)
|
||||
.rotationEffect(.degrees(-90))
|
||||
.animation(.linear, value: progress)
|
||||
.padding(2)
|
||||
}
|
||||
.frame(width: 20, height: 20)
|
||||
.offset(x: 30, y: -30)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: 80, height: 80)
|
||||
.contentShape(Rectangle())
|
||||
.padding(4) // Add padding to prevent clipping
|
||||
|
||||
// Selection checkmark
|
||||
if isSelected && showCheckmark {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
.font(.system(size: 20))
|
||||
.foregroundColor(.white)
|
||||
.background(Circle().fill(Color.themePrimary))
|
||||
.offset(x: 6, y: -6)
|
||||
.zIndex(1)
|
||||
}
|
||||
|
||||
// Video icon
|
||||
if media.isVideo {
|
||||
Image(systemName: "video.fill")
|
||||
.font(.caption)
|
||||
.foregroundColor(.white)
|
||||
.padding(4)
|
||||
.background(Color.black.opacity(0.6))
|
||||
.clipShape(Circle())
|
||||
.padding(4)
|
||||
.offset(x: -4, y: 4)
|
||||
}
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
.frame(width: 80, height: 80)
|
||||
.contentShape(Rectangle())
|
||||
.padding(4)
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Add More Button
|
||||
@ -357,83 +460,46 @@ struct MediaPreview: View {
|
||||
@ObservedObject var uploadManager: MediaUploadManager
|
||||
|
||||
private var uploadProgress: Double {
|
||||
// Get the upload progress for this media item using its index
|
||||
if let index = uploadManager.selectedMedia.firstIndex(where: { $0 == media }) {
|
||||
let status = uploadManager.uploadStatus["\(index)"]
|
||||
if case .uploading(let progress) = status {
|
||||
return progress
|
||||
}
|
||||
guard let index = uploadManager.selectedMedia.firstIndex(where: { $0 == media }),
|
||||
case .uploading(let progress) = uploadManager.uploadStatus["\(index)"] else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
private var isUploading: Bool {
|
||||
if let index = uploadManager.selectedMedia.firstIndex(where: { $0 == media }) {
|
||||
let status = uploadManager.uploadStatus["\(index)"]
|
||||
if case .uploading = status {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return progress
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
// Main media content
|
||||
// 媒体内容
|
||||
Group {
|
||||
switch media {
|
||||
case .image(let uiImage):
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.cornerRadius(12)
|
||||
.drawingGroup()
|
||||
.scaledToFill()
|
||||
case .video(_, let thumbnail):
|
||||
if let thumbnail = thumbnail {
|
||||
Image(uiImage: thumbnail)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.scaledToFill()
|
||||
.overlay(
|
||||
Image(systemName: "play.circle.fill")
|
||||
.font(.system(size: 48))
|
||||
.font(.system(size: 36))
|
||||
.foregroundColor(.white)
|
||||
.shadow(radius: 10)
|
||||
.shadow(radius: 8)
|
||||
)
|
||||
.cornerRadius(12)
|
||||
.drawingGroup()
|
||||
} else {
|
||||
Color.gray
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Upload progress border
|
||||
if isUploading {
|
||||
Circle()
|
||||
.stroke(
|
||||
Color.themePrimary.opacity(0.3),
|
||||
style: StrokeStyle(lineWidth: 4, lineCap: .round)
|
||||
)
|
||||
.rotationEffect(.degrees(-90))
|
||||
.padding(4)
|
||||
|
||||
Circle()
|
||||
.trim(from: 0, to: uploadProgress)
|
||||
.stroke(
|
||||
Color.themePrimary,
|
||||
style: StrokeStyle(lineWidth: 4, lineCap: .round)
|
||||
)
|
||||
.rotationEffect(.degrees(-90))
|
||||
.animation(.linear, value: uploadProgress)
|
||||
.padding(4)
|
||||
}
|
||||
.aspectRatio(1, contentMode: .fill)
|
||||
.clipped()
|
||||
.cornerRadius(8)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.stroke(Color.themePrimary.opacity(0.3), lineWidth: 1)
|
||||
)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(Color.themeTextWhiteSecondary)
|
||||
.cornerRadius(16)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.stroke(Color.themePrimary, lineWidth: 2)
|
||||
)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user