Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose a new handle(externalURL) function #165

Merged
merged 4 commits into from
Nov 30, 2023
Merged
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
15 changes: 15 additions & 0 deletions Source/Turbo Navigator/Helpers/ExternalURLNavigationAction.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation

/// When TurboNavigator encounters an external URL, its delegate may handle it with any of these actions.
public enum ExternalURLNavigationAction {
/// Attempts to open via an embedded `SafariViewController` so the user stays in-app.
/// Silently fails if you pass a URL that's not `http` or `https`.
case openViaSafariController

/// Attempts to open via `openURL(_:options:completionHandler)`.
/// This is useful if the external URL is a deeplink.
case openViaSystem

/// Will do nothing with the external URL.
case reject
}
14 changes: 0 additions & 14 deletions Source/Turbo Navigator/TurboNavigationHierarchyController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,6 @@ class TurboNavigationHierarchyController {
}
}

func openExternal(url: URL, navigationType: NavigationStackType) {
if ["http", "https"].contains(url.scheme) {
let safariViewController = SFSafariViewController(url: url)
safariViewController.modalPresentationStyle = .pageSheet
if #available(iOS 15.0, *) {
safariViewController.preferredControlTintColor = .tintColor
}
let navController = navController(for: navigationType)
navController.present(safariViewController, animated: true)
} else if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
}
olivaresf marked this conversation as resolved.
Show resolved Hide resolved
}

// MARK: Private

@available(*, unavailable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ import WebKit
/// or to render a native controller instead of a Turbo web visit.
protocol TurboNavigationHierarchyControllerDelegate: AnyObject {
func visit(_ : Visitable, on: TurboNavigationHierarchyController.NavigationStackType, with: VisitOptions)

func refresh(navigationStack: TurboNavigationHierarchyController.NavigationStackType)
}
27 changes: 22 additions & 5 deletions Source/Turbo Navigator/TurboNavigator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,25 @@ extension TurboNavigator: SessionDelegate {
}
}

public func session(_ session: Session, openExternalURL url: URL) {
let navigationType: TurboNavigationHierarchyController.NavigationStackType = session === modalSession ? .modal : .main
hierarchyController.openExternal(url: url, navigationType: navigationType)
public func session(_ session: Session, openExternalURL externalURL: URL) {

switch delegate.handle(externalURL: externalURL) {

case .openViaSystem:
UIApplication.shared.open(externalURL)

case .openViaSafariController:
let safariViewController = SFSafariViewController(url: externalURL)
safariViewController.modalPresentationStyle = .pageSheet
if #available(iOS 15.0, *) {
safariViewController.preferredControlTintColor = .tintColor
}

activeNavigationController.present(safariViewController, animated: true)

case .reject:
return
}
}

public func session(_ session: Session, didFailRequestForVisitable visitable: Visitable, error: Error) {
Expand Down Expand Up @@ -146,10 +162,11 @@ extension TurboNavigator: SessionDelegate {
// MARK: - TurboNavigationHierarchyControllerDelegate

extension TurboNavigator: TurboNavigationHierarchyControllerDelegate {

func visit(_ controller: Visitable, on navigationStack: TurboNavigationHierarchyController.NavigationStackType, with: VisitOptions) {
switch navigationStack {
case .main: session.visit(controller, action: .advance)
case .modal: modalSession.visit(controller, action: .advance)
case .main: session.visit(controller, action: .advance)
case .modal: modalSession.visit(controller, action: .advance)
}
}

Expand Down
6 changes: 6 additions & 0 deletions Source/Turbo Navigator/TurboNavigatorDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public protocol TurboNavigatorDelegate: AnyObject {
/// - Returns: how to react to the visit proposal
func handle(proposal: VisitProposal) -> ProposalResult

func handle(externalURL: URL) -> ExternalURLNavigationAction

/// Optional. An error occurred loading the request, present it to the user.
/// Retry the request by executing the closure.
/// If not implemented, will present the error's localized description and a Retry button.
Expand All @@ -26,6 +28,10 @@ public extension TurboNavigatorDelegate {
func handle(proposal: VisitProposal) -> ProposalResult {
.accept
}

func handle(externalURL: URL) -> ExternalURLNavigationAction {
.openViaSafariController
}

func visitableDidFailRequest(_ visitable: Visitable, error: Error, retry: @escaping RetryBlock) {
if let errorPresenter = visitable as? ErrorPresenter {
Expand Down