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