Navigate to downloads via deeplink

This commit is contained in:
Balazs Perlaki-Horvath 2025-03-02 18:22:49 +01:00
parent d057f95ec0
commit a98cc5cace
7 changed files with 53 additions and 9 deletions

View File

@ -73,7 +73,14 @@ struct Kiwix: App {
if url.isFileURL { if url.isFileURL {
NotificationCenter.openFiles([url], context: .file) NotificationCenter.openFiles([url], context: .file)
} else if url.isZIMURL { } else if url.isZIMURL {
NotificationCenter.openURL(url) switch url {
case DownloadActivityAttributes.downloadsDeepLink:
if FeatureFlags.hasLibrary {
navigation.showDownloads.send()
}
default:
NotificationCenter.openURL(url)
}
} }
} }
.task { .task {

View File

@ -137,11 +137,15 @@ private struct CompactView: View {
@EnvironmentObject private var library: LibraryViewModel @EnvironmentObject private var library: LibraryViewModel
@State private var presentedSheet: PresentedSheet? @State private var presentedSheet: PresentedSheet?
private enum PresentedSheet: String, Identifiable { private enum PresentedSheet: Identifiable {
case library case library(downloads: Bool)
case settings case settings
var id: String { 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: { Content(tabID: tabID, showLibrary: {
if presentedSheet == nil { if presentedSheet == nil {
presentedSheet = .library presentedSheet = .library(downloads: false)
} else { } else {
// there's a sheet already presented by the user // there's a sheet already presented by the user
// do nothing // do nothing
@ -183,7 +187,7 @@ private struct CompactView: View {
Spacer() Spacer()
if FeatureFlags.hasLibrary { if FeatureFlags.hasLibrary {
Button { Button {
presentedSheet = .library presentedSheet = .library(downloads: false)
} label: { } label: {
Label(LocalString.common_tab_menu_library, systemImage: "folder") Label(LocalString.common_tab_menu_library, systemImage: "folder")
} }
@ -200,8 +204,10 @@ private struct CompactView: View {
.environmentObject(browser) .environmentObject(browser)
.sheet(item: $presentedSheet) { presentedSheet in .sheet(item: $presentedSheet) { presentedSheet in
switch presentedSheet { switch presentedSheet {
case .library: case .library(downloads: false):
Library(dismiss: dismiss) Library(dismiss: dismiss)
case .library(downloads: true):
Library(dismiss: dismiss, tabItem: .downloads)
case .settings: case .settings:
NavigationStack { NavigationStack {
Settings().toolbar { 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)
}
}
} }
} }
} }

View File

@ -21,6 +21,7 @@ import UIKit
final class SplitViewController: UISplitViewController { final class SplitViewController: UISplitViewController {
let navigationViewModel: NavigationViewModel let navigationViewModel: NavigationViewModel
private var navigationItemObserver: AnyCancellable? private var navigationItemObserver: AnyCancellable?
private var showDownloadsObserver: AnyCancellable?
private var openURLObserver: NSObjectProtocol? private var openURLObserver: NSObjectProtocol?
private var hasZimFiles: Bool private var hasZimFiles: Bool
@ -74,6 +75,16 @@ final class SplitViewController: UISplitViewController {
self?.preferredDisplayMode = .automatic 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( openURLObserver = NotificationCenter.default.addObserver(
forName: .openURL, object: nil, queue: nil forName: .openURL, object: nil, queue: nil
) { [weak self] notification in ) { [weak self] notification in

View File

@ -18,6 +18,8 @@ import ActivityKit
public struct DownloadActivityAttributes: ActivityAttributes { public struct DownloadActivityAttributes: ActivityAttributes {
static let downloadsDeepLink = URL(string: "zim://downloads")
private static func progressFor(items: [DownloadItem]) -> Progress { private static func progressFor(items: [DownloadItem]) -> Progress {
let sumOfTotal = items.reduce(0) { result, item in let sumOfTotal = items.reduce(0) { result, item in
result + item.total result + item.total

View File

@ -15,12 +15,15 @@
import CoreData import CoreData
import WebKit import WebKit
import Combine
@MainActor @MainActor
final class NavigationViewModel: ObservableObject { final class NavigationViewModel: ObservableObject {
let uuid = UUID() let uuid = UUID()
// remained optional due to focusedSceneValue conformance // remained optional due to focusedSceneValue conformance
@Published var currentItem: NavigationItem? = .loading @Published var currentItem: NavigationItem? = .loading
private(set) var showDownloads = PassthroughSubject<Void, Never>()
#if os(macOS) #if os(macOS)
var isTerminating: Bool = false var isTerminating: Bool = false

View File

@ -21,16 +21,19 @@ import Defaults
/// Tabbed library view on iOS & iPadOS /// Tabbed library view on iOS & iPadOS
struct Library: View { struct Library: View {
@EnvironmentObject private var viewModel: LibraryViewModel @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 @Default(.hasSeenCategories) private var hasSeenCategories
private let categories: [Category] private let categories: [Category]
let dismiss: (() -> Void)? let dismiss: (() -> Void)?
init( init(
dismiss: (() -> Void)?, dismiss: (() -> Void)?,
tabItem: LibraryTabItem = .categories,
categories: [Category] = CategoriesToLanguages().allCategories() categories: [Category] = CategoriesToLanguages().allCategories()
) { ) {
self.dismiss = dismiss self.dismiss = dismiss
self.tabItem = tabItem
self.categories = categories self.categories = categories
} }
@ -70,6 +73,8 @@ struct Library: View {
viewModel.start(isUserInitiated: false) viewModel.start(isUserInitiated: false)
}.onDisappear { }.onDisappear {
hasSeenCategories = true hasSeenCategories = true
}.onReceive(navigation.showDownloads) { _ in
tabItem = .downloads
} }
} }
} }

View File

@ -66,7 +66,7 @@ struct DownloadsLiveActivity: Widget {
.progressViewStyle(CircularProgressGaugeStyle(lineWidth: 5.7)) .progressViewStyle(CircularProgressGaugeStyle(lineWidth: 5.7))
.frame(width: 24, height: 24) .frame(width: 24, height: 24)
} }
.widgetURL(URL(string: "zim://downloads")) .widgetURL(DownloadActivityAttributes.downloadsDeepLink)
.keylineTint(Color.red) .keylineTint(Color.red)
}.containerBackgroundRemovable() }.containerBackgroundRemovable()
} }