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

Custom URL Scheme Implementation Supporting Sura and Verse Number #659

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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
1 change: 1 addition & 0 deletions Example/QuranEngineApp/Classes/Container.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import LastPagePersistence
import NotePersistence
import PageBookmarkPersistence
import ReadingService
import UIKit

/// Hosts singleton dependencies
class Container: AppDependencies {
Expand Down
15 changes: 12 additions & 3 deletions Example/QuranEngineApp/Classes/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// MARK: Internal

var window: UIWindow?
private var launchBuilder: LaunchBuilder?

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
Expand All @@ -21,9 +22,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
window.overrideUserInterfaceStyle = ThemeService.shared.theme.userInterfaceStyle
self.window = window

let launchBuilder = LaunchBuilder(container: Container.shared)
let launchStartup = launchBuilder.launchStartup()
launchStartup.launch(from: window)
self.launchBuilder = LaunchBuilder(container: container)
let launchStartup = launchBuilder?.launchStartup()
launchStartup?.launch(from: window)

self.launchStartup = launchStartup
}
Expand Down Expand Up @@ -55,8 +56,16 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let urlContext: UIOpenURLContext = URLContexts.first else {
return
}
launchBuilder?.handleIncomingUrl(urlContext: urlContext)
}

// MARK: Private

private var launchStartup: LaunchStartup?
private let container = Container.shared
}
12 changes: 12 additions & 0 deletions Example/QuranEngineApp/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.quran.QuranEngineApp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>quran</string>
<string>quran-ios</string>
</array>
</dict>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
Expand Down
65 changes: 60 additions & 5 deletions Features/AppStructureFeature/Launch/LaunchBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ import AppMigrationFeature
import AudioUpdater
import ReciterService
import SettingsService
import UIKit

@MainActor
public struct LaunchBuilder {
// MARK: Lifecycle

public init(container: AppDependencies) {
self.container = container
}

// MARK: Public

public func launchStartup() -> LaunchStartup {
let audioUpdater = AudioUpdater(baseURL: container.appHost)
let fileSystemMigrator = FileSystemMigrator(
Expand All @@ -36,8 +37,62 @@ public struct LaunchBuilder {
reviewService: ReviewService(analytics: container.analytics)
)
}


public func handleIncomingUrl(urlContext: UIOpenURLContext) {
let url = urlContext.url
print("Received URL: \(url)")

// Function to extract surah and ayah numbers from the URL
func extractSurahAndAyah(from url: URL) -> (surah: Int, ayah: Int)? {
// For custom schemes, use the host and path
let components = (url.host ?? "") + url.path
let parts = components.trimmingCharacters(in: CharacterSet(charactersIn: "/")).components(separatedBy: "/")

guard parts.count >= 2,
let surah = Int(parts[0]),
let ayah = Int(parts[1]) else {
return nil
}
return (surah, ayah)
}

// Handle both custom URL scheme and Universal Links
if url.scheme == "quran" || url.scheme == "quran-ios" {
print("URL scheme recognized")

let path: String
if #available(iOS 16.0, *) {
path = url.path(percentEncoded: true)
} else {
path = url.path
}
if let (surah, ayah) = extractSurahAndAyah(from: url) {
print("Extracted Surah: \(surah), Ayah: \(ayah)")
_ = navigateToAyah(surah: surah, ayah: ayah)
} else {
_ = navigateTo(path: path)
}
}
}

// MARK: Internal

let container: AppDependencies

// MARK: Private

private func navigateToAyah(surah: Int, ayah: Int) -> Bool {
// Implement the logic to navigate to the specific surah and ayah
print("Navigating to Surah \(surah), Ayah \(ayah)")
// Quran.hafsMadani1405.suras[surah].verses[ayah]
return true
// You would replace this with actual navigation logic
}

private func navigateTo(path: String) -> Bool {
// Implement the logic to navigate based on the path
print("Navigating to path: \(path)")
return true
// You would replace this with actual navigation logic
}
}