恢复 USB 相机连接、边拍边传、三品牌驱动与 SwiftUI 历史导入页,通过适配层对接现有本地上传与 OSS 管道。 Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
2.9 KiB
Swift
97 lines
2.9 KiB
Swift
import Foundation
|
||
|
||
/// 旅拍相册 OTG 照片落盘实现:写入 scoped 本地目录并通知传输管道。
|
||
@MainActor
|
||
final class TravelAlbumOTGPhotoSink: OTGPhotoSink {
|
||
private let albumId: Int
|
||
private let accountKey: String
|
||
private let pipeline: WiredCameraTransferPipeline
|
||
private let existingObjectIDsProvider: () async -> Set<String>
|
||
private let autoUploadProvider: () -> Bool
|
||
|
||
/// 初始化旅拍相册 OTG 落盘实现。
|
||
init(
|
||
albumId: Int,
|
||
accountKey: String,
|
||
pipeline: WiredCameraTransferPipeline,
|
||
existingObjectIDsProvider: @escaping () async -> Set<String>,
|
||
autoUploadProvider: @escaping () -> Bool
|
||
) {
|
||
self.albumId = albumId
|
||
self.accountKey = accountKey
|
||
self.pipeline = pipeline
|
||
self.existingObjectIDsProvider = existingObjectIDsProvider
|
||
self.autoUploadProvider = autoUploadProvider
|
||
}
|
||
|
||
/// 保存边拍边传图像数据。
|
||
func saveLiveShot(
|
||
data: Data,
|
||
filename: String,
|
||
capturedAt: Date,
|
||
cameraObjectID: String
|
||
) async throws -> SavedOTGPhoto {
|
||
let fileURL = try OTGPhotoFileWriter.writeImage(
|
||
data,
|
||
filename: filename,
|
||
accountKey: accountKey,
|
||
albumID: albumId
|
||
)
|
||
return ingestSavedFile(
|
||
fileURL: fileURL,
|
||
filename: filename,
|
||
capturedAt: capturedAt,
|
||
cameraObjectID: cameraObjectID
|
||
)
|
||
}
|
||
|
||
/// 保存历史导入已下载文件。
|
||
func saveDownloadedFile(
|
||
at url: URL,
|
||
filename: String,
|
||
capturedAt: Date,
|
||
cameraObjectID: String
|
||
) async throws -> SavedOTGPhoto {
|
||
let fileURL = try OTGPhotoFileWriter.moveDownloadedFile(
|
||
from: url,
|
||
filename: filename,
|
||
accountKey: accountKey,
|
||
albumID: albumId
|
||
)
|
||
return ingestSavedFile(
|
||
fileURL: fileURL,
|
||
filename: filename,
|
||
capturedAt: capturedAt,
|
||
cameraObjectID: cameraObjectID
|
||
)
|
||
}
|
||
|
||
/// 返回当前相册已导入的相机对象 ID。
|
||
func existingCameraObjectIDs() async -> Set<String> {
|
||
await existingObjectIDsProvider()
|
||
}
|
||
|
||
private func ingestSavedFile(
|
||
fileURL: URL,
|
||
filename: String,
|
||
capturedAt: Date,
|
||
cameraObjectID: String
|
||
) -> SavedOTGPhoto {
|
||
let relativePath = OTGPhotoFileWriter.relativePath(for: fileURL)
|
||
let autoUpload = autoUploadProvider()
|
||
pipeline.ingestDownloadedAsset(
|
||
assetID: cameraObjectID,
|
||
filename: filename,
|
||
localPath: relativePath,
|
||
capturedAt: capturedAt,
|
||
autoUpload: autoUpload
|
||
)
|
||
return SavedOTGPhoto(
|
||
assetID: cameraObjectID,
|
||
relativeLocalPath: relativePath,
|
||
filename: filename,
|
||
capturedAt: capturedAt
|
||
)
|
||
}
|
||
}
|