mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-22 02:52:39 -04:00
Merge pull request #1174 from kiwix/1169-openzim-navigate-to-recent-tab-race-fix
1169 openzim navigate to recent tab race fix
This commit is contained in:
commit
7e5a66184c
@ -60,14 +60,15 @@ struct Kiwix: App {
|
||||
}
|
||||
case .background:
|
||||
break
|
||||
// reScheduleBackgroundDownloadTask()
|
||||
@unknown default:
|
||||
break
|
||||
}
|
||||
}
|
||||
.onOpenURL { url in
|
||||
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 {
|
||||
NotificationCenter.openURL(url)
|
||||
}
|
||||
@ -77,7 +78,9 @@ struct Kiwix: App {
|
||||
case .kiwix:
|
||||
fileMonitor.start()
|
||||
await LibraryOperations.reopen()
|
||||
navigation.navigateToMostRecentTab()
|
||||
if !DeepLinkService.shared.isRunning() {
|
||||
navigation.navigateToMostRecentTab()
|
||||
}
|
||||
LibraryOperations.scanDirectory(URL.documentDirectory)
|
||||
LibraryOperations.applyFileBackupSetting()
|
||||
DownloadService.shared.restartHeartbeatIfNeeded()
|
||||
|
@ -264,12 +264,14 @@ struct RootView: View {
|
||||
// from opening an external file
|
||||
let browser = BrowserViewModel.getCached(tabID: navigation.currentTabId)
|
||||
browser.forceLoadingState()
|
||||
NotificationCenter.openFiles([url], context: .file)
|
||||
// deeplink id is not needed on macOS
|
||||
NotificationCenter.openFiles([url], context: .file(deepLinkId: nil))
|
||||
} else if url.isZIMURL {
|
||||
// from deeplinks
|
||||
let browser = BrowserViewModel.getCached(tabID: navigation.currentTabId)
|
||||
browser.forceLoadingState()
|
||||
NotificationCenter.openURL(url, context: .deepLink)
|
||||
// deeplink id is not needed on macOS
|
||||
NotificationCenter.openURL(url, context: .deepLink(id: nil))
|
||||
}
|
||||
}
|
||||
.onReceive(openURL) { notification in
|
||||
|
@ -45,7 +45,6 @@ final class SplitViewController: UISplitViewController {
|
||||
}
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
@ -63,6 +62,13 @@ final class SplitViewController: UISplitViewController {
|
||||
setSecondaryController()
|
||||
|
||||
// observers
|
||||
observeNavigation()
|
||||
observeOpeningFiles()
|
||||
observeGoBackAndForward()
|
||||
observeAppBackgrounding()
|
||||
}
|
||||
|
||||
private func observeNavigation() {
|
||||
navigationItemObserver = navigationViewModel.$currentItem
|
||||
.receive(on: DispatchQueue.main) // needed to postpones sink after navigationViewModel.currentItem updates
|
||||
.dropFirst()
|
||||
@ -77,8 +83,7 @@ final class SplitViewController: UISplitViewController {
|
||||
self?.preferredDisplayMode = .automatic
|
||||
}
|
||||
}
|
||||
showDownloadsObserver = navigationViewModel
|
||||
.showDownloads
|
||||
showDownloadsObserver = navigationViewModel.showDownloads
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] _ in
|
||||
if self?.traitCollection.horizontalSizeClass == .regular,
|
||||
@ -87,9 +92,11 @@ final class SplitViewController: UISplitViewController {
|
||||
}
|
||||
// the compact one is triggered in CompactViewController
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private func observeOpeningFiles() {
|
||||
openURLObserver = NotificationCenter.default.addObserver(
|
||||
forName: .openURL, object: nil, queue: nil
|
||||
forName: .openURL, object: nil, queue: .main
|
||||
) { [weak self] notification in
|
||||
guard let url = notification.userInfo?["url"] as? URL else { return }
|
||||
let inNewTab = notification.userInfo?["inNewTab"] as? Bool ?? false
|
||||
@ -99,10 +106,12 @@ final class SplitViewController: UISplitViewController {
|
||||
} else if let tabID = self?.navigationViewModel.createTab() {
|
||||
BrowserViewModel.getCached(tabID: tabID).load(url: url)
|
||||
}
|
||||
if let context = notification.userInfo?["context"] as? OpenURLContext,
|
||||
case .deepLink(.some(let deepLinkId)) = context {
|
||||
DeepLinkService.shared.stopFor(uuid: deepLinkId)
|
||||
}
|
||||
}
|
||||
}
|
||||
observeGoBackAndForward()
|
||||
observeAppBackgrounding()
|
||||
}
|
||||
|
||||
private func 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 {
|
||||
case deepLink
|
||||
enum OpenURLContext {
|
||||
case deepLink(id: UUID?)
|
||||
case file
|
||||
}
|
||||
|
||||
enum OpenFileContext: String {
|
||||
enum OpenFileContext {
|
||||
case command
|
||||
case file
|
||||
case file(deepLinkId: UUID? = nil)
|
||||
case welcomeScreen
|
||||
case library
|
||||
}
|
||||
|
@ -54,14 +54,14 @@ struct OpenFileHandler: ViewModifier {
|
||||
@State private var isAlertPresented = false
|
||||
@State private var activeAlert: ActiveAlert?
|
||||
|
||||
private let importFiles = NotificationCenter.default.publisher(for: .openFiles)
|
||||
private let openFiles = NotificationCenter.default.publisher(for: .openFiles)
|
||||
|
||||
enum ActiveAlert {
|
||||
case unableToOpen(filenames: [String])
|
||||
}
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
// swiftlint:disable:next cyclomatic_complexity function_body_length
|
||||
func body(content: Content) -> some View {
|
||||
content.onReceive(importFiles) { notification in
|
||||
content.onReceive(openFiles) { notification in
|
||||
guard let urls = notification.userInfo?["urls"] as? [URL],
|
||||
let context = notification.userInfo?["context"] as? OpenFileContext else { return }
|
||||
|
||||
@ -83,14 +83,21 @@ struct OpenFileHandler: ViewModifier {
|
||||
for fileID in openedZimFileIDs {
|
||||
guard let url = await ZimFileService.shared.getMainPageURL(zimFileID: fileID) else { return }
|
||||
#if os(macOS)
|
||||
if .command == context {
|
||||
switch context {
|
||||
case .command:
|
||||
NotificationCenter.openURL(url, inNewTab: true)
|
||||
} else if .file == context {
|
||||
case .file:
|
||||
// Note: inNewTab:true/false has no meaning here, the system will open a new window anyway
|
||||
NotificationCenter.openURL(url, inNewTab: true, context: .file)
|
||||
default:
|
||||
break
|
||||
}
|
||||
#elseif os(iOS)
|
||||
NotificationCenter.openURL(url, inNewTab: true)
|
||||
if case .file(.some(let deepLinkID)) = context {
|
||||
NotificationCenter.openURL(url, inNewTab: true, context: .deepLink(id: deepLinkID))
|
||||
} else {
|
||||
NotificationCenter.openURL(url, inNewTab: true)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
case .welcomeScreen:
|
||||
|
Loading…
x
Reference in New Issue
Block a user