对齐有线传图页 Android UI,并改用相对路径持久化本地照片。

还原顶栏、浮动卡片、时间侧栏与底部交互;照片路径改为 CameraDownloads 相对路径并兼容旧数据;格式 Chip 固定 JPG 且不可点击。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-30 11:16:28 +08:00
parent e91a46c315
commit c71b45bdfd
29 changed files with 2097 additions and 256 deletions

View File

@ -82,6 +82,93 @@ final class WiredCameraTransferViewModelTests: XCTestCase {
XCTAssertTrue(viewModel.photos.isEmpty)
}
///
func testBatchUploadButtonThreeStateFlow() async {
let viewModel = makeViewModelWithPendingPhotos()
let api = MockTravelAlbumAPIForWiredTransfer()
let oss = WiredTransferMockOSSUploadService()
XCTAssertFalse(viewModel.selectUploadMode)
await viewModel.onBatchUploadButtonClick(api: api, ossService: oss, scenicID: 1)
XCTAssertTrue(viewModel.selectUploadMode)
XCTAssertTrue(viewModel.selectedPhotoIDs.isEmpty)
viewModel.togglePhotoSelection(id: "pending-1")
XCTAssertEqual(viewModel.selectedPhotoIDs, ["pending-1"])
await viewModel.onBatchUploadButtonClick(api: api, ossService: oss, scenicID: 1)
XCTAssertFalse(viewModel.selectUploadMode)
XCTAssertTrue(viewModel.selectedPhotoIDs.isEmpty)
}
/// pending
func testToggleSelectAllPendingInVisible() {
let viewModel = makeViewModelWithPendingPhotos()
viewModel.selectUploadMode = true
viewModel.toggleSelectAllPendingInVisible()
XCTAssertEqual(viewModel.selectedPhotoIDs, ["pending-1", "pending-2"])
viewModel.toggleSelectAllPendingInVisible()
XCTAssertTrue(viewModel.selectedPhotoIDs.isEmpty)
}
///
func testUploadAllTodayCapturedFiltersByDate() async {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.locale = Locale(identifier: "zh_CN")
let today = formatter.string(from: Date())
let viewModel = WiredCameraTransferViewModel(
context: WiredTransferContext(albumId: 1, albumName: "相册", phone: "", orderNumber: ""),
cameraService: MockWiredCameraService()
)
viewModel.photos = [
makePendingPhoto(id: "today", capturedAt: today),
makePendingPhoto(id: "old", capturedAt: "2020-01-01 09:00:00"),
]
await viewModel.onSpecifyUploadOptionSelected(
WiredCameraTransferViewModel.specifyUploadTodayCaptured,
api: MockTravelAlbumAPIForWiredTransfer(),
ossService: WiredTransferMockOSSUploadService(),
scenicID: 1
)
XCTAssertNil(viewModel.errorMessage)
}
private func makeViewModelWithPendingPhotos() -> WiredCameraTransferViewModel {
let viewModel = WiredCameraTransferViewModel(
context: WiredTransferContext(albumId: 1, albumName: "相册", phone: "", orderNumber: ""),
cameraService: MockWiredCameraService()
)
viewModel.photos = [
makePendingPhoto(id: "pending-1", capturedAt: "2026-05-20 12:05:18"),
makePendingPhoto(id: "pending-2", capturedAt: "2026-05-20 12:18:06"),
WiredTransferPhotoItem(
id: "uploaded-1",
fileName: "uploaded.JPG",
thumbnailURL: "",
capturedAt: "2026-05-20 12:20:00",
fileSizeText: "1 MB",
status: .uploaded
),
]
return viewModel
}
private func makePendingPhoto(id: String, capturedAt: String) -> WiredTransferPhotoItem {
WiredTransferPhotoItem(
id: id,
fileName: "\(id).JPG",
thumbnailURL: "",
capturedAt: capturedAt,
fileSizeText: "1 MB",
status: .pending
)
}
}
@MainActor

View File

@ -0,0 +1,68 @@
//
// WiredTransferPhotoGroupingTests.swift
// suixinkanTests
//
import XCTest
@testable import suixinkan
/// 线
final class WiredTransferPhotoGroupingTests: XCTestCase {
/// 30
func testBuildPhotoSectionsAndSidebarGroups() {
let photos = [
makePhoto(id: "1", capturedAt: "2026-05-20 12:05:18", status: .uploaded),
makePhoto(id: "2", capturedAt: "2026-05-20 12:18:06", status: .pending),
makePhoto(id: "3", capturedAt: "2026-05-20 11:55:51", status: .failed),
]
let sections = photos.buildPhotoSections()
XCTAssertEqual(sections.count, 2)
XCTAssertEqual(sections[0].photos.count, 2)
XCTAssertTrue(sections[0].headerTitle.contains("12:00 - 12:30"))
let sidebar = photos.buildSidebarGroups()
XCTAssertEqual(sidebar.count, 1)
XCTAssertEqual(sidebar[0].slots.count, 2)
XCTAssertEqual(sidebar[0].slots[0].photoCount, 2)
}
///
func testIsCapturedTodayUsesLocalCalendar() {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.locale = Locale(identifier: "zh_CN")
let today = formatter.string(from: Date())
let photo = makePhoto(id: "today", capturedAt: today, status: .pending)
XCTAssertTrue(photo.isCapturedToday())
XCTAssertFalse(makePhoto(id: "old", capturedAt: "2020-01-01 10:00:00", status: .pending).isCapturedToday())
}
/// Tab pending
func testTransferTabCountsAndSelectablePendingIDs() {
let photos = [
makePhoto(id: "1", capturedAt: "2026-05-20 12:05:18", status: .uploaded),
makePhoto(id: "2", capturedAt: "2026-05-20 12:18:06", status: .pending),
makePhoto(id: "3", capturedAt: "2026-05-20 12:35:44", status: .failed),
]
XCTAssertEqual(photos.transferTabCounts, [3, 1, 1])
XCTAssertEqual(photos.selectablePendingPhotoIDs, ["2"])
}
private func makePhoto(
id: String,
capturedAt: String,
status: WiredTransferUploadStatus
) -> WiredTransferPhotoItem {
WiredTransferPhotoItem(
id: id,
fileName: "\(id).JPG",
thumbnailURL: "",
capturedAt: capturedAt,
fileSizeText: "1.00 MB",
resolutionText: "4032x3024",
status: status
)
}
}