fix(apple): make the device detail screen reachable

The Settings stack has a typed path of [SettingsSection], so a
NavigationLink carrying a String could never push onto it: tapping a device
in the list did nothing. Contact detail is now a SettingsSection case, and
the path maps it to the two-level push the way the bug report screen
already does.
This commit is contained in:
2026-08-07 10:33:10 +02:00
parent 3441280599
commit 677fc3c6d5
3 changed files with 11 additions and 7 deletions

View File

@@ -25,7 +25,7 @@ struct ContactsScreen: View {
} else { } else {
Section(String(localized: L10n.Contacts.title)) { Section(String(localized: L10n.Contacts.title)) {
ForEach(model.state.contacts) { contact in ForEach(model.state.contacts) { contact in
NavigationLink(value: contact.endpointId) { NavigationLink(value: SettingsSection.contactDetail(endpointId: contact.endpointId)) {
ContactRow(contact: contact) ContactRow(contact: contact)
} }
} }
@@ -75,9 +75,6 @@ struct ContactsScreen: View {
} }
.formStyle(.grouped) .formStyle(.grouped)
.navigationTitle(Text(String(localized: L10n.Contacts.title))) .navigationTitle(Text(String(localized: L10n.Contacts.title)))
.navigationDestination(for: String.self) { endpointId in
ContactDetailScreen(model: model, endpointId: endpointId)
}
.task { await model.refresh() } .task { await model.refresh() }
} }
} }

View File

@@ -9,6 +9,9 @@ enum SettingsSection: Hashable {
case notifications case notifications
case network case network
case contacts case contacts
/// One device's detail. Part of this enum because the Settings stack has a
/// typed path: a link carrying any other value type cannot push onto it.
case contactDetail(endpointId: String)
case storage case storage
case about case about
case bugReport case bugReport
@@ -20,7 +23,7 @@ enum SettingsSection: Hashable {
case .appearance: return L10n.Appearance.title case .appearance: return L10n.Appearance.title
case .notifications: return L10n.Notifications.title case .notifications: return L10n.Notifications.title
case .network: return L10n.Settings.networkTitle case .network: return L10n.Settings.networkTitle
case .contacts: return L10n.Contacts.title case .contacts, .contactDetail: return L10n.Contacts.title
case .storage: return L10n.Storage.title case .storage: return L10n.Storage.title
case .about: return L10n.About.title case .about: return L10n.About.title
case .bugReport: return L10n.About.bugReport case .bugReport: return L10n.About.bugReport

View File

@@ -15,6 +15,8 @@ struct SettingsScreen: View {
switch model.state.selectedSection { switch model.state.selectedSection {
case .overview: return [] case .overview: return []
case .bugReport: return [.about, .bugReport] case .bugReport: return [.about, .bugReport]
case .contactDetail(let endpointId):
return [.contacts, .contactDetail(endpointId: endpointId)]
case let section: return [section] case let section: return [section]
} }
}, },
@@ -92,7 +94,9 @@ struct SettingsScreen: View {
private func sectionForm(_ section: SettingsSection) -> some View { private func sectionForm(_ section: SettingsSection) -> some View {
// Contacts brings its own Form and push destination, so it is not wrapped // Contacts brings its own Form and push destination, so it is not wrapped
// in the shared section chrome. // in the shared section chrome.
if section == .contacts { if case .contactDetail(let endpointId) = section {
ContactDetailScreen(model: contacts, endpointId: endpointId)
} else if section == .contacts {
ContactsScreen(model: contacts) { ContactsScreen(model: contacts) {
model.reportNothingWaiting() model.reportNothingWaiting()
} }
@@ -153,7 +157,7 @@ private struct SettingsSectionContent: View {
NetworkSettings(model: model) NetworkSettings(model: model)
case .storage: case .storage:
StorageSettings(model: model) StorageSettings(model: model)
case .contacts: case .contacts, .contactDetail:
// Rendered by SettingsScreen itself, which owns the contacts model. // Rendered by SettingsScreen itself, which owns the contacts model.
EmptyView() EmptyView()
case .about: case .about: