diff --git a/AltStore/Browse/FeaturedViewController.swift b/AltStore/Browse/FeaturedViewController.swift index 1d751b91..cfbfb60e 100644 --- a/AltStore/Browse/FeaturedViewController.swift +++ b/AltStore/Browse/FeaturedViewController.swift @@ -363,6 +363,7 @@ private extension FeaturedViewController dataSource.cellConfigurationHandler = { cell, storeApp, indexPath in let cell = cell as! AppCardCollectionViewCell cell.configure(for: storeApp) + cell.prefersPagingScreenshots = false cell.bannerView.button.addTarget(self, action: #selector(FeaturedViewController.performAppAction), for: .primaryActionTriggered) cell.bannerView.sourceIconImageView.isHidden = true diff --git a/AltStore/Components/AppCardCollectionViewCell.swift b/AltStore/Components/AppCardCollectionViewCell.swift index 9e25089d..d06c1eb5 100644 --- a/AltStore/Components/AppCardCollectionViewCell.swift +++ b/AltStore/Components/AppCardCollectionViewCell.swift @@ -20,9 +20,13 @@ class AppCardCollectionViewCell: UICollectionViewCell let bannerView: AppBannerView let captionLabel: UILabel + var prefersPagingScreenshots = true + private let screenshotsCollectionView: UICollectionView private let stackView: UIStackView + private let topAreaPanGestureRecognizer: UIPanGestureRecognizer + private lazy var dataSource = self.makeDataSource() private var screenshots: [AppScreenshot] = [] { @@ -81,6 +85,12 @@ class AppCardCollectionViewCell: UICollectionViewCell let spacing = (inset * 2) + (minimumItemSpacing * 2) self.collectionViewAspectRatioConstraint = self.screenshotsCollectionView.widthAnchor.constraint(equalTo: self.screenshotsCollectionView.heightAnchor, multiplier: multiplier, constant: spacing) + // Allows us to ignore swipes in top portion of screenshotsCollectionView. + self.topAreaPanGestureRecognizer = UIPanGestureRecognizer(target: nil, action: nil) + self.topAreaPanGestureRecognizer.cancelsTouchesInView = false + self.topAreaPanGestureRecognizer.delaysTouchesBegan = false + self.topAreaPanGestureRecognizer.delaysTouchesEnded = false + super.init(frame: frame) self.contentView.clipsToBounds = true @@ -101,6 +111,10 @@ class AppCardCollectionViewCell: UICollectionViewCell tapGestureRecognizer.delaysTouchesEnded = false self.screenshotsCollectionView.addGestureRecognizer(tapGestureRecognizer) + self.topAreaPanGestureRecognizer.delegate = self + self.screenshotsCollectionView.panGestureRecognizer.require(toFail: self.topAreaPanGestureRecognizer) + self.screenshotsCollectionView.addGestureRecognizer(self.topAreaPanGestureRecognizer) + self.screenshotsCollectionView.register(AppScreenshotCollectionViewCell.self, forCellWithReuseIdentifier: RSTCellContentGenericCellIdentifier) self.stackView.isLayoutMarginsRelativeArrangement = true @@ -324,3 +338,51 @@ extension AppCardCollectionViewCell } } } + +extension AppCardCollectionViewCell: UIGestureRecognizerDelegate +{ + override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool + { + // Never recognize topAreaPanGestureRecognizer unless prefersPagingScreenshots is false. + guard !self.prefersPagingScreenshots else { return false } + + let point = gestureRecognizer.location(in: self.screenshotsCollectionView) + + // Top area = Top 3/4 + let isTopArea = point.y < (self.screenshotsCollectionView.bounds.height / 4) * 3 + return isTopArea + } + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool + { + guard let panGestureRecognizer = otherGestureRecognizer as? UIPanGestureRecognizer, let view = panGestureRecognizer.view else { return false } + + if view.isDescendant(of: self.screenshotsCollectionView) + { + // Only allow nested gesture recognizers if topAreaPanGestureRecognizer fails. + return true + } + else + { + // Always allow parent gesture recognizers. + return false + } + } + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool + { + guard let panGestureRecognizer = otherGestureRecognizer as? UIPanGestureRecognizer, let view = panGestureRecognizer.view else { return true } + + if view.isDescendant(of: self.screenshotsCollectionView) + { + // Don't recognize topAreaPanGestureRecognizer alongside nested gesture recognizers. + return false + } + else + { + // Allow recognizing simultaneously with parent gesture recognizers. + // This fixes accidentally breaking scrolling in parent. + return true + } + } +}