移除 Core 层 OTG 相机实现,保留旅拍有线传图 UI 与本地照片上传能力。
将本地存储与上传编排下沉到 Features/TravelAlbum,删除 USB/PTP 相关代码与测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -0,0 +1,83 @@
|
||||
//
|
||||
// CameraTransferModels.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// 有线传图任务状态。
|
||||
enum CameraTransferStatus: String, Codable, Equatable {
|
||||
case pending
|
||||
case downloading
|
||||
case downloaded
|
||||
case uploading
|
||||
case uploaded
|
||||
case failed
|
||||
}
|
||||
|
||||
/// 有线传图任务,表示单张照片从本地到上传登记的记录。
|
||||
struct CameraTransferTask: Identifiable, Equatable, Codable {
|
||||
let id: UUID
|
||||
let assetID: String
|
||||
let filename: String
|
||||
var localPath: String?
|
||||
var remoteURL: String?
|
||||
/// 拍摄时间,格式 `yyyy-MM-dd HH:mm:ss`。
|
||||
var capturedAt: String?
|
||||
var status: CameraTransferStatus
|
||||
var progress: Int
|
||||
var errorMessage: String?
|
||||
|
||||
/// 初始化传图任务。
|
||||
init(
|
||||
id: UUID = UUID(),
|
||||
assetID: String,
|
||||
filename: String,
|
||||
localPath: String? = nil,
|
||||
remoteURL: String? = nil,
|
||||
capturedAt: String? = nil,
|
||||
status: CameraTransferStatus = .pending,
|
||||
progress: Int = 0,
|
||||
errorMessage: String? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.assetID = assetID
|
||||
self.filename = filename
|
||||
self.localPath = localPath
|
||||
self.remoteURL = remoteURL
|
||||
self.capturedAt = capturedAt
|
||||
self.status = status
|
||||
self.progress = progress
|
||||
self.errorMessage = errorMessage
|
||||
}
|
||||
|
||||
/// 将日期格式化为列表使用的拍摄时间字符串。
|
||||
static func capturedAtString(from date: Date?) -> String {
|
||||
Self.capturedAtFormatter.string(from: date ?? Date())
|
||||
}
|
||||
|
||||
/// 从本地文件推断拍摄时间。
|
||||
static func capturedAtString(forLocalPath path: String) -> String? {
|
||||
guard let url = CameraDownloadStorage.resolveLocalURL(from: path),
|
||||
FileManager.default.fileExists(atPath: url.path),
|
||||
let attributes = try? FileManager.default.attributesOfItem(atPath: url.path)
|
||||
else { return nil }
|
||||
|
||||
let date = (attributes[.creationDate] as? Date)
|
||||
?? (attributes[.modificationDate] as? Date)
|
||||
return date.map { capturedAtString(from: $0) }
|
||||
}
|
||||
|
||||
private static let capturedAtFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.locale = Locale(identifier: "zh_CN")
|
||||
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
||||
return formatter
|
||||
}()
|
||||
|
||||
/// 本地文件 URL,支持相对 Documents 的 scoped 路径与绝对路径。
|
||||
var localURL: URL? {
|
||||
guard let localPath, !localPath.isEmpty else { return nil }
|
||||
return CameraDownloadStorage.resolveLocalURL(from: localPath)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user