Skip to content
Open
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
78 changes: 78 additions & 0 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ extension UINavigationController {
CATransaction.commit()
}

func setViewControllers(
_ viewControllers: [UIViewController],
animated: Bool,
completion: (() -> Void)?
) {
CATransaction.begin()
CATransaction.setCompletionBlock(completion)

setViewControllers(viewControllers, animated: animated)

CATransaction.commit()
}

func popViewController(
animated: Bool,
completion: (() -> Void)?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,28 @@ import SwiftUIX
extension UIViewController {
public func trigger(
_ transition: ViewTransition,
animated: Bool,
completion: @escaping () -> ()
) throws {
switch transition.finalize() {
case .present(let view): do {
presentOnTop(view, named: transition.payloadViewName, animated: animated) {
presentOnTop(view, named: transition.payloadViewName, animated: transition.animated) {
completion()
}
}

case .replace(let view): do {
if let viewController = topmostPresentedViewController?.presentingViewController {
viewController.dismiss(animated: animated) {
viewController.dismiss(animated: transition.animated) {
viewController.presentOnTop(
view,
named: transition.payloadViewName,
animated: animated
animated: transition.animated
) {
completion()
}
}
} else {
presentOnTop(view, named: transition.payloadViewName, animated: animated) {
presentOnTop(view, named: transition.payloadViewName, animated: transition.animated) {
completion()
}
}
Expand All @@ -44,7 +43,7 @@ extension UIViewController {
throw ViewTransition.Error.nothingToDismiss
}

dismiss(animated: animated) {
dismiss(animated: transition.animated) {
completion()
}
}
Expand All @@ -62,7 +61,7 @@ extension UIViewController {

navigationController.pushViewController(
view._toAppKitOrUIKitViewController(),
animated: animated
animated: transition.animated
) {
completion()
}
Expand All @@ -72,12 +71,12 @@ extension UIViewController {
if let navigationController = nearestNavigationController {
navigationController.pushViewController(
view._toAppKitOrUIKitViewController(),
animated: animated
animated: transition.animated
) {
completion()
}
} else {
presentOnTop(view, named: transition.payloadViewName, animated: animated) {
presentOnTop(view, named: transition.payloadViewName, animated: transition.animated) {
completion()
}
}
Expand All @@ -88,7 +87,7 @@ extension UIViewController {
throw ViewTransition.Error.navigationControllerMissing
}

viewController.popViewController(animated: animated) {
viewController.popViewController(animated: transition.animated) {
completion()
}
}
Expand All @@ -98,38 +97,38 @@ extension UIViewController {
throw ViewTransition.Error.navigationControllerMissing
}

viewController.popToRootViewController(animated: animated) {
viewController.popToRootViewController(animated: transition.animated) {
completion()
}
}

case .popOrDismiss: do {
if let navigationController = nearestNavigationController, navigationController.viewControllers.count > 1 {
navigationController.popViewController(animated: animated) {
navigationController.popViewController(animated: transition.animated) {
completion()
}
} else {
guard presentedViewController != nil else {
throw ViewTransition.Error.nothingToDismiss
}

dismiss(animated: animated) {
dismiss(animated: transition.animated) {
completion()
}
}
}

case .popToRootOrDismiss: do {
if let navigationController = nearestNavigationController, navigationController.viewControllers.count > 1 {
navigationController.popToRootViewController(animated: animated) {
navigationController.popToRootViewController(animated: transition.animated) {
completion()
}
} else {
guard presentedViewController != nil else {
throw ViewTransition.Error.nothingToDismiss
}

dismiss(animated: animated) {
dismiss(animated: transition.animated) {
completion()
}
}
Expand All @@ -151,7 +150,7 @@ extension UIViewController {

case .set(let view, _): do {
if let viewController = nearestNavigationController {
viewController.setViewControllers([view._toAppKitOrUIKitViewController()], animated: animated)
viewController.setViewControllers([view._toAppKitOrUIKitViewController()], animated: transition.animated)

completion()
} else if let window = self.view.window, window.rootViewController === self {
Expand All @@ -163,13 +162,26 @@ extension UIViewController {

completion()
} else if topmostPresentedViewController != nil {
dismiss(animated: animated) {
self.presentOnTop(view, named: transition.payloadViewName, animated: animated) {
dismiss(animated: transition.animated) {
self.presentOnTop(view, named: transition.payloadViewName, animated: transition.animated) {
completion()
}
}
}
}

case .setMany(let views): do {
guard let navigationController = nearestNavigationController else {
throw ViewTransition.Error.navigationControllerMissing
}

navigationController.setViewControllers(
views.map { $0._toAppKitOrUIKitViewController() },
animated: transition.animated
) {
completion()
}
}

case .linear(var transitions): do {
guard !transitions.isEmpty else {
Expand All @@ -178,11 +190,12 @@ extension UIViewController {

var _error: Error?

let firstTransition = transitions.removeFirst()
var firstTransition = transitions.removeFirst()
firstTransition.animated = transition.animated && firstTransition.animated

try trigger(firstTransition, animated: animated) {
try trigger(firstTransition) {
do {
try self.trigger(.linear(transitions), animated: animated) {
try self.trigger(.linear(transitions)) {
completion()
}
} catch {
Expand Down Expand Up @@ -218,18 +231,17 @@ extension ViewTransition {
@_transparent
func triggerPublisher<VC: ViewCoordinator>(
in controller: UIViewController,
animated: Bool,
coordinator: VC
) -> AnyPublisher<ViewTransitionContext, Swift.Error> {
let transition = merge(coordinator: coordinator)

if case .custom(let trigger) = transition.finalize() {
return trigger()
return trigger(animated)
}

return Future { attemptToFulfill in
do {
try controller.trigger(transition, animated: animated) {
try controller.trigger(transition) {
attemptToFulfill(.success(transition))
}
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ extension ViewTransition {
coordinator: Coordinator
) -> AnyPublisher<ViewTransitionContext, Swift.Error> {
let transition = merge(coordinator: coordinator)
let animated = transition.animated

if case .custom(let trigger) = transition.finalize() {
return trigger()
return trigger(animated)
}

return Future { attemptToFulfill in
Expand Down Expand Up @@ -54,7 +53,7 @@ extension ViewTransition {
}
default: do {
do {
try window.rootViewController.unwrap().trigger(transition, animated: animated) {
try window.rootViewController.unwrap().trigger(transition) {
attemptToFulfill(.success(self))
}
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,19 @@ open class UIViewControllerCoordinator<Route>: _AppKitOrUIKitViewCoordinatorBase
fatalError()
}

public override func triggerPublisher(for route: Route) -> AnyPublisher<ViewTransitionContext, Error> {
public override func triggerPublisher(for route: Route, animated: Bool = true) -> AnyPublisher<ViewTransitionContext, Error> {
guard let rootViewController = rootViewController else {
runtimeIssue("Could not resolve a root view controller.")

return .failure(TriggerError.rootViewControllerMissing)
}

return transition(for: route)
var transition = transition(for: route)
transition.animated = animated

return transition
.environment(environmentInsertions)
.triggerPublisher(in: rootViewController, animated: true, coordinator: self)
.triggerPublisher(in: rootViewController, coordinator: self)
.handleOutput { [weak self] _ in
self?.updateAllChildren()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ open class AppKitOrUIKitWindowCoordinator<Route>: _AppKitOrUIKitViewCoordinatorB

@discardableResult
override public func triggerPublisher(
for route: Route
for route: Route,
animated: Bool = true
) -> AnyPublisher<ViewTransitionContext, Error> {
do {
let window = try self.window.unwrap()

return transition(for: route)
var transition = transition(for: route)
transition.animated = animated

return transition
.environment(environmentInsertions)
.triggerPublisher(in: window, coordinator: self)
.handleOutput { [weak self] _ in
Expand All @@ -80,9 +84,10 @@ open class AppKitOrUIKitWindowCoordinator<Route>: _AppKitOrUIKitViewCoordinatorB

@discardableResult
override public func trigger(
_ route: Route
_ route: Route,
animated: Bool = true
) -> AnyPublisher<ViewTransitionContext, Error> {
super.trigger(route)
super.trigger(route, animated: animated)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,13 @@ open class _AppKitOrUIKitViewCoordinatorBase<Route>: _opaque_AppKitOrUIKitViewCo
fatalError()
}

public func triggerPublisher(for route: Route) -> AnyPublisher<ViewTransitionContext, Error> {
public func triggerPublisher(for route: Route, animated: Bool) -> AnyPublisher<ViewTransitionContext, Error> {
Empty().eraseToAnyPublisher()
}

@discardableResult
public func trigger(_ route: Route) -> AnyPublisher<ViewTransitionContext, Error> {
let publisher = triggerPublisher(for: route)
public func trigger(_ route: Route, animated: Bool = true) -> AnyPublisher<ViewTransitionContext, Error> {
let publisher = triggerPublisher(for: route, animated: animated)
let result = PassthroughSubject<ViewTransitionContext, Error>()

publisher.subscribe(result, in: cancellables)
Expand Down
Loading