OpenTabsTransition.swift 5.43 KB
//  Transition.swift
//  browser
//
//  Created by Artem Talko on 23.11.2023.
//

import UIKit


final class OpenTabsTransition: NSObject, UIViewControllerAnimatedTransitioning {
    private var operation: UINavigationController.Operation
    
    init(operation: UINavigationController.Operation) {
        self.operation = operation
        
        super.init()
    }
    
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.6
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let toController = transitionContext.viewController(forKey: .to),
              let fromController = transitionContext.viewController(forKey: .from) else {
            transitionContext.completeTransition(true)
            return
        }
        switch operation {
        case .push :
            pushController(fromController: fromController, toController: toController, transitionContext: transitionContext)
        case .pop:
            popController(fromController: fromController, toController: toController, transitionContext: transitionContext)
        case .none:
            transitionContext.completeTransition(true)
            return
        @unknown default:
            break
        }
    }
}


//MARK: animation handlers
extension OpenTabsTransition {
    private func pushController(fromController: UIViewController, toController: UIViewController, transitionContext: UIViewControllerContextTransitioning) {
        let container = transitionContext.containerView
        guard let tabsController = fromController as? TabsViewController else {
            transitionContext.completeTransition(true)
            return
        }
        guard let browserHomeController = toController as? BrowserHomeViewController else {
            transitionContext.completeTransition(true)
            return
        }
        let cellIndexPathForTransition = tabsController.getCellIndex()
        
        container.insertSubview(browserHomeController.mainView, at: 0)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) {
            let tabsCollectionView = tabsController.mainView.openedTabsCollectionView
            tabsCollectionView.scrollToItem(at: cellIndexPathForTransition, at: .bottom, animated: false)
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) {
                let cell = tabsController.mainView.openedTabsCollectionView.cellForItem(at: cellIndexPathForTransition)
                let browserHomeImage = UIImageView()
                browserHomeImage.image = SnapshotService.shared.makeSnapshot(browserHomeController.mainView)
                
                guard let lastTab = cell as? OpenedTabsCollectionViewCell else {
                    return
                }
                lastTab.isHidden = true
                
                container.addSubview(browserHomeImage)
                browserHomeImage.frame = lastTab.frame
                UIView.animate(withDuration: 0.2) {
                    browserHomeImage.frame = UIScreen.main.bounds
                } completion: { _ in
                    browserHomeImage.removeFromSuperview()
                    lastTab.isHidden = false
                    transitionContext.completeTransition(true)
                }
            }
        }
    }
    
    private func popController(fromController: UIViewController, toController: UIViewController, transitionContext: UIViewControllerContextTransitioning) {
        let container = transitionContext.containerView
        guard let tabsController = toController as? TabsViewController else {
            transitionContext.completeTransition(true)
            return
        }
        guard let browserHomeController = fromController as? BrowserHomeViewController else {
            transitionContext.completeTransition(true)
            return
        }
        let cellIndexPathForTransition = tabsController.getCellIndex()
        
        container.insertSubview(tabsController.mainView, at: 0)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) {
            let tabsCollectionView = tabsController.mainView.openedTabsCollectionView
            tabsCollectionView.scrollToItem(at: cellIndexPathForTransition, at: .bottom, animated: false)
            let lastItemIndex = tabsController.getCellIndex()
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) {
                let cell = tabsController.mainView.openedTabsCollectionView.cellForItem(at: lastItemIndex)
                let browserHomeImage = UIImageView()
                browserHomeImage.image = SnapshotService.shared.makeSnapshot(browserHomeController.mainView)
                
                guard let lastTab = cell as? OpenedTabsCollectionViewCell else {
                    return
                }
                lastTab.isHidden = true
                
                container.addSubview(browserHomeImage)
                browserHomeImage.frame = browserHomeController.mainView.frame
                UIView.animate(withDuration: 0.2) {
                    fromController.view.isHidden = true
                    browserHomeImage.frame = lastTab.convertFrameToScreenCoordinates() ?? CGRect()
                } completion: { _ in
                    browserHomeImage.removeFromSuperview()
                    lastTab.isHidden = false
                    transitionContext.completeTransition(true)
                }
            }
        }
    }
}