Skip to content

Commit

Permalink
Merge MasterCoordinator start methods to an adaptive one
Browse files Browse the repository at this point in the history
  • Loading branch information
mvasilak committed Sep 8, 2023
1 parent 2174252 commit 9d8ea20
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 51 deletions.
56 changes: 34 additions & 22 deletions Zotero/Scenes/Master/MasterContainerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ final class MasterContainerViewController: UINavigationController {
private static let bottomContainerTappableHeight: CGFloat = 35
private static let bottomContainerDraggableHeight: CGFloat = 55
private static let minVisibleBottomHeight: CGFloat = 200
let bottomController: DraggableViewController
private let disposeBag: DisposeBag

private var bottomContainer: UIView!
Expand All @@ -52,11 +51,40 @@ final class MasterContainerViewController: UINavigationController {
// Used to calculate position and velocity when dragging
private var initialBottomMinY: CGFloat?
private var keyboardHeight: CGFloat = 0

private var _bottomController: DraggableViewController?
var bottomController: DraggableViewController? {
if _bottomController != nil {
return _bottomController
}
guard let bottomController = coordinatorDelegate?.bottomController() else { return nil }
setupBottomController()
_bottomController = bottomController
return _bottomController

func setupBottomController() {
bottomController.view.translatesAutoresizingMaskIntoConstraints = false
// Since the instance keeps a strong reference to the bottomController, its view is simply added as a subview.
// Adding bottomController as a child view controller, would mess up the navigation stack.
bottomContainer.addSubview(bottomController.view)
let bottomControllerHeight = bottomController.view.heightAnchor.constraint(greaterThanOrEqualToConstant: 100)
bottomControllerHeight.priority = .required
let bottomControllerBottom = bottomController.view.bottomAnchor.constraint(equalTo: bottomContainer.bottomAnchor)
bottomControllerBottom.priority = UILayoutPriority(999)
NSLayoutConstraint.activate([
// bottom controller view
bottomController.view.topAnchor.constraint(equalTo: bottomContainer.topAnchor, constant: Self.bottomControllerHandleHeight),
bottomController.view.leadingAnchor.constraint(equalTo: bottomContainer.leadingAnchor),
bottomController.view.trailingAnchor.constraint(equalTo: bottomContainer.trailingAnchor),
bottomControllerHeight,
bottomControllerBottom
])
}
}

private weak var coordinatorDelegate: MasterContainerCoordinatorDelegate?

init(bottomController: DraggableViewController, coordinatorDelegate: MasterContainerCoordinatorDelegate) {
self.bottomController = bottomController
init(coordinatorDelegate: MasterContainerCoordinatorDelegate) {
self.coordinatorDelegate = coordinatorDelegate
self.bottomPosition = .default
self.didAppear = false
Expand All @@ -78,8 +106,6 @@ final class MasterContainerViewController: UINavigationController {
showBottomSheet(false)

func setupView() {
bottomController.view.translatesAutoresizingMaskIntoConstraints = false

let bottomPanRecognizer = UIPanGestureRecognizer()
bottomPanRecognizer.delegate = self
bottomPanRecognizer.rx.event
Expand All @@ -106,10 +132,6 @@ final class MasterContainerViewController: UINavigationController {
view.addSubview(bottomContainer)
self.bottomContainer = bottomContainer

// Since the instance keeps a strong reference to the bottomController, its view is simply added as a subview.
// Adding bottomController as a child view controller, would mess up the navigation stack.
bottomContainer.addSubview(bottomController.view)

let handleBackground = UIView()
handleBackground.translatesAutoresizingMaskIntoConstraints = false
handleBackground.backgroundColor = .systemBackground
Expand All @@ -126,10 +148,6 @@ final class MasterContainerViewController: UINavigationController {
bottomContainer.addSubview(separator)

let bottomYConstraint = bottomContainer.topAnchor.constraint(equalTo: view.topAnchor)
let bottomControllerHeight = bottomController.view.heightAnchor.constraint(greaterThanOrEqualToConstant: 100)
bottomControllerHeight.priority = .required
let bottomControllerBottom = bottomController.view.bottomAnchor.constraint(equalTo: bottomContainer.bottomAnchor)
bottomControllerBottom.priority = UILayoutPriority(999)
let bottomContainerBottomConstraint = view.bottomAnchor.constraint(equalTo: bottomContainer.bottomAnchor)

// bottom container contains from top to bottom:
Expand All @@ -148,12 +166,6 @@ final class MasterContainerViewController: UINavigationController {
// drag icon
dragIcon.centerXAnchor.constraint(equalTo: bottomContainer.centerXAnchor),
dragIcon.topAnchor.constraint(equalTo: bottomContainer.topAnchor, constant: Self.dragHandleTopOffset),
// bottom controller view
bottomController.view.topAnchor.constraint(equalTo: bottomContainer.topAnchor, constant: Self.bottomControllerHandleHeight),
bottomController.view.leadingAnchor.constraint(equalTo: bottomContainer.leadingAnchor),
bottomController.view.trailingAnchor.constraint(equalTo: bottomContainer.trailingAnchor),
bottomControllerHeight,
bottomControllerBottom,
// separator
separator.heightAnchor.constraint(equalToConstant: 1 / UIScreen.main.scale),
separator.topAnchor.constraint(equalTo: bottomContainer.topAnchor),
Expand All @@ -168,7 +180,7 @@ final class MasterContainerViewController: UINavigationController {
switch recognizer.state {
case .began:
initialBottomMinY = self.bottomContainer.frame.minY
bottomController.disablePanning()
bottomController?.disablePanning()

case .changed:
guard let initialBottomMinY else { return }
Expand Down Expand Up @@ -206,7 +218,7 @@ final class MasterContainerViewController: UINavigationController {
}

initialBottomMinY = nil
bottomController.enablePanning()
bottomController?.enablePanning()

case .cancelled, .possible:
break
Expand Down Expand Up @@ -349,7 +361,7 @@ final class MasterContainerViewController: UINavigationController {

// MARK: - Bottom panning
private func showBottomSheet(_ show: Bool) {
if show {
if show, bottomController != nil {
bottomContainer.isHidden = false
additionalSafeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: 16, right: 0)
} else {
Expand Down
40 changes: 11 additions & 29 deletions Zotero/Scenes/Master/MasterCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import CocoaLumberjackSwift

protocol MasterContainerCoordinatorDelegate: AnyObject {
func showDefaultCollection()
func bottomController() -> DraggableViewController?
}

final class MasterCoordinator {
Expand All @@ -30,38 +31,10 @@ final class MasterCoordinator {
}

func start() {
switch UIDevice.current.userInterfaceIdiom {
case .pad:
self.startPad()

default:
self.startPhone()
}
}

private func startPad() {
guard let dbStorage = self.controllers.userControllers?.dbStorage else { return }

let state = TagFilterState(selectedTags: [], showAutomatic: Defaults.shared.tagPickerShowAutomaticTags, displayAll: Defaults.shared.tagPickerDisplayAllTags)
let handler = TagFilterActionHandler(dbStorage: dbStorage)
let viewModel = ViewModel(initialState: state, handler: handler)
let tagController = TagFilterViewController(viewModel: viewModel, dragDropController: self.controllers.dragDropController)

let containerController = MasterContainerViewController(bottomController: tagController, coordinatorDelegate: self)
let masterController = containerController
let masterController = MasterContainerViewController(coordinatorDelegate: self)
let masterCoordinator = MasterTopCoordinator(navigationController: masterController, mainCoordinatorDelegate: self.mainController, controllers: self.controllers)
masterCoordinator.start(animated: false)
self.topCoordinator = masterCoordinator
self.mainController.viewControllers = [containerController]
}

// TODO: Merge startPad() and startPhone() methods to one adaptive workflow
private func startPhone() {
let masterController = UINavigationController()
let masterCoordinator = MasterTopCoordinator(navigationController: masterController, mainCoordinatorDelegate: self.mainController, controllers: self.controllers)
masterCoordinator.start(animated: false)
self.topCoordinator = masterCoordinator

self.mainController.viewControllers = [masterController]
}
}
Expand All @@ -70,4 +43,13 @@ extension MasterCoordinator: MasterContainerCoordinatorDelegate {
func showDefaultCollection() {
topCoordinator?.showDefaultCollection()
}

func bottomController() -> DraggableViewController? {
guard UIDevice.current.userInterfaceIdiom == .pad else { return nil }
guard let dbStorage = controllers.userControllers?.dbStorage else { return nil }
let state = TagFilterState(selectedTags: [], showAutomatic: Defaults.shared.tagPickerShowAutomaticTags, displayAll: Defaults.shared.tagPickerDisplayAllTags)
let handler = TagFilterActionHandler(dbStorage: dbStorage)
let viewModel = ViewModel(initialState: state, handler: handler)
return TagFilterViewController(viewModel: viewModel, dragDropController: controllers.dragDropController)
}
}

0 comments on commit 9d8ea20

Please sign in to comment.