diff --git a/NOICommunity/Coordinator/Implementations/Base/BaseCoordinator.swift b/NOICommunity/Coordinator/Implementations/Base/BaseCoordinator.swift index 21a8177..cebc384 100644 --- a/NOICommunity/Coordinator/Implementations/Base/BaseCoordinator.swift +++ b/NOICommunity/Coordinator/Implementations/Base/BaseCoordinator.swift @@ -16,7 +16,14 @@ class BaseCoordinator: NSObject, CoordinatorType { var childCoordinators: [CoordinatorType] = [] var dependencyContainer: DependencyRepresentable - + + var topViewController: UIViewController? { + guard let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? UIWindowSceneDelegate + else { return nil } + + return sceneDelegate.window??.topViewController + } + @available(*, unavailable) override init() { fatalError("\(#function) not available") diff --git a/NOICommunity/Coordinator/Implementations/Custom/AppCoordinator.swift b/NOICommunity/Coordinator/Implementations/Custom/AppCoordinator.swift index 7a0ba4a..70a75b8 100644 --- a/NOICommunity/Coordinator/Implementations/Custom/AppCoordinator.swift +++ b/NOICommunity/Coordinator/Implementations/Custom/AppCoordinator.swift @@ -31,7 +31,7 @@ final class AppCoordinator: BaseNavigationCoordinator { private var pendingDeepLinkIntent: DeepLinkIntent? private weak var tabCoordinator: TabCoordinator! - + override func start(animated: Bool) { NotificationCenter .default @@ -202,6 +202,9 @@ private extension AppCoordinator { } func showNewsDetails(newsId: String, sender: Any?) { + guard let topViewController + else { return } + func configureBindings( viewModel: NewsDetailsViewModel, pageViewController: NewsPageViewController @@ -243,10 +246,9 @@ private extension AppCoordinator { pageVC.navigationItem.largeTitleDisplayMode = .never pageVC.navigationItem.leftBarButtonItem = UIBarButtonItem( image: UIImage(systemName: "xmark.circle.fill"), - style: .plain, - target: self, - action: #selector(closeModal(sender:)) - ) + primaryAction: UIAction { [weak pageVC] _ in + pageVC?.dismiss(animated: true) + }) pageVC.modalPresentationStyle = .fullScreen return pageVC @@ -256,8 +258,8 @@ private extension AppCoordinator { viewModel: viewModel, pageViewController: pageVC ) - - navigationController.present( + + topViewController.present( NavigationController(rootViewController: pageVC), animated: true ) @@ -309,6 +311,9 @@ private extension AppCoordinator { } func showEventDetails(eventId: String, sender: Any?) { + guard let topViewController + else { return } + func configureBindings( viewModel: EventDetailsViewModel, pageViewController: EventPageViewController @@ -354,10 +359,9 @@ private extension AppCoordinator { pageVC.navigationItem.largeTitleDisplayMode = .never pageVC.navigationItem.leftBarButtonItem = UIBarButtonItem( image: UIImage(systemName: "xmark.circle.fill"), - style: .plain, - target: self, - action: #selector(closeModal(sender:)) - ) + primaryAction: UIAction { [weak pageVC] _ in + pageVC?.dismiss(animated: true) + }) pageVC.modalPresentationStyle = .fullScreen return pageVC @@ -365,16 +369,12 @@ private extension AppCoordinator { configureBindings(viewModel: viewModel, pageViewController: pageVC) - navigationController.present( + topViewController.present( NavigationController(rootViewController: pageVC), animated: true ) } - @objc func closeModal(sender: Any?) { - navigationController.dismiss(animated: true) - } - func showAccessNotGrantedCoordinator(animated: Bool) { let accessNotGrantedCoordinator = AccessNotGrantedCoordinator( navigationController: navigationController, diff --git a/NOICommunity/EventsFeature/View Controllers/EventPageViewController.swift b/NOICommunity/EventsFeature/View Controllers/EventPageViewController.swift index 4a49a22..77adff0 100644 --- a/NOICommunity/EventsFeature/View Controllers/EventPageViewController.swift +++ b/NOICommunity/EventsFeature/View Controllers/EventPageViewController.swift @@ -27,19 +27,25 @@ final class EventPageViewController: BasePageViewController Void)? { didSet { - eventDetailsViewController?.locateActionHandler = locateActionHandler + eventDetailsViewController?.locateActionHandler = { [weak self] in + self?.locateActionHandler?($0) + } } } var addToCalendarActionHandler: ((Event) -> Void)? { didSet { - eventDetailsViewController?.addToCalendarActionHandler = addToCalendarActionHandler + eventDetailsViewController?.addToCalendarActionHandler = { [weak self] in + self?.addToCalendarActionHandler?($0) + } } } var signupActionHandler: ((Event) -> Void)? { didSet { - eventDetailsViewController?.signupActionHandler = signupActionHandler + eventDetailsViewController?.signupActionHandler = { [weak self] in + self?.signupActionHandler?($0) + } } } @@ -93,9 +99,15 @@ private extension EventPageViewController { func makeResultContent(for event: Event) -> EventDetailsViewController { let result = EventDetailsViewController(for: event) - result.locateActionHandler = locateActionHandler - result.addToCalendarActionHandler = addToCalendarActionHandler - result.signupActionHandler = signupActionHandler + result.locateActionHandler = { [weak self] in + self?.locateActionHandler?($0) + } + result.addToCalendarActionHandler = { [weak self] in + self?.addToCalendarActionHandler?($0) + } + result.signupActionHandler = { [weak self] in + self?.signupActionHandler?($0) + } return result } diff --git a/NOICommunity/NewsFeature/View Controllers/NewsPageViewController.swift b/NOICommunity/NewsFeature/View Controllers/NewsPageViewController.swift index 3ed03f6..2471b11 100644 --- a/NOICommunity/NewsFeature/View Controllers/NewsPageViewController.swift +++ b/NOICommunity/NewsFeature/View Controllers/NewsPageViewController.swift @@ -28,13 +28,17 @@ final class NewsPageViewController: BasePageViewController var externalLinkActionHandler: ((Article) -> Void)? { didSet { - newsDetailsViewController?.externalLinkActionHandler = externalLinkActionHandler + newsDetailsViewController?.externalLinkActionHandler = { [weak self] in + self?.externalLinkActionHandler?($0) + } } } var askQuestionActionHandler: ((Article) -> Void)? { didSet { - newsDetailsViewController?.askQuestionActionHandler = askQuestionActionHandler + newsDetailsViewController?.askQuestionActionHandler = { [weak self] in + self?.askQuestionActionHandler?($0) + } } } @@ -89,8 +93,12 @@ private extension NewsPageViewController { func makeResultContent(for news: Article) -> NewsDetailsViewController { let result = NewsDetailsViewController(for: news) - result.externalLinkActionHandler = externalLinkActionHandler - result.askQuestionActionHandler = askQuestionActionHandler + result.externalLinkActionHandler = { [weak self] in + self?.externalLinkActionHandler?($0) + } + result.askQuestionActionHandler = { [weak self] in + self?.askQuestionActionHandler?($0) + } return result } diff --git a/NOICommunityLib/Sources/CoreUI/UIWindow+topViewController.swift b/NOICommunityLib/Sources/CoreUI/UIWindow+topViewController.swift new file mode 100644 index 0000000..6e1fca4 --- /dev/null +++ b/NOICommunityLib/Sources/CoreUI/UIWindow+topViewController.swift @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: NOI Techpark +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +// +// UIWindow+topViewController.swift +// NOICommunityLib +// +// Created by Matteo Matassoni on 06/12/24. +// + +import UIKit + +public extension UIWindow { + + var topViewController: UIViewController? { + topMostViewController(from: rootViewController) + } + +} + +private extension UIWindow { + + func topMostViewController( + from viewController: UIViewController? + ) -> UIViewController? { + if let presentedViewController = viewController?.presentedViewController { + topMostViewController(from: presentedViewController) + } else if let tabBarController = viewController as? UITabBarController { + topMostViewController(from: tabBarController.selectedViewController) + } else if let navigationController = viewController as? UINavigationController, + let topViewController = navigationController.topViewController { + topMostViewController(from: topViewController) + } else { + viewController + } + } + +}