diff --git a/Reader/Screens/Home/HomeViewController.swift b/Reader/Screens/Home/HomeViewController.swift index cf8570f..a15319d 100644 --- a/Reader/Screens/Home/HomeViewController.swift +++ b/Reader/Screens/Home/HomeViewController.swift @@ -214,6 +214,7 @@ extension HomeViewController: UICollectionViewDelegate { let vc = ItemsViewController(fetchRequest: item.fetchRequest, fervorController: fervorController) vc.title = item.title show(vc, sender: nil) + UISelectionFeedbackGenerator().selectionChanged() } func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { diff --git a/Reader/Screens/Items/ItemCollectionViewCell.swift b/Reader/Screens/Items/ItemCollectionViewCell.swift index 7203524..a41ae08 100644 --- a/Reader/Screens/Items/ItemCollectionViewCell.swift +++ b/Reader/Screens/Items/ItemCollectionViewCell.swift @@ -19,10 +19,12 @@ class ItemCollectionViewCell: UICollectionViewListCell { private let titleLabel = UILabel() private let feedTitleLabel = UILabel() private let contentLabel = UILabel() - private var shouldHighlight = true + private var shouldInteractOnNextTouch = true private var item: Item! + private lazy var feedbackGenerator = UISelectionFeedbackGenerator() + override init(frame: CGRect) { super.init(frame: frame) @@ -55,7 +57,7 @@ class ItemCollectionViewCell: UICollectionViewListCell { ]) let doubleTap = DoubleTapRecognizer(target: self, action: #selector(cellDoubleTapped)) - doubleTap.onTouchesBegan = highlightCell + doubleTap.onTouchesBegan = onDoubleTapBegan addGestureRecognizer(doubleTap) let singleTap = UITapGestureRecognizer(target: self, action: #selector(cellSingleTapped)) @@ -108,13 +110,10 @@ class ItemCollectionViewCell: UICollectionViewListCell { } } - override func touchesBegan(_ touches: Set, with event: UIEvent?) { - highlightCell() - } - - @objc private func highlightCell() { - guard shouldHighlight else { return } - shouldHighlight = false + private func onDoubleTapBegan() { + guard shouldInteractOnNextTouch else { return } + shouldInteractOnNextTouch = false + feedbackGenerator.prepare() UIView.animateKeyframes(withDuration: 0.4, delay: 0, options: .allowUserInteraction) { UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5) { self.backgroundColor = .appCellHighlightBackground @@ -127,12 +126,14 @@ class ItemCollectionViewCell: UICollectionViewListCell { @objc private func cellDoubleTapped() { setRead(!item.read, animated: true) - shouldHighlight = true + shouldInteractOnNextTouch = true + feedbackGenerator.selectionChanged() } @objc private func cellSingleTapped() { delegate?.itemCellSelected(cell: self, item: item) - shouldHighlight = true + shouldInteractOnNextTouch = true + feedbackGenerator.selectionChanged() } } @@ -149,5 +150,12 @@ private class DoubleTapRecognizer: UITapGestureRecognizer { override func touchesBegan(_ touches: Set, with event: UIEvent) { super.touchesBegan(touches, with: event) onTouchesBegan() + // shorten the delay before the single tap is recognized + DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) { [weak self] in + guard let self = self else { return } + if self.state != .recognized { + self.state = .failed + } + } } }