还原顶栏、浮动卡片、时间侧栏与底部交互;照片路径改为 CameraDownloads 相对路径并兼容旧数据;格式 Chip 固定 JPG 且不可点击。 Co-authored-by: Cursor <cursoragent@cursor.com>
121 lines
4.4 KiB
Swift
121 lines
4.4 KiB
Swift
//
|
|
// WiredTransferPhotoRow.swift
|
|
// suixinkan
|
|
//
|
|
|
|
import SwiftUI
|
|
import UIKit
|
|
|
|
/// 有线传图照片列表行。
|
|
struct WiredTransferPhotoRow: View {
|
|
let photo: WiredTransferPhotoItem
|
|
let selectUploadMode: Bool
|
|
let selected: Bool
|
|
let onToggleSelection: () -> Void
|
|
let onPhotoClick: () -> Void
|
|
let onRetry: () -> Void
|
|
let onDelete: () -> Void
|
|
|
|
private var canSelect: Bool { photo.canSelectForSpecifyUpload }
|
|
private var canRetry: Bool { photo.status == .failed || photo.status == .pending }
|
|
private var rowOpacity: Double { selectUploadMode && !canSelect ? 0.45 : 1 }
|
|
|
|
var body: some View {
|
|
VStack(spacing: 0) {
|
|
HStack(alignment: .center, spacing: 8) {
|
|
if selectUploadMode {
|
|
Button(action: onToggleSelection) {
|
|
WiredTransferSelectIndicator(selected: selected, enabled: canSelect)
|
|
}
|
|
.buttonStyle(.plain)
|
|
.disabled(!canSelect)
|
|
}
|
|
|
|
thumbnailView
|
|
.frame(width: WiredTransferDesign.thumbnailSize, height: WiredTransferDesign.thumbnailSize)
|
|
.clipShape(RoundedRectangle(cornerRadius: WiredTransferDesign.thumbnailCornerRadius))
|
|
.opacity(rowOpacity)
|
|
.onTapGesture {
|
|
if !selectUploadMode { onPhotoClick() }
|
|
}
|
|
|
|
VStack(alignment: .leading, spacing: 3) {
|
|
HStack(spacing: 4) {
|
|
Text(photo.fileName)
|
|
.font(.system(size: 12, weight: .medium))
|
|
.foregroundStyle(WiredTransferDesign.text333.opacity(rowOpacity))
|
|
.lineLimit(1)
|
|
Spacer(minLength: 0)
|
|
WiredTransferStatusBadge(status: photo.status)
|
|
.opacity(rowOpacity)
|
|
}
|
|
Text(metaText)
|
|
.font(.system(size: 10))
|
|
.foregroundStyle(WiredTransferDesign.text999.opacity(rowOpacity))
|
|
.lineLimit(1)
|
|
}
|
|
|
|
if !selectUploadMode {
|
|
Menu {
|
|
Button("重传") { onRetry() }
|
|
.disabled(!canRetry)
|
|
Button("删除", role: .destructive) { onDelete() }
|
|
} label: {
|
|
Image(systemName: "ellipsis")
|
|
.font(.system(size: 16))
|
|
.foregroundStyle(WiredTransferDesign.text666)
|
|
.frame(width: 32, height: 32)
|
|
.rotationEffect(.degrees(90))
|
|
}
|
|
}
|
|
}
|
|
.padding(.horizontal, 10)
|
|
.padding(.vertical, 8)
|
|
.contentShape(Rectangle())
|
|
.onTapGesture {
|
|
if selectUploadMode, canSelect { onToggleSelection() }
|
|
}
|
|
|
|
if photo.status == .transferring || photo.status == .uploading {
|
|
ProgressView(value: Double(photo.progress), total: 100)
|
|
.tint(AppDesign.primary)
|
|
.frame(height: WiredTransferDesign.progressBarHeight)
|
|
.padding(.horizontal, 10)
|
|
.padding(.bottom, 8)
|
|
}
|
|
}
|
|
}
|
|
|
|
private var metaText: String {
|
|
if photo.resolutionText.isEmpty { return photo.fileSizeText }
|
|
return "\(photo.fileSizeText) \(photo.resolutionText)"
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var thumbnailView: some View {
|
|
if photo.thumbnailURL.hasPrefix("file://"), let url = URL(string: photo.thumbnailURL) {
|
|
if let uiImage = UIImage(contentsOfFile: url.path) {
|
|
Image(uiImage: uiImage)
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fill)
|
|
} else {
|
|
thumbnailPlaceholder
|
|
}
|
|
} else if !photo.thumbnailURL.isEmpty {
|
|
RemoteImage(urlString: photo.thumbnailURL) {
|
|
thumbnailPlaceholder
|
|
}
|
|
} else {
|
|
thumbnailPlaceholder
|
|
}
|
|
}
|
|
|
|
private var thumbnailPlaceholder: some View {
|
|
WiredTransferDesign.pageBackground
|
|
.overlay {
|
|
Image(systemName: "photo")
|
|
.foregroundStyle(WiredTransferDesign.text999)
|
|
}
|
|
}
|
|
}
|