Skip to content
Snippets Groups Projects
Presenting.swift 3.39 KiB
Newer Older
Bruno Muniz's avatar
Bruno Muniz committed
import UIKit
import Theme

public protocol Presenting {
    func present(_ target: UIViewController, from parent: UIViewController)
    func dismiss(from parent: UIViewController)
}

public extension Presenting {
    func dismiss(from parent: UIViewController) {
        parent.dismiss(animated: true)
    }
}

public struct PushPresenter: Presenting {
    public init() {}

    public func present(_ target: UIViewController, from parent: UIViewController) {
        parent.navigationController?.pushViewController(target, animated: true)
    }
}

public struct ModalPresenter: Presenting {
    public init() {}

    public func present(_ target: UIViewController, from parent: UIViewController) {
        let statusBarVC = StatusBarViewController(target)
        statusBarVC.modalPresentationStyle = .fullScreen
        parent.present(statusBarVC, animated: true)
    }
}

public struct ReplacePresenter: Presenting {
    public enum Mode {
        case replaceAll
        case replaceLast
        case replaceBackwards(AnyObject.Type)
    }

    var mode: Mode

    public init(mode: Mode = .replaceAll) {
        self.mode = mode
    }

    public func present(_ target: UIViewController, from parent: UIViewController) {
        guard let navigationController = parent.navigationController else { return }

        switch mode {
        case .replaceAll:
            navigationController.setViewControllers([target], animated: true)

        case .replaceBackwards(let OlderInStack):
            if let oldScreen = navigationController.viewControllers.filter({ $0.isKind(of: OlderInStack.self) }).first,
               let index = navigationController.viewControllers.firstIndex(of: oldScreen) {

                let viewControllersBefore =
                    navigationController.viewControllers.dropLast(
                        navigationController.viewControllers.count - index
                    )

                if let coordinator = navigationController.transitionCoordinator {
                    coordinator.animate(alongsideTransition: nil) { _ in
                        navigationController.setViewControllers(viewControllersBefore + [target] , animated: true)
                    }
                } else {
                    navigationController.setViewControllers(viewControllersBefore + [target] , animated: true)
                }

            } else {
                navigationController.pushViewController(target, animated: true)
            }
        case .replaceLast:
            let viewControllersBefore = navigationController.viewControllers.dropLast()

            func replace() {
                navigationController.setViewControllers(viewControllersBefore + [target] , animated: true)
            }

            if let coordinator = navigationController.transitionCoordinator {
                coordinator.animate(alongsideTransition: nil) { _ in
                    replace()
                }
            } else {
                replace()
            }
        }
    }
}

public struct PopReplacePresenter: Presenting {
    public init() {}

    public func present(_ target: UIViewController, from parent: UIViewController) {
        if let lastViewController = parent.navigationController?.viewControllers.last {
            parent.navigationController?.setViewControllers([target, lastViewController], animated: false)
            parent.navigationController?.setViewControllers([target], animated: true)
        }
    }
}