diff --git a/Example/QuranEngineApp/Classes/Container.swift b/Example/QuranEngineApp/Classes/Container.swift index e988775f..8b873f47 100644 --- a/Example/QuranEngineApp/Classes/Container.swift +++ b/Example/QuranEngineApp/Classes/Container.swift @@ -15,6 +15,7 @@ import LastPagePersistence import NotePersistence import PageBookmarkPersistence import ReadingService +import UIKit /// Hosts singleton dependencies class Container: AppDependencies { diff --git a/Example/QuranEngineApp/Classes/SceneDelegate.swift b/Example/QuranEngineApp/Classes/SceneDelegate.swift index ff274e7e..b7e7151f 100644 --- a/Example/QuranEngineApp/Classes/SceneDelegate.swift +++ b/Example/QuranEngineApp/Classes/SceneDelegate.swift @@ -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 } @@ -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 } @@ -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) { + guard let urlContext: UIOpenURLContext = URLContexts.first else { + return + } + launchBuilder?.handleIncomingUrl(urlContext: urlContext) + } // MARK: Private private var launchStartup: LaunchStartup? + private let container = Container.shared } diff --git a/Example/QuranEngineApp/Info.plist b/Example/QuranEngineApp/Info.plist index 0eb786dc..f8369499 100644 --- a/Example/QuranEngineApp/Info.plist +++ b/Example/QuranEngineApp/Info.plist @@ -2,6 +2,18 @@ + CFBundleURLTypes + + + CFBundleURLName + com.quran.QuranEngineApp + CFBundleURLSchemes + + quran + quran-ios + + + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/Features/AppStructureFeature/Launch/LaunchBuilder.swift b/Features/AppStructureFeature/Launch/LaunchBuilder.swift index 28936fd5..24629295 100644 --- a/Features/AppStructureFeature/Launch/LaunchBuilder.swift +++ b/Features/AppStructureFeature/Launch/LaunchBuilder.swift @@ -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( @@ -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 + } }