将 otg_swift OTG 引擎迁入 Core/CameraOTG,并接入旅拍有线传图与历史导入。

恢复 USB 相机连接、边拍边传、三品牌驱动与 SwiftUI 历史导入页,通过适配层对接现有本地上传与 OSS 管道。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-06 11:22:07 +08:00
parent d7fec35715
commit be9c844bd3
50 changed files with 5721 additions and 20 deletions

View File

@ -233,6 +233,47 @@ final class WiredCameraTransferViewModelTests: XCTestCase {
XCTAssertEqual(store.loadTransferModeOption(), WiredCameraTransferViewModel.modePostShootTransfer)
}
/// ConnectionState CameraConnectionState
func testConnectionStateMapsToCameraConnectionState() {
XCTAssertEqual(ConnectionState.idle.cameraConnectionState, .disconnected)
XCTAssertEqual(ConnectionState.disconnected.cameraConnectionState, .disconnected)
XCTAssertEqual(ConnectionState.searching.cameraConnectionState, .searching)
XCTAssertEqual(ConnectionState.connecting(deviceName: "EOS R5").cameraConnectionState, .connecting)
XCTAssertEqual(
ConnectionState.connected(platform: .sony, deviceName: "ILCE-7M4").cameraConnectionState,
.connected(deviceName: "ILCE-7M4")
)
XCTAssertEqual(
ConnectionState.failed(message: "授权被拒绝").cameraConnectionState,
.error("授权被拒绝")
)
}
/// ingest
func testPipelineIngestAutoUploadUploadsAsset() async throws {
let scope = CameraDownloadStorage.Scope(accountKey: "otg-pipe", albumID: 42)
let fileURL = CameraDownloadStorage.uniqueLocalURL(for: "otg_live.JPG", scope: scope)
try Data(repeating: 0xAA, count: 32).write(to: fileURL)
defer { CameraDownloadStorage.removeScopeDirectory(for: scope) }
let pipeline = WiredCameraTransferPipeline()
let sink = MockCameraAssetUploadSink()
let relativePath = CameraDownloadStorage.relativePath(for: fileURL)
pipeline.configure(uploadSink: sink, uploadEnabled: true, downloadScope: scope)
pipeline.ingestDownloadedAsset(
assetID: "obj-1",
filename: "otg_live.JPG",
localPath: relativePath,
capturedAt: Date(),
autoUpload: true
)
try await Task.sleep(nanoseconds: 800_000_000)
XCTAssertEqual(sink.uploadedFileNames, ["otg_live.JPG"])
XCTAssertEqual(pipeline.task(forAssetID: "obj-1")?.status, .uploaded)
}
///
func testStartRestoresCachedTransferModeOption() async {
let account = makeTransferModeTestAccount()
@ -466,6 +507,22 @@ final class WiredCameraTransferViewModelTests: XCTestCase {
}
}
@MainActor
private final class MockCameraAssetUploadSink: CameraAssetUploadSink {
private(set) var uploadedFileNames: [String] = []
func upload(
localURL: URL,
fileName: String,
fileType: Int,
progress: @escaping @Sendable (Int) -> Void
) async throws -> String {
uploadedFileNames.append(fileName)
progress(100)
return "https://cdn/mock/\(fileName)"
}
}
@MainActor
private final class MockTravelAlbumAPIForWiredTransfer: TravelAlbumServing {
func availableOrders() async throws -> [TravelAlbumAvailableOrder] { [] }