Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix FXIOS-10756 App hangs while opening Tab Tray when there are many tabs open #23474

Merged
merged 7 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions firefox-ios/Client/Frontend/Browser/SwipeAnimator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,15 @@ extension SwipeAnimator {
// Calculate the edge to calculate distance from
let translation = velocity.x >= 0 ? animatingView.frame.width : -animatingView.frame.width
let timeStep = TimeInterval(abs(translation) / speed)
self.delegate?.swipeAnimator(self)
UIView.animate(
withDuration: timeStep,
animations: {
animatingView.transform = self.transformForTranslation(translation)
animatingView.alpha = self.alphaForDistanceFromCenter(abs(translation))
}, completion: { finished in
}, completion: { [weak self] finished in
if let self {
delegate?.swipeAnimator(self)
}
if finished {
animatingView.alpha = 0
}
Expand Down
16 changes: 8 additions & 8 deletions firefox-ios/Client/Frontend/Browser/Tabs/Views/TabCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class TabCell: UICollectionViewCell, ThemeApplicable, ReusableCell {

private lazy var smallFaviconView: FaviconImageView = .build()
private lazy var favicon: FaviconImageView = .build()
private var headerView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
private lazy var headerView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))

// MARK: - UI

Expand Down Expand Up @@ -82,8 +82,8 @@ class TabCell: UICollectionViewCell, ThemeApplicable, ReusableCell {

override init(frame: CGRect) {
super.init(frame: frame)
self.animator = SwipeAnimator(animatingView: self)
self.closeButton.addTarget(self, action: #selector(close), for: .touchUpInside)
animator = SwipeAnimator(animatingView: self)
closeButton.addTarget(self, action: #selector(close), for: .touchUpInside)

contentView.addSubview(backgroundHolder)

Expand All @@ -92,14 +92,14 @@ class TabCell: UICollectionViewCell, ThemeApplicable, ReusableCell {

accessibilityCustomActions = [
UIAccessibilityCustomAction(name: .TabTrayCloseAccessibilityCustomAction,
target: self.animator,
target: animator,
selector: #selector(SwipeAnimator.closeWithoutGesture))
]

headerView.translatesAutoresizingMaskIntoConstraints = false
headerView.contentView.addSubview(self.closeButton)
headerView.contentView.addSubview(self.titleText)
headerView.contentView.addSubview(self.favicon)
headerView.contentView.addSubview(closeButton)
headerView.contentView.addSubview(titleText)
headerView.contentView.addSubview(favicon)

setupConstraints()
}
Expand All @@ -112,7 +112,7 @@ class TabCell: UICollectionViewCell, ThemeApplicable, ReusableCell {
self.delegate = delegate

if let swipeAnimatorDelegate = delegate as? SwipeAnimatorDelegate {
self.animator?.delegate = swipeAnimatorDelegate
animator?.delegate = swipeAnimatorDelegate
}

animator?.animateBackToCenter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ class TabDisplayPanelViewController: UIViewController,
super.viewWillAppear(animated)

if !viewHasAppeared {
tabDisplayView.layoutIfNeeded()
store.dispatch(TabPanelViewAction(panelType: panelType,
windowUUID: windowUUID,
actionType: TabPanelViewActionType.tabPanelWillAppear))
Expand Down Expand Up @@ -162,6 +161,8 @@ class TabDisplayPanelViewController: UIViewController,
}

func newState(state: TabsPanelState) {
guard state != tabsState else { return }

tabsState = state
tabDisplayView.newState(state: tabsState)
shouldShowEmptyView(tabsState.isPrivateTabsEmpty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,19 +127,14 @@ class TabDisplayView: UIView,
private func scrollToTab(_ scrollState: TabsPanelState.ScrollState) {
let section: Int = scrollState.isInactiveTabSection ? 0 : 1
let indexPath = IndexPath(row: scrollState.toIndex, section: section)

// We cannot get the visible cells unless all layout operations have finished finished (e.g. after `reloadData()`)
collectionView.layoutIfNeeded()

// Only scroll to the view if it is not visible.
guard !collectionView.indexPathsForFullyVisibleItems.contains(indexPath) else { return }

// Scrolling to an invalid cell will crash the app, so check indexPath first
guard collectionView.isValid(indexPath: indexPath) else { return }

collectionView.scrollToItem(at: indexPath,
at: .centeredVertically,
animated: scrollState.withAnimation)
// Piping this into main thread let the collection view finish its layout process
DispatchQueue.main.async {
guard !self.collectionView.indexPathsForFullyVisibleItems.contains(indexPath) else { return }
guard self.collectionView.isValid(indexPath: indexPath) else { return }
self.collectionView.scrollToItem(at: indexPath,
at: .centeredVertically,
animated: scrollState.withAnimation)
}
}

private func configureDataSource() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,12 @@ class TabTrayViewController: UIViewController,
}

func newState(state: TabTrayState) {
guard state != tabTrayState else { return }

tabTrayState = state
updateTabCountImage(count: state.normalTabsCount)
segmentedControl.selectedSegmentIndex = state.selectedPanel.rawValue

updateTabCountImage(count: tabTrayState.normalTabsCount)
segmentedControl.selectedSegmentIndex = tabTrayState.selectedPanel.rawValue

if tabTrayState.shouldDismiss {
delegate?.didFinish()
Expand All @@ -303,7 +306,7 @@ class TabTrayViewController: UIViewController,
showCloseAllConfirmation()
}

if let toastType = state.toastType {
if let toastType = tabTrayState.toastType {
presentToast(toastType: toastType) { [weak self] undoClose in
guard let self else { return }

Expand Down