Fix profile page switching on iOS 18
This commit is contained in:
parent
703f6f695b
commit
348dcc558c
|
@ -38,10 +38,12 @@ class ProfileHeaderCollectionViewCell: UICollectionViewCell {
|
|||
header.translatesAutoresizingMaskIntoConstraints = false
|
||||
contentView.embedSubview(header)
|
||||
self.state = .view(header)
|
||||
case .view(_):
|
||||
case .view(let existing):
|
||||
if existing !== header {
|
||||
fatalError("profile header collection view cell already has view")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addConstraint(height: CGFloat) -> ProfileHeaderView? {
|
||||
switch state {
|
||||
|
|
|
@ -17,7 +17,7 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
|
|||
let filterer: Filterer
|
||||
private(set) var accountID: String!
|
||||
let kind: Kind
|
||||
var initialHeaderMode: HeaderMode?
|
||||
var headerViewMode: HeaderMode?
|
||||
weak var profileHeaderDelegate: ProfileHeaderViewDelegate?
|
||||
|
||||
private(set) var controller: TimelineLikeController<TimelineItem>!
|
||||
|
@ -30,7 +30,9 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
|
|||
view as? UICollectionView
|
||||
}
|
||||
private(set) var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
|
||||
private(set) var headerCell: ProfileHeaderCollectionViewCell?
|
||||
var headerCell: ProfileHeaderCollectionViewCell? {
|
||||
collectionView.cellForItem(at: IndexPath(item: 0, section: 0)) as? ProfileHeaderCollectionViewCell
|
||||
}
|
||||
|
||||
var reconfigureVisibleItemsOnEndDecelerating: Bool = false
|
||||
|
||||
|
@ -173,29 +175,29 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
|
|||
return UICollectionViewDiffableDataSource(collectionView: collectionView) { [unowned self] collectionView, indexPath, itemIdentifier in
|
||||
switch itemIdentifier {
|
||||
case .header(let id):
|
||||
if let headerCell = self.headerCell {
|
||||
headerCell.view?.updateUI(for: id)
|
||||
return headerCell
|
||||
} else {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "headerCell", for: indexPath) as! ProfileHeaderCollectionViewCell
|
||||
switch self.initialHeaderMode {
|
||||
switch self.headerViewMode {
|
||||
case nil:
|
||||
fatalError("missing initialHeaderMode")
|
||||
case .createView:
|
||||
fatalError("missing headerViewMode")
|
||||
case .createViewIfNeeded:
|
||||
if let view = cell.view {
|
||||
view.updateUI(for: id)
|
||||
self.headerViewMode = .useExistingView(view)
|
||||
} else {
|
||||
let view = ProfileHeaderView.create()
|
||||
view.delegate = self.profileHeaderDelegate
|
||||
view.updateUI(for: id)
|
||||
view.pagesSegmentedControl.setSelectedOption(self.owner!.currentPage, animated: false)
|
||||
cell.addHeader(view)
|
||||
self.headerViewMode = .useExistingView(view)
|
||||
}
|
||||
case .useExistingView(let view):
|
||||
view.updateUI(for: id)
|
||||
cell.addHeader(view)
|
||||
case .placeholder(height: let height):
|
||||
_ = cell.addConstraint(height: height)
|
||||
}
|
||||
self.headerCell = cell
|
||||
return cell
|
||||
}
|
||||
case .status(id: let id, collapseState: let collapseState, filterState: let filterState, pinned: let pinned):
|
||||
let (result, precomputedContent) = filterResult(state: filterState, statusID: id)
|
||||
switch result {
|
||||
|
@ -411,7 +413,9 @@ extension ProfileStatusesViewController {
|
|||
case statuses, withReplies, onlyMedia
|
||||
}
|
||||
enum HeaderMode {
|
||||
case createView, useExistingView(ProfileHeaderView), placeholder(height: CGFloat)
|
||||
case createViewIfNeeded
|
||||
case useExistingView(ProfileHeaderView)
|
||||
case placeholder(height: CGFloat)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ class ProfileViewController: UIViewController, StateRestorableViewController {
|
|||
guard let currentIndex else {
|
||||
assert(!animated)
|
||||
// if old doesn't exist, we're selecting the initial view controller, so moving the header around isn't necessary
|
||||
new.initialHeaderMode = .createView
|
||||
new.headerViewMode = .createViewIfNeeded
|
||||
new.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
addChild(new)
|
||||
view.addSubview(new.view)
|
||||
|
@ -213,11 +213,14 @@ class ProfileViewController: UIViewController, StateRestorableViewController {
|
|||
|
||||
// old header cell must have the header view
|
||||
let headerView = oldHeaderCell.addConstraint(height: oldHeaderCell.bounds.height)!
|
||||
// Set the outgoing VC's header view mode to placeholder, so that it does steal the header view back
|
||||
// in case it updates the cell in the background.
|
||||
old.headerViewMode = .placeholder(height: oldHeaderCell.bounds.height)
|
||||
|
||||
if let newHeaderCell = new.headerCell {
|
||||
_ = newHeaderCell.addConstraint(height: oldHeaderCell.bounds.height)
|
||||
} else {
|
||||
new.initialHeaderMode = .placeholder(height: oldHeaderCell.bounds.height)
|
||||
new.headerViewMode = .placeholder(height: oldHeaderCell.bounds.height)
|
||||
}
|
||||
|
||||
// disable user interaction during animation, to avoid any potential weird race conditions
|
||||
|
@ -285,7 +288,7 @@ class ProfileViewController: UIViewController, StateRestorableViewController {
|
|||
if let newHeaderCell = new.headerCell {
|
||||
newHeaderCell.addHeader(headerView)
|
||||
} else {
|
||||
new.initialHeaderMode = .useExistingView(headerView)
|
||||
new.headerViewMode = .useExistingView(headerView)
|
||||
}
|
||||
|
||||
self.state = .idle
|
||||
|
|
Loading…
Reference in New Issue