diff --git a/App/App_iOS.swift b/App/App_iOS.swift index 1a06d9bd..c0a946e5 100644 --- a/App/App_iOS.swift +++ b/App/App_iOS.swift @@ -73,7 +73,14 @@ struct Kiwix: App { if url.isFileURL { NotificationCenter.openFiles([url], context: .file) } else if url.isZIMURL { - NotificationCenter.openURL(url) + switch url { + case DownloadActivityAttributes.downloadsDeepLink: + if FeatureFlags.hasLibrary { + navigation.showDownloads.send() + } + default: + NotificationCenter.openURL(url) + } } } .task { diff --git a/App/CompactViewController.swift b/App/CompactViewController.swift index d64003d5..f301aaa7 100644 --- a/App/CompactViewController.swift +++ b/App/CompactViewController.swift @@ -137,11 +137,15 @@ private struct CompactView: View { @EnvironmentObject private var library: LibraryViewModel @State private var presentedSheet: PresentedSheet? - private enum PresentedSheet: String, Identifiable { - case library + private enum PresentedSheet: Identifiable { + case library(downloads: Bool) case settings var id: String { - rawValue + switch self { + case .library(true): return "library-downloads" + case .library(false): return "library" + case .settings: return "settings" + } } } @@ -161,7 +165,7 @@ private struct CompactView: View { } Content(tabID: tabID, showLibrary: { if presentedSheet == nil { - presentedSheet = .library + presentedSheet = .library(downloads: false) } else { // there's a sheet already presented by the user // do nothing @@ -183,7 +187,7 @@ private struct CompactView: View { Spacer() if FeatureFlags.hasLibrary { Button { - presentedSheet = .library + presentedSheet = .library(downloads: false) } label: { Label(LocalString.common_tab_menu_library, systemImage: "folder") } @@ -200,8 +204,10 @@ private struct CompactView: View { .environmentObject(browser) .sheet(item: $presentedSheet) { presentedSheet in switch presentedSheet { - case .library: + case .library(downloads: false): Library(dismiss: dismiss) + case .library(downloads: true): + Library(dismiss: dismiss, tabItem: .downloads) case .settings: NavigationStack { Settings().toolbar { @@ -216,6 +222,16 @@ private struct CompactView: View { } } } + .onReceive(navigation.showDownloads) { _ in + switch presentedSheet { + case .library: + // switching to the downloads tab + // is done within Library + break + case .settings, nil: + presentedSheet = .library(downloads: true) + } + } } } } diff --git a/App/SplitViewController.swift b/App/SplitViewController.swift index c13cfffe..8c134186 100644 --- a/App/SplitViewController.swift +++ b/App/SplitViewController.swift @@ -21,6 +21,7 @@ import UIKit final class SplitViewController: UISplitViewController { let navigationViewModel: NavigationViewModel private var navigationItemObserver: AnyCancellable? + private var showDownloadsObserver: AnyCancellable? private var openURLObserver: NSObjectProtocol? private var hasZimFiles: Bool @@ -74,6 +75,16 @@ final class SplitViewController: UISplitViewController { self?.preferredDisplayMode = .automatic } } + showDownloadsObserver = navigationViewModel + .showDownloads + .receive(on: DispatchQueue.main) + .sink(receiveValue: { [weak self] _ in + if self?.traitCollection.horizontalSizeClass == .regular { + self?.navigationViewModel.currentItem = .downloads + } + // the compact one is triggered in CompactViewController + }) + openURLObserver = NotificationCenter.default.addObserver( forName: .openURL, object: nil, queue: nil ) { [weak self] notification in diff --git a/Common/DownloadActivityAttributes.swift b/Common/DownloadActivityAttributes.swift index e894c9b3..69e2ad18 100644 --- a/Common/DownloadActivityAttributes.swift +++ b/Common/DownloadActivityAttributes.swift @@ -18,6 +18,8 @@ import ActivityKit public struct DownloadActivityAttributes: ActivityAttributes { + static let downloadsDeepLink = URL(string: "zim://downloads") + private static func progressFor(items: [DownloadItem]) -> Progress { let sumOfTotal = items.reduce(0) { result, item in result + item.total diff --git a/ViewModel/NavigationViewModel.swift b/ViewModel/NavigationViewModel.swift index 37b88768..e4f9939e 100644 --- a/ViewModel/NavigationViewModel.swift +++ b/ViewModel/NavigationViewModel.swift @@ -15,12 +15,15 @@ import CoreData import WebKit +import Combine @MainActor final class NavigationViewModel: ObservableObject { let uuid = UUID() // remained optional due to focusedSceneValue conformance @Published var currentItem: NavigationItem? = .loading + private(set) var showDownloads = PassthroughSubject() + #if os(macOS) var isTerminating: Bool = false diff --git a/Views/Library/Library.swift b/Views/Library/Library.swift index 99e52acb..c999cb0c 100644 --- a/Views/Library/Library.swift +++ b/Views/Library/Library.swift @@ -21,16 +21,19 @@ import Defaults /// Tabbed library view on iOS & iPadOS struct Library: View { @EnvironmentObject private var viewModel: LibraryViewModel - @SceneStorage("LibraryTabItem") private var tabItem: LibraryTabItem = .categories + @EnvironmentObject private var navigation: NavigationViewModel + @State private var tabItem: LibraryTabItem @Default(.hasSeenCategories) private var hasSeenCategories private let categories: [Category] let dismiss: (() -> Void)? init( dismiss: (() -> Void)?, + tabItem: LibraryTabItem = .categories, categories: [Category] = CategoriesToLanguages().allCategories() ) { self.dismiss = dismiss + self.tabItem = tabItem self.categories = categories } @@ -70,6 +73,8 @@ struct Library: View { viewModel.start(isUserInitiated: false) }.onDisappear { hasSeenCategories = true + }.onReceive(navigation.showDownloads) { _ in + tabItem = .downloads } } } diff --git a/Widgets/DownloadsLiveActivity.swift b/Widgets/DownloadsLiveActivity.swift index e3aee799..1ce8dce5 100644 --- a/Widgets/DownloadsLiveActivity.swift +++ b/Widgets/DownloadsLiveActivity.swift @@ -66,7 +66,7 @@ struct DownloadsLiveActivity: Widget { .progressViewStyle(CircularProgressGaugeStyle(lineWidth: 5.7)) .frame(width: 24, height: 24) } - .widgetURL(URL(string: "zim://downloads")) + .widgetURL(DownloadActivityAttributes.downloadsDeepLink) .keylineTint(Color.red) }.containerBackgroundRemovable() }