Commit 1b7270d767

1b7270d7670fde8d62d459d14f5aa8844aca20cf

parent: ab77dbf977

Unsigned

cmc <hello@cleberg.net> · 2026-07-16 02:56 UTC

fix: push patchset views directly instead of by route

Tapping a patch failed with "no matching navigationDestination declaration
visible from the location of the link".

MailingListDetailView is presented from four places, but only the More tab and
Lookup declare a MoreRoute destination. Reached from a project, via
ProjectMailingListView, there is no such destination in the surrounding stack,
so a NavigationLink carrying MoreRoute.patchset had nowhere to resolve. The
thread rows beside it already use the closure form for exactly this reason.

Push PatchsetDetailView directly, from the rows and from the version-chain
links inside the detail view, which inherits whatever stack presented it. That
leaves MoreRoute.patchset with no users, so it and its two destinations are
removed rather than left as a route nothing links to.

Neither the compiler nor the tests catch this: it is a runtime SwiftUI
resolution failure.

Layout: unified · split

Hutch/App/RootView.swift −3
@@ -439,7 +439,6 @@ enum MoreRoute: Hashable {
439439 case projectDashboard(id: String, title: String?)
440440 case mailingList(InboxMailingListReference)
441441 case thread(InboxThreadSummary)
442 case patchset(id: Int, listName: String?)
443442 case manPageBrowser
444443 case manPage(URL)
445444}
@@ -473,8 +472,6 @@ private struct MoreNavigationRoot: View {
473472 ProjectDashboardDeepLinkView(projectID: id, title: title)
474473 case .mailingList(let mailingList):
475474 MailingListDetailView(mailingList: mailingList)
476 case .patchset(let id, let listName):
477 PatchsetDetailView(patchsetID: id, listName: listName)
478475 case .thread(let thread):
479476 ThreadDetailView(
480477 thread: thread,
Hutch/Views/Lookup/LookupView.swift −2
@@ -465,8 +465,6 @@ struct LookupView: View {
465465 ProjectDashboardDeepLinkView(projectID: id, title: title)
466466 case .mailingList(let mailingList):
467467 MailingListDetailView(mailingList: mailingList)
468 case .patchset(let id, let listName):
469 PatchsetDetailView(patchsetID: id, listName: listName)
470468 case .thread(let thread):
471469 ThreadDetailView(
472470 thread: thread,
Hutch/Views/Patchsets/PatchsetDetailView.swift +10 −2
@@ -122,8 +122,14 @@ struct PatchsetDetailView: View {
122122
123123 // The version chain matters during review: a superseded series should
124124 // usually be read at its newest version instead.
125 //
126 // Pushed directly rather than by value, for the same reason as the rows
127 // that lead here — this view inherits whatever stack presented it, and
128 // not all of them declare a MoreRoute destination.
125129 if let supersededBy = patchset.supersededBy {
126 NavigationLink(value: MoreRoute.patchset(id: supersededBy, listName: listName)) {
130 NavigationLink {
131 PatchsetDetailView(patchsetID: supersededBy, listName: listName)
132 } label: {
127133 SwiftUI.Label("Superseded by a newer version", systemImage: "arrow.right.circle")
128134 .font(.subheadline)
129135 }
@@ -131,7 +137,9 @@ struct PatchsetDetailView: View {
131137 }
132138
133139 if let supersedes = patchset.supersedes {
134 NavigationLink(value: MoreRoute.patchset(id: supersedes, listName: listName)) {
140 NavigationLink {
141 PatchsetDetailView(patchsetID: supersedes, listName: listName)
142 } label: {
135143 SwiftUI.Label("Revises an earlier version", systemImage: "arrow.left.circle")
136144 .font(.subheadline)
137145 }
Hutch/Views/Projects/ProjectMailingListView.swift +5 −1
@@ -420,7 +420,11 @@ struct MailingListDetailView: View {
420420
421421 if showingPatches(viewModel) {
422422 ForEach(viewModel.filteredPatchsets) { patchset in
423 NavigationLink(value: MoreRoute.patchset(id: patchset.id, listName: mailingList.name)) {
423 // Pushed directly rather than by value: this view is also shown
424 // from a project, whose stack declares no MoreRoute destination.
425 NavigationLink {
426 PatchsetDetailView(patchsetID: patchset.id, listName: mailingList.name)
427 } label: {
424428 PatchsetRow(patchset: patchset)
425429 }
426430 .themedRow()