mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-14 14:49:50 -04:00
Add DeepLinkService to track external ZIM file launch of the app
This commit is contained in:
parent
d62334be58
commit
6ae4852701
@ -28,6 +28,7 @@ struct Kiwix: App {
|
|||||||
@StateObject private var navigation = NavigationViewModel()
|
@StateObject private var navigation = NavigationViewModel()
|
||||||
@UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
|
@UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
|
||||||
private let fileMonitor: DirectoryMonitor
|
private let fileMonitor: DirectoryMonitor
|
||||||
|
// @State var isOpeningDeeplink = true
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
fileMonitor = DirectoryMonitor(url: URL.documentDirectory) { LibraryOperations.scanDirectory($0) }
|
fileMonitor = DirectoryMonitor(url: URL.documentDirectory) { LibraryOperations.scanDirectory($0) }
|
||||||
@ -60,14 +61,15 @@ struct Kiwix: App {
|
|||||||
}
|
}
|
||||||
case .background:
|
case .background:
|
||||||
break
|
break
|
||||||
// reScheduleBackgroundDownloadTask()
|
|
||||||
@unknown default:
|
@unknown default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onOpenURL { url in
|
.onOpenURL { url in
|
||||||
if url.isFileURL {
|
if url.isFileURL {
|
||||||
NotificationCenter.openFiles([url], context: .file)
|
let deepLinkId = UUID()
|
||||||
|
DeepLinkService.shared.startFor(uuid: deepLinkId)
|
||||||
|
NotificationCenter.openFiles([url], context: .file(deepLinkId: deepLinkId))
|
||||||
} else if url.isZIMURL {
|
} else if url.isZIMURL {
|
||||||
NotificationCenter.openURL(url)
|
NotificationCenter.openURL(url)
|
||||||
}
|
}
|
||||||
@ -77,7 +79,9 @@ struct Kiwix: App {
|
|||||||
case .kiwix:
|
case .kiwix:
|
||||||
fileMonitor.start()
|
fileMonitor.start()
|
||||||
await LibraryOperations.reopen()
|
await LibraryOperations.reopen()
|
||||||
|
if !DeepLinkService.shared.isRunning() {
|
||||||
navigation.navigateToMostRecentTab()
|
navigation.navigateToMostRecentTab()
|
||||||
|
}
|
||||||
LibraryOperations.scanDirectory(URL.documentDirectory)
|
LibraryOperations.scanDirectory(URL.documentDirectory)
|
||||||
LibraryOperations.applyFileBackupSetting()
|
LibraryOperations.applyFileBackupSetting()
|
||||||
DownloadService.shared.restartHeartbeatIfNeeded()
|
DownloadService.shared.restartHeartbeatIfNeeded()
|
||||||
|
@ -89,7 +89,7 @@ final class SplitViewController: UISplitViewController {
|
|||||||
})
|
})
|
||||||
|
|
||||||
openURLObserver = NotificationCenter.default.addObserver(
|
openURLObserver = NotificationCenter.default.addObserver(
|
||||||
forName: .openURL, object: nil, queue: nil
|
forName: .openURL, object: nil, queue: .main
|
||||||
) { [weak self] notification in
|
) { [weak self] notification in
|
||||||
guard let url = notification.userInfo?["url"] as? URL else { return }
|
guard let url = notification.userInfo?["url"] as? URL else { return }
|
||||||
let inNewTab = notification.userInfo?["inNewTab"] as? Bool ?? false
|
let inNewTab = notification.userInfo?["inNewTab"] as? Bool ?? false
|
||||||
@ -99,6 +99,10 @@ final class SplitViewController: UISplitViewController {
|
|||||||
} else if let tabID = self?.navigationViewModel.createTab() {
|
} else if let tabID = self?.navigationViewModel.createTab() {
|
||||||
BrowserViewModel.getCached(tabID: tabID).load(url: url)
|
BrowserViewModel.getCached(tabID: tabID).load(url: url)
|
||||||
}
|
}
|
||||||
|
if let context = notification.userInfo?["context"] as? OpenURLContext,
|
||||||
|
case .deepLink(let deepLinkId) = context {
|
||||||
|
DeepLinkService.shared.stopFor(uuid: deepLinkId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
observeGoBackAndForward()
|
observeGoBackAndForward()
|
||||||
|
42
Model/DeepLinkService.swift
Normal file
42
Model/DeepLinkService.swift
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// This file is part of Kiwix for iOS & macOS.
|
||||||
|
//
|
||||||
|
// Kiwix is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// Kiwix is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Kiwix; If not, see https://www.gnu.org/licenses/.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// Helper to figure out if a deeplink started ZIM file
|
||||||
|
/// handling is already running.
|
||||||
|
/// In that case we do not want to handle the default
|
||||||
|
/// navigation to the latest opened ZIM file
|
||||||
|
@MainActor
|
||||||
|
final class DeepLinkService {
|
||||||
|
|
||||||
|
static let shared = DeepLinkService()
|
||||||
|
|
||||||
|
private var ids = Set<UUID>()
|
||||||
|
|
||||||
|
private init() {}
|
||||||
|
|
||||||
|
func startFor(uuid: UUID) {
|
||||||
|
ids.insert(uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopFor(uuid: UUID) {
|
||||||
|
ids.remove(uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRunning() -> Bool {
|
||||||
|
!ids.isEmpty
|
||||||
|
}
|
||||||
|
}
|
@ -138,14 +138,14 @@ enum ExternalLinkLoadingPolicy: String, CaseIterable, Identifiable, Defaults.Ser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum OpenURLContext: String {
|
enum OpenURLContext {
|
||||||
case deepLink
|
case deepLink(id: UUID)
|
||||||
case file
|
case file
|
||||||
}
|
}
|
||||||
|
|
||||||
enum OpenFileContext: String {
|
enum OpenFileContext {
|
||||||
case command
|
case command
|
||||||
case file
|
case file(deepLinkId: UUID? = nil)
|
||||||
case welcomeScreen
|
case welcomeScreen
|
||||||
case library
|
case library
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
import CoreData
|
import CoreData
|
||||||
import WebKit
|
import WebKit
|
||||||
import Combine
|
import Combine
|
||||||
|
import os
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
final class NavigationViewModel: ObservableObject {
|
final class NavigationViewModel: ObservableObject {
|
||||||
@ -67,6 +68,7 @@ final class NavigationViewModel: ObservableObject {
|
|||||||
let tab = (try? context.fetch(fetchRequest).first) ?? Self.makeTab(context: context)
|
let tab = (try? context.fetch(fetchRequest).first) ?? Self.makeTab(context: context)
|
||||||
Task {
|
Task {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
|
os_log("open navigate to most recent tab", log: Log.LibraryOperations, type: .error)
|
||||||
currentItem = NavigationItem.tab(objectID: tab.objectID)
|
currentItem = NavigationItem.tab(objectID: tab.objectID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,14 +54,14 @@ struct OpenFileHandler: ViewModifier {
|
|||||||
@State private var isAlertPresented = false
|
@State private var isAlertPresented = false
|
||||||
@State private var activeAlert: ActiveAlert?
|
@State private var activeAlert: ActiveAlert?
|
||||||
|
|
||||||
private let importFiles = NotificationCenter.default.publisher(for: .openFiles)
|
private let openFiles = NotificationCenter.default.publisher(for: .openFiles)
|
||||||
|
|
||||||
enum ActiveAlert {
|
enum ActiveAlert {
|
||||||
case unableToOpen(filenames: [String])
|
case unableToOpen(filenames: [String])
|
||||||
}
|
}
|
||||||
// swiftlint:disable:next cyclomatic_complexity
|
// swiftlint:disable:next cyclomatic_complexity
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
content.onReceive(importFiles) { notification in
|
content.onReceive(openFiles) { notification in
|
||||||
guard let urls = notification.userInfo?["urls"] as? [URL],
|
guard let urls = notification.userInfo?["urls"] as? [URL],
|
||||||
let context = notification.userInfo?["context"] as? OpenFileContext else { return }
|
let context = notification.userInfo?["context"] as? OpenFileContext else { return }
|
||||||
|
|
||||||
@ -90,7 +90,11 @@ struct OpenFileHandler: ViewModifier {
|
|||||||
NotificationCenter.openURL(url, inNewTab: true, context: .file)
|
NotificationCenter.openURL(url, inNewTab: true, context: .file)
|
||||||
}
|
}
|
||||||
#elseif os(iOS)
|
#elseif os(iOS)
|
||||||
|
if case .file(.some(let deepLinkID)) = context {
|
||||||
|
NotificationCenter.openURL(url, inNewTab: true, context: .deepLink(id: deepLinkID))
|
||||||
|
} else {
|
||||||
NotificationCenter.openURL(url, inNewTab: true)
|
NotificationCenter.openURL(url, inNewTab: true)
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
case .welcomeScreen:
|
case .welcomeScreen:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user