Skip to content

Commit

Permalink
fix deeplink code and extend URLSchemeRouter
Browse files Browse the repository at this point in the history
  • Loading branch information
hilmyveradin committed Apr 1, 2024
1 parent 1712ddc commit 2a10eaa
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 114 deletions.
3 changes: 1 addition & 2 deletions Apps/OneBusAway/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ - (void)applicationWillResignActive:(UIApplication *)application {
#pragma mark - OBAApplicationDelegate

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
[CustomRegionDeepLink parseURL:url application:self.app];
return YES;
return [self.app application:app open:url options:options];
}

- (UIApplication*)uiApplication {
Expand Down
95 changes: 0 additions & 95 deletions OBAKit/DeepLinks/CustomRegionDeepLink.swift

This file was deleted.

58 changes: 52 additions & 6 deletions OBAKit/Orchestration/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ public class Application: CoreApplication, PushServiceDelegate {
}

private var presentDonationUIOnActive = false
private var presentAddRegionAlertOnActive = false
private var donationPromptID: String?

public func pushService(_ pushService: PushService, receivedDonationPrompt id: String?) {
Expand Down Expand Up @@ -363,6 +364,18 @@ public class Application: CoreApplication, PushServiceDelegate {
presentDonationUIOnActive = false
donationPromptID = nil
}

if presentAddRegionAlertOnActive, let topViewController {
// Show alert for nil addRegion data
let alertController = UIAlertController(
title: "Error",
message: "The provided region URL is invalid or does not point to a functional OBA server.",
preferredStyle: .alert
)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
topViewController.present(alertController, animated: true)
presentAddRegionAlertOnActive = false
}
}

@objc public func applicationWillResignActive(_ application: UIApplication) {
Expand Down Expand Up @@ -429,15 +442,48 @@ public class Application: CoreApplication, PushServiceDelegate {
}

let router = URLSchemeRouter(scheme: scheme)
guard
let stopData = router.decode(url: url),
let topViewController = topViewController
else {

guard let urlType = router.decodeURLType(from: url) else {
return false
}

viewRouter.navigateTo(stopID: stopData.stopID, from: topViewController)
return true
switch urlType {
case .viewStop(let stopData):
guard let topViewController = self.topViewController else { return false }
viewRouter.navigateTo(stopID: stopData.stopID, from: topViewController)
return true
case .addRegion(let regionData):
viewRouter.rootNavigateTo(page: .map)
Task { @MainActor in
do {
if let regionData = regionData {
guard let regionCoordinate = try await self.apiService?.getAgenciesWithCoverage().list.first?.region else { return }

// Adjustments for coordinate span
var adjustedRegionCoordinate = regionCoordinate
adjustedRegionCoordinate.span.latitudeDelta = 2
adjustedRegionCoordinate.span.longitudeDelta = 2

// Create region provider
let regionProvider = RegionPickerCoordinator(regionsService: self.regionsService)

// Construct Region from URL data
let currentRegion = Region(name: regionData.name, OBABaseURL: regionData.obaURL, coordinateRegion: adjustedRegionCoordinate, contactEmail: "[email protected]", openTripPlannerURL: regionData.otpURL)

// Add and set current region
try await regionProvider.add(customRegion: currentRegion)
try await regionProvider.setCurrentRegion(to: currentRegion)
} else {
presentAddRegionAlertOnActive = true
return
}
} catch {
presentAddRegionAlertOnActive = true
return
}
}
return true
}
}

override public func apiServicesRefreshed() {
Expand Down
57 changes: 47 additions & 10 deletions OBAKitCore/DeepLinks/URLSchemeRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ public struct StopURLData {
public let regionID: Int
}

public struct AddRegionURLData {
public let name: String
public let obaURL: URL
public let otpURL: URL?
}

// Enum to distinguish between URL types
public enum URLType {
case viewStop(StopURLData)
case addRegion(AddRegionURLData?)
}
/// Provides support for deep linking into the app by way of a custom URL scheme.
///
/// Custom URL scheme deep linking (e.g. `onebusaway://view-stop?region_id=1&stop_id=12345`)
Expand All @@ -25,21 +36,37 @@ public class URLSchemeRouter: NSObject {
/// The app bundle's URL scheme for extensions.
private let scheme: String

private let viewStopHost = "view-stop"
private let addRegionHost = "add-region"

/// Creates a new URL Scheme Router.
/// - Parameter scheme: The app bundle's `extensionURLScheme` value.
public init(scheme: String) {
self.scheme = scheme
}

// MARK: - Stop URLs
/// Decode URL Types based on host
public func decodeURLType(from url: URL) -> URLType? {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
return nil
}

private let viewStopHost = "view-stop"
switch components.host {
case viewStopHost:
return decodeViewStop(from: components)
case addRegionHost:
return decodeAddRegion(from: components)
default:
return nil
}
}

// MARK: - Stop URLs
/// Encodes the ID for a Stop along with its Region ID into an URL with the scheme `extensionURLScheme`.
/// - Parameters:
/// - stopID: The ID for the Stop.
/// - regionID: The ID for the Region that hosts the Stop.
public func encode(stopID: StopID, regionID: Int) -> URL {
public func encodeViewStop(stopID: StopID, regionID: Int) -> URL {
var components = URLComponents()
components.scheme = scheme
components.host = viewStopHost
Expand All @@ -50,17 +77,27 @@ public class URLSchemeRouter: NSObject {

/// Decodes a `StopURLData` struct from `url`, which can be used to display a `StopViewController`.
/// - Parameter url: An URL created from calling `URLSchemeRouter.encode()`
public func decode(url: URL) -> StopURLData? {
private func decodeViewStop(from components: URLComponents) -> URLType? {
guard
let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
components.host == viewStopHost,
let stopID = components.queryItem(named: "stopID")?.value,
let regionIDString = components.queryItem(named: "regionID")?.value,
let regionID = Int(regionIDString)
else {
return nil
let regionID = Int(regionIDString) else {
return nil
}
return .viewStop(StopURLData(stopID: stopID, regionID: regionID))
}

return StopURLData(stopID: stopID, regionID: regionID)
// MARK: - Add Region URLs
/// Encodes the OBA URL for adding custom region along with its Name into an URL with the scheme `extensionURLScheme`. It also has optional OTP URL
private func decodeAddRegion(from components: URLComponents) -> URLType? {
guard
let name = components.queryItem(named: "name")?.value,
let obaUrlString = components.queryItem(named: "oba-url")?.value,
let obaURL = URL(string: obaUrlString) else {
return .addRegion(nil)
}
let otpUrlString = components.queryItem(named: "otp-url")?.value
let otpURL = otpUrlString != nil ? URL(string: otpUrlString!) : nil
return .addRegion(AddRegionURLData(name: name, obaURL: obaURL, otpURL: otpURL))
}
}
2 changes: 1 addition & 1 deletion TodayView/TodayViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class TodayViewController: UIViewController, BookmarkDataDelegate, NCWidgetProvi
}

let router = URLSchemeRouter(scheme: Bundle.main.extensionURLScheme!)
let url = router.encode(stopID: bookmark.stopID, regionID: bookmark.regionIdentifier)
let url = router.encodeViewStop(stopID: bookmark.stopID, regionID: bookmark.regionIdentifier)

extensionContext?.open(url, completionHandler: nil)
}
Expand Down

0 comments on commit 2a10eaa

Please sign in to comment.