feat: add AI retouch before-after comparison
This commit is contained in:
@@ -48,6 +48,7 @@ final class TravelAlbumPhotoPreviewViewController: UIViewController {
|
||||
private let variantControls = UIView()
|
||||
private let variantSegmentedControl = UISegmentedControl()
|
||||
private let highResolutionButton = UIButton(type: .system)
|
||||
private let comparisonButton = UIButton(type: .system)
|
||||
private let actionStack = UIStackView()
|
||||
private let deleteButton = UIButton(type: .system)
|
||||
private let refreshButton = UIButton(type: .system)
|
||||
@@ -193,6 +194,7 @@ final class TravelAlbumPhotoPreviewViewController: UIViewController {
|
||||
)
|
||||
actionStack.accessibilityIdentifier = "travelAlbum.previewActionStack"
|
||||
configureHighResolutionButton()
|
||||
configureComparisonButton()
|
||||
configureActions()
|
||||
|
||||
let titleStack = UIStackView(arrangedSubviews: [titleLabel, sizeLabel])
|
||||
@@ -212,6 +214,7 @@ final class TravelAlbumPhotoPreviewViewController: UIViewController {
|
||||
variantControls.addSubview(variantSegmentedControl)
|
||||
variantControls.addSubview(highResolutionButton)
|
||||
bottomChrome.addSubview(actionStack)
|
||||
view.addSubview(comparisonButton)
|
||||
|
||||
topChrome.snp.makeConstraints { make in
|
||||
make.top.leading.trailing.equalToSuperview()
|
||||
@@ -274,6 +277,11 @@ final class TravelAlbumPhotoPreviewViewController: UIViewController {
|
||||
make.height.equalTo(70)
|
||||
make.bottom.equalTo(view.safeAreaLayoutGuide)
|
||||
}
|
||||
comparisonButton.snp.makeConstraints { make in
|
||||
make.trailing.equalToSuperview().inset(16)
|
||||
make.bottom.equalTo(bottomChrome.snp.top).offset(-12)
|
||||
make.size.equalTo(48)
|
||||
}
|
||||
}
|
||||
|
||||
private func configureHighResolutionButton() {
|
||||
@@ -293,6 +301,27 @@ final class TravelAlbumPhotoPreviewViewController: UIViewController {
|
||||
highResolutionButton.addTarget(self, action: #selector(highResolutionTapped), for: .touchUpInside)
|
||||
}
|
||||
|
||||
private func configureComparisonButton() {
|
||||
var configuration = UIButton.Configuration.filled()
|
||||
configuration.image = UIImage(named: "travel_album_before_after")?.withRenderingMode(.alwaysTemplate)
|
||||
configuration.contentInsets = .zero
|
||||
configuration.baseForegroundColor = .white
|
||||
configuration.baseBackgroundColor = UIColor(hex: 0x111827).withAlphaComponent(0.94)
|
||||
configuration.background.cornerRadius = 24
|
||||
configuration.background.strokeColor = UIColor(hex: 0x263244)
|
||||
configuration.background.strokeWidth = 1
|
||||
comparisonButton.configuration = configuration
|
||||
comparisonButton.accessibilityLabel = "前后对比"
|
||||
comparisonButton.accessibilityHint = "对比当前效果图与原图"
|
||||
comparisonButton.accessibilityIdentifier = "travelAlbum.previewComparisonButton"
|
||||
comparisonButton.layer.shadowColor = UIColor.black.cgColor
|
||||
comparisonButton.layer.shadowOpacity = 0.28
|
||||
comparisonButton.layer.shadowRadius = 8
|
||||
comparisonButton.layer.shadowOffset = CGSize(width: 0, height: 3)
|
||||
comparisonButton.isHidden = true
|
||||
comparisonButton.addTarget(self, action: #selector(comparisonTapped), for: .touchUpInside)
|
||||
}
|
||||
|
||||
private func configureActions() {
|
||||
let aiButton = makeActionButton(
|
||||
title: "AI修图",
|
||||
@@ -392,9 +421,21 @@ final class TravelAlbumPhotoPreviewViewController: UIViewController {
|
||||
highResolutionButton.isEnabled = asset != nil
|
||||
highResolutionButton.alpha = asset == nil ? 0.45 : 1
|
||||
rebuildTabs()
|
||||
updateComparisonButton()
|
||||
loadMoreIfNeeded(projectIndex: node.projectIndex)
|
||||
}
|
||||
|
||||
private func updateComparisonButton() {
|
||||
let hasComparison = currentProject?.comparisonContent(for: currentAsset?.kind ?? .original) != nil
|
||||
let shouldShow = chromeVisible && hasComparison
|
||||
comparisonButton.isHidden = !hasComparison
|
||||
comparisonButton.isUserInteractionEnabled = shouldShow
|
||||
comparisonButton.alpha = shouldShow ? 1 : 0
|
||||
comparisonButton.transform = shouldShow
|
||||
? .identity
|
||||
: CGAffineTransform(translationX: 0, y: 10)
|
||||
}
|
||||
|
||||
private func rebuildTabs() {
|
||||
while variantSegmentedControl.numberOfSegments > 0 {
|
||||
variantSegmentedControl.removeSegment(at: 0, animated: false)
|
||||
@@ -581,6 +622,11 @@ final class TravelAlbumPhotoPreviewViewController: UIViewController {
|
||||
|
||||
private func toggleChrome() {
|
||||
chromeVisible.toggle()
|
||||
let hasComparison = currentProject?.comparisonContent(for: currentAsset?.kind ?? .original) != nil
|
||||
if chromeVisible && hasComparison {
|
||||
comparisonButton.isHidden = false
|
||||
}
|
||||
comparisonButton.isUserInteractionEnabled = chromeVisible && hasComparison
|
||||
let reduceMotion = UIAccessibility.isReduceMotionEnabled
|
||||
let animations = {
|
||||
self.topChrome.alpha = self.chromeVisible ? 1 : 0
|
||||
@@ -591,12 +637,20 @@ final class TravelAlbumPhotoPreviewViewController: UIViewController {
|
||||
self.bottomChrome.transform = self.chromeVisible
|
||||
? .identity
|
||||
: CGAffineTransform(translationX: 0, y: self.bottomChrome.bounds.height)
|
||||
self.comparisonButton.alpha = self.chromeVisible && hasComparison ? 1 : 0
|
||||
self.comparisonButton.transform = self.chromeVisible && hasComparison
|
||||
? .identity
|
||||
: CGAffineTransform(translationX: 0, y: 10)
|
||||
}
|
||||
UIView.animate(
|
||||
withDuration: reduceMotion ? 0.12 : 0.22,
|
||||
delay: 0,
|
||||
options: reduceMotion ? [.curveEaseOut] : [.curveEaseOut, .beginFromCurrentState],
|
||||
animations: animations
|
||||
animations: animations,
|
||||
completion: { [weak self] _ in
|
||||
guard let self else { return }
|
||||
self.comparisonButton.isHidden = !self.chromeVisible || !hasComparison
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -632,6 +686,17 @@ final class TravelAlbumPhotoPreviewViewController: UIViewController {
|
||||
toggleChrome()
|
||||
}
|
||||
|
||||
@objc private func comparisonTapped() {
|
||||
guard presentedViewController == nil,
|
||||
let project = currentProject,
|
||||
let content = project.comparisonContent(for: currentAsset?.kind ?? .original)
|
||||
else { return }
|
||||
let controller = BeforeAfterComparisonViewController(
|
||||
viewModel: BeforeAfterComparisonViewModel(content: content)
|
||||
)
|
||||
present(controller, animated: true)
|
||||
}
|
||||
|
||||
@objc private func aiTapped() {
|
||||
guard presentedViewController == nil else { return }
|
||||
guard let project = currentProject else { return }
|
||||
|
||||
Reference in New Issue
Block a user