diff --git a/Tusker/Screens/Account List/AccountListViewController.swift b/Tusker/Screens/Account List/AccountListViewController.swift index 72f5dbcc..6bf8dd3a 100644 --- a/Tusker/Screens/Account List/AccountListViewController.swift +++ b/Tusker/Screens/Account List/AccountListViewController.swift @@ -8,13 +8,13 @@ import UIKit -class AccountListViewController: UIViewController { +class AccountListViewController: UIViewController, CollectionViewController { typealias Item = String private let mastodonController: MastodonController private let accountIDs: [String] - private var collectionView: UICollectionView { + var collectionView: UICollectionView! { view as! UICollectionView } private var dataSource: UICollectionViewDiffableDataSource! @@ -61,9 +61,7 @@ class AccountListViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - collectionView.indexPathsForSelectedItems?.forEach { - collectionView.deselectItem(at: $0, animated: true) - } + clearSelectionOnAppear(animated: animated) } } diff --git a/Tusker/Screens/Explore/ExploreViewController.swift b/Tusker/Screens/Explore/ExploreViewController.swift index ebfd12c5..1bd25407 100644 --- a/Tusker/Screens/Explore/ExploreViewController.swift +++ b/Tusker/Screens/Explore/ExploreViewController.swift @@ -12,11 +12,11 @@ import Pachyderm import CoreData import WebURLFoundationExtras -class ExploreViewController: UIViewController, UICollectionViewDelegate { +class ExploreViewController: UIViewController, UICollectionViewDelegate, CollectionViewController { weak var mastodonController: MastodonController! - private var collectionView: UICollectionView! + var collectionView: UICollectionView! private var dataSource: UICollectionViewDiffableDataSource! private(set) var resultsController: SearchResultsViewController! @@ -95,15 +95,7 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - // Can't use UICollectionViewController's builtin version of this because it requires - // the collection view layout be passed into the constructor. Swipe actions for list collection views - // are created by passing a closure to the layout's configuration. This closure needs to capture - // `self`, so it can't be passed into the super constructor. - if let indexPaths = collectionView.indexPathsForSelectedItems { - for indexPath in indexPaths { - collectionView.deselectItem(at: indexPath, animated: true) - } - } + clearSelectionOnAppear(animated: animated) } override func viewDidAppear(_ animated: Bool) { diff --git a/Tusker/Screens/Profile/ProfileStatusesViewController.swift b/Tusker/Screens/Profile/ProfileStatusesViewController.swift index 83cb107c..a7b06a7f 100644 --- a/Tusker/Screens/Profile/ProfileStatusesViewController.swift +++ b/Tusker/Screens/Profile/ProfileStatusesViewController.swift @@ -10,7 +10,7 @@ import UIKit import Pachyderm import Combine -class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionViewController { +class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionViewController, CollectionViewController { weak var owner: ProfileViewController? let mastodonController: MastodonController @@ -188,9 +188,7 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - collectionView.indexPathsForSelectedItems?.forEach { - collectionView.deselectItem(at: $0, animated: true) - } + clearSelectionOnAppear(animated: animated) Task { if case .notLoadedInitial = controller.state { diff --git a/Tusker/Screens/Status Action Account List/StatusActionAccountListViewController.swift b/Tusker/Screens/Status Action Account List/StatusActionAccountListViewController.swift index b556de92..e2aee53d 100644 --- a/Tusker/Screens/Status Action Account List/StatusActionAccountListViewController.swift +++ b/Tusker/Screens/Status Action Account List/StatusActionAccountListViewController.swift @@ -9,7 +9,7 @@ import UIKit import Pachyderm -class StatusActionAccountListViewController: UIViewController { +class StatusActionAccountListViewController: UIViewController, CollectionViewController { private let mastodonController: MastodonController private let actionType: ActionType @@ -20,8 +20,8 @@ class StatusActionAccountListViewController: UIViewController { /// If `true`, a warning will be shown below the account list describing that the total favs/reblogs may be innacurate. var showInacurateCountWarning = false - private var collectionView: UICollectionView { - view as! UICollectionView + var collectionView: UICollectionView! { + view as? UICollectionView } private var dataSource: UICollectionViewDiffableDataSource! @@ -120,9 +120,7 @@ class StatusActionAccountListViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - collectionView.indexPathsForSelectedItems?.forEach { - collectionView.deselectItem(at: $0, animated: true) - } + clearSelectionOnAppear(animated: animated) if accountIDs == nil { Task { diff --git a/Tusker/Screens/Timeline/TimelineViewController.swift b/Tusker/Screens/Timeline/TimelineViewController.swift index bac71bda..eda5f7cb 100644 --- a/Tusker/Screens/Timeline/TimelineViewController.swift +++ b/Tusker/Screens/Timeline/TimelineViewController.swift @@ -210,9 +210,7 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - collectionView.indexPathsForSelectedItems?.forEach { - collectionView.deselectItem(at: $0, animated: true) - } + clearSelectionOnAppear(animated: animated) if case .notLoadedInitial = controller.state { if restoreState() { diff --git a/Tusker/Screens/Utilities/CollectionViewController.swift b/Tusker/Screens/Utilities/CollectionViewController.swift index b1a084c2..22b6fcc2 100644 --- a/Tusker/Screens/Utilities/CollectionViewController.swift +++ b/Tusker/Screens/Utilities/CollectionViewController.swift @@ -11,3 +11,23 @@ import UIKit protocol CollectionViewController: UIViewController { var collectionView: UICollectionView! { get } } + +extension CollectionViewController { + func clearSelectionOnAppear(animated: Bool) { + guard let indexPath = collectionView.indexPathsForSelectedItems?.first else { + return + } + if let transitionCoordinator { + transitionCoordinator.animate { context in + self.collectionView.deselectItem(at: indexPath, animated: true) + } completion: { context in + if context.isCancelled { + self.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: [] /* UICollectionViewScrollPositionNone */) + } + } + + } else { + collectionView.deselectItem(at: indexPath, animated: animated) + } + } +}