diff options
Diffstat (limited to 'Hutch/App/RootView.swift')
| -rw-r--r-- | Hutch/App/RootView.swift | 124 |
1 files changed, 109 insertions, 15 deletions
diff --git a/Hutch/App/RootView.swift b/Hutch/App/RootView.swift index 7c8037e..e223766 100644 --- a/Hutch/App/RootView.swift +++ b/Hutch/App/RootView.swift @@ -75,8 +75,8 @@ struct RootView: View { HomeView() .navigationDestination(for: HomeRoute.self) { route in switch route { - case .work: - WorkView() + case .work(let scope): + WorkView(initialScope: scope) } } } @@ -202,9 +202,16 @@ struct RootView: View { homePath = NavigationPath() appState.selectedTab = .home + case .recentActivity: + homePath = NavigationPath() + appState.selectedTab = .home + case .repository(let service, let owner, let repo): resolveRepositoryLink(service: service, owner: owner, repo: repo) + case .tracker(let owner, let tracker): + resolveTrackerLink(owner: owner, tracker: tracker) + case .build(let jobId): buildsPath = NavigationPath() appState.selectedTab = .builds @@ -223,11 +230,39 @@ struct RootView: View { resolveUserProfileLink(owner: owner) case .work: - homePath = NavigationPath() - appState.selectedTab = .home + navigateToWork(scope: .all) + + case .workQueue(let scope): + navigateToWork(scope: scope) + + case .projectDashboard(let id, let title): + morePath = NavigationPath() + appState.selectedTab = .more + Task { + await settleNavigationTransition() + morePath.append(MoreRoute.projects) + morePath.append(MoreRoute.projectDashboard(id: id, title: title)) + } + + case .failedBuilds: + buildsPath = NavigationPath() + appState.pendingBuildListFilter = .failed + appState.selectedTab = .builds + + case .search(let query): + morePath = NavigationPath() + appState.selectedTab = .more Task { await settleNavigationTransition() - homePath.append(HomeRoute.work) + morePath.append(MoreRoute.lookup(query: query)) + } + + case .lookup: + morePath = NavigationPath() + appState.selectedTab = .more + Task { + await settleNavigationTransition() + morePath.append(MoreRoute.lookup(query: nil)) } case .buildsTab: @@ -244,14 +279,15 @@ struct RootView: View { case .systemStatus: appState.navigateToSystemStatus() + } + } - case .lookup: - morePath = NavigationPath() - appState.selectedTab = .more - Task { - await settleNavigationTransition() - morePath.append(MoreRoute.lookup) - } + private func navigateToWork(scope: HutchWorkQueueScope) { + homePath = NavigationPath() + appState.selectedTab = .home + Task { + await settleNavigationTransition() + homePath.append(HomeRoute.work(scope: scope)) } } @@ -310,6 +346,22 @@ struct RootView: View { } } + private func resolveTrackerLink(owner: String, tracker: String) { + isResolvingDeepLink = true + Task { + defer { isResolvingDeepLink = false } + do { + let trackerSummary = try await appState.resolveTracker(owner: owner, name: tracker) + ticketsPath = NavigationPath() + appState.selectedTab = .tickets + await settleNavigationTransition() + ticketsPath.append(trackerSummary) + } catch { + appState.presentTicketDeepLinkError() + } + } + } + private func resolveMailingListLink(owner: String, list: String) { isResolvingDeepLink = true Task { @@ -375,7 +427,7 @@ enum MoreDestination: Hashable { } enum MoreRoute: Hashable { - case lookup + case lookup(query: String?) case projects case lists case pastes @@ -384,6 +436,7 @@ enum MoreRoute: Hashable { case settings case about case userProfile(String) + case projectDashboard(id: String, title: String?) case mailingList(InboxMailingListReference) case thread(InboxThreadSummary) case manPageBrowser @@ -397,8 +450,8 @@ private struct MoreNavigationRoot: View { MoreView() .navigationDestination(for: MoreRoute.self) { route in switch route { - case .lookup: - LookupView() + case .lookup(let query): + LookupView(initialQuery: query ?? "") case .projects: ProjectsListView() case .lists: @@ -415,6 +468,8 @@ private struct MoreNavigationRoot: View { AboutView() case .userProfile(let owner): UserProfileDeepLinkView(owner: owner) + case .projectDashboard(let id, let title): + ProjectDashboardDeepLinkView(projectID: id, title: title) case .mailingList(let mailingList): MailingListDetailView(mailingList: mailingList) case .thread(let thread): @@ -484,6 +539,45 @@ struct UserProfileDeepLinkView: View { } } +struct ProjectDashboardDeepLinkView: View { + @Environment(AppState.self) private var appState + let projectID: String + let title: String? + @State private var project: Project? + @State private var errorMessage: String? + + var body: some View { + Group { + if let project { + ProjectDetailView(project: project) + } else if let errorMessage { + ContentUnavailableView( + "Couldn't Open Project", + systemImage: "square.stack.3d.up.slash", + description: Text(errorMessage) + ) + } else { + SRHTLoadingStateView(message: "Loading project...") + } + } + .navigationTitle(title ?? "Project") + .navigationBarTitleDisplayMode(.inline) + .task(id: projectID) { + await loadProject() + } + } + + @MainActor + private func loadProject() async { + errorMessage = nil + do { + project = try await ProjectService(client: appState.client).fetchProjectDetail(rid: projectID) + } catch { + errorMessage = "The project could not be found or is inaccessible." + } + } +} + // MARK: - Ticket Deep Link Navigation Target /// Hashable wrapper to push a ticket detail view from a deep link. |
