feat: 优化AI修图模板选择界面

This commit is contained in:
2026-08-11 17:04:51 +08:00
parent aca19a53fb
commit 010add828b
4 changed files with 593 additions and 77 deletions
@@ -21,6 +21,12 @@ final class TravelAlbumAIRetouchTemplateViewModelTests: XCTestCase {
XCTAssertEqual(api.aiRetouchTemplateScenicIds, [18])
XCTAssertEqual(viewModel.workflow, .initial(albumId: 8, materialIds: [1, 2, 3, 4]))
XCTAssertEqual(viewModel.selectedPhotoCount, 4)
XCTAssertTrue(viewModel.shouldShowInitialTips)
XCTAssertEqual(
viewModel.initialTipsText,
"Tips:本次显示 3 类风格。每张照片生成「精修后 + 氛围感」2 个结果,第一张照片另生成所选封面结果。"
)
XCTAssertEqual(viewModel.visibleCategories, [.refined, .atmosphere, .cover])
XCTAssertEqual(viewModel.selectedRefinedTemplateId, 11)
XCTAssertNil(viewModel.selectedAtmosphereTemplateId)
@@ -95,6 +101,8 @@ final class TravelAlbumAIRetouchTemplateViewModelTests: XCTestCase {
workflow: .reretouch(materialId: 7, batchId: 70, type: .refined)
)
await refined.loadTemplates(api: api)
XCTAssertEqual(refined.selectedPhotoCount, 1)
XCTAssertFalse(refined.shouldShowInitialTips)
XCTAssertEqual(refined.visibleCategories, [.refined])
XCTAssertEqual(refined.selectedRefinedTemplateId, 11)
XCTAssertNil(refined.selectedAtmosphereTemplateId)
@@ -296,7 +296,33 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
await waitUntil { confirmButton.isEnabled }
controller.view.layoutIfNeeded()
let selectionCountLabel = try XCTUnwrap(
controller.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchSelectionCountLabel"
} as? UILabel
)
let tipsLabel = try XCTUnwrap(
controller.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchTipsLabel"
} as? UILabel
)
let tipsContainer = try XCTUnwrap(
controller.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchTipsContainer"
}
)
XCTAssertTrue(collectionView.collectionViewLayout is UICollectionViewCompositionalLayout)
XCTAssertEqual(selectionCountLabel.text, "已选择 4 张照片")
XCTAssertEqual(
tipsLabel.text,
"Tips:本次显示 3 类风格。每张照片生成「精修后 + 氛围感」2 个结果,第一张照片另生成所选封面结果。"
)
XCTAssertFalse(tipsContainer.isHidden)
XCTAssertEqual(tipsContainer.backgroundColor?.travelAlbumTestHexRGB, 0xEAF3FF)
XCTAssertEqual(tipsLabel.textColor.travelAlbumTestHexRGB, 0x385778)
XCTAssertEqual(tipsContainer.layer.cornerRadius, 10)
XCTAssertTrue(tipsContainer.isDescendant(of: collectionView))
XCTAssertFalse(bottomBar.isDescendant(of: collectionView))
XCTAssertEqual(cancelButton.configuration?.title, "取消")
XCTAssertEqual(confirmButton.configuration?.title, "确定")
@@ -327,29 +353,47 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
await waitUntil { !viewModel.isLoading && api.aiRetouchTemplateScenicIds.count == 1 }
controller.view.layoutIfNeeded()
let collectionView = try XCTUnwrap(
controller.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchTemplateCollection"
} as? UICollectionView
)
let accessibleLabels = controller.view.allAccessibilityLabels()
XCTAssertTrue(accessibleLabels.contains("原图精修"))
XCTAssertTrue(accessibleLabels.contains("氛围感修图,选填"))
XCTAssertTrue(accessibleLabels.contains("封面风格模板"))
XCTAssertTrue(accessibleLabels.contains("封面风格模板,赠送 · 不占精修张数"))
collectionView.scrollToItem(
at: IndexPath(item: 0, section: 4),
at: .top,
animated: false
)
controller.view.layoutIfNeeded()
let quotaLabel = try XCTUnwrap(
controller.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchRemainingQuotaLabel"
} as? UILabel
)
XCTAssertEqual(quotaLabel.text, "剩余 8 次")
XCTAssertEqual(quotaLabel.accessibilityLabel, "剩余8次修图额度")
XCTAssertEqual(quotaLabel.text, "剩余 8 张")
XCTAssertEqual(quotaLabel.accessibilityLabel, "剩余8张修图额度")
}
func testAIRetouchTemplateCellExposesSelectedState() {
let cell = TravelAlbumAIRetouchTemplateCell(frame: .zero)
let template = TravelAlbumAIRetouchTemplate(id: 1, name: "清透", previewURL: "")
var previewTapped = false
cell.onPreviewTapped = { previewTapped = true }
cell.apply(template: template, selected: true)
let previewButton = cell.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchTemplatePreviewButton"
} as? UIButton
previewButton?.sendActions(for: .touchUpInside)
XCTAssertEqual(cell.contentView.layer.borderWidth, 2)
XCTAssertTrue(cell.accessibilityTraits.contains(.selected))
XCTAssertEqual(cell.accessibilityValue, "已选择")
XCTAssertTrue(previewTapped)
cell.apply(template: template, selected: false)
@@ -358,6 +402,37 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
XCTAssertEqual(cell.accessibilityValue, "未选择")
}
func testAIRetouchTemplatePreviewUsesImmersiveZoomableLayout() throws {
let template = TravelAlbumAIRetouchTemplate(
id: 2,
name: "简约留白",
previewURL: ""
)
let controller = TravelAlbumAIRetouchTemplatePreviewViewController(template: template)
controller.loadViewIfNeeded()
controller.view.frame = CGRect(x: 0, y: 0, width: 390, height: 844)
controller.view.layoutIfNeeded()
let scrollView = try XCTUnwrap(
controller.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchTemplatePreviewScrollView"
} as? UIScrollView
)
let backButton = try XCTUnwrap(
controller.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchTemplatePreviewBackButton"
} as? UIButton
)
XCTAssertEqual(controller.view.backgroundColor, .black)
XCTAssertTrue(controller.view.allLabels().contains { $0.text == "简约留白" })
XCTAssertTrue(controller.view.allLabels().contains { $0.text == "双指缩放查看细节" })
XCTAssertEqual(scrollView.minimumZoomScale, 1)
XCTAssertEqual(scrollView.maximumZoomScale, 4)
XCTAssertGreaterThanOrEqual(backButton.bounds.width, 44)
XCTAssertGreaterThanOrEqual(backButton.bounds.height, 44)
}
func testPreviewAIRetouchUsesSelectedRetouchedTabWorkflowAndStaysPresented() async throws {
UIView.setAnimationsEnabled(false)
defer { UIView.setAnimationsEnabled(true) }
@@ -424,9 +499,29 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase {
sheet.view.frame = CGRect(x: 0, y: 0, width: 390, height: 844)
sheet.view.layoutIfNeeded()
let labels = sheet.view.allAccessibilityLabels()
XCTAssertTrue(labels.contains("原图精修"))
XCTAssertFalse(labels.contains { $0.contains("氛围感修图") })
let visibleLabelTexts = sheet.view.allLabels().compactMap { label in
label.isHidden ? nil : label.text
}
XCTAssertTrue(visibleLabelTexts.contains("原图精修"))
XCTAssertFalse(visibleLabelTexts.contains { $0.contains("氛围感修图") })
let selectionCountLabel = try XCTUnwrap(
sheet.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchSelectionCountLabel"
} as? UILabel
)
let tipsLabel = try XCTUnwrap(
sheet.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchTipsLabel"
} as? UILabel
)
let tipsContainer = try XCTUnwrap(
sheet.view.findSubview {
$0.accessibilityIdentifier == "travelAlbum.aiRetouchTipsContainer"
}
)
XCTAssertEqual(selectionCountLabel.text, "已选择 1 张照片")
XCTAssertTrue(tipsContainer.isHidden)
XCTAssertTrue(tipsLabel.isHidden)
confirmButton.sendActions(for: .touchUpInside)
await waitUntil { api.aiReretouchRequests.count == 1 }
await waitUntil { controller.presentedViewController == nil }