fix(ios): unify Talk and Settings row typography on one branded detail row (#100515)

* fix(ios): unify Talk and Settings row typography on one branded detail row

* chore(i18n): sync native string inventory for iOS detail row refactor
This commit is contained in:
Peter Steinberger
2026-07-06 07:46:19 +01:00
committed by GitHub
parent a18708c5c1
commit f1d28c855c
7 changed files with 127 additions and 120 deletions
+57 -57
View File
@@ -9035,7 +9035,7 @@
},
{
"kind": "conditional-branch",
"line": 867,
"line": 858,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Configured",
"surface": "apple",
@@ -9043,7 +9043,7 @@
},
{
"kind": "conditional-branch",
"line": 867,
"line": 858,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Not configured",
"surface": "apple",
@@ -9051,7 +9051,7 @@
},
{
"kind": "conditional-branch",
"line": 932,
"line": 923,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Connect to the gateway.",
"surface": "apple",
@@ -9059,7 +9059,7 @@
},
{
"kind": "conditional-branch",
"line": 932,
"line": 923,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Gateway requests will appear here.",
"surface": "apple",
@@ -9067,7 +9067,7 @@
},
{
"kind": "conditional-branch",
"line": 979,
"line": 970,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "High",
"surface": "apple",
@@ -9075,7 +9075,7 @@
},
{
"kind": "conditional-branch",
"line": 979,
"line": 970,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Resolving",
"surface": "apple",
@@ -9083,7 +9083,7 @@
},
{
"kind": "conditional-branch",
"line": 984,
"line": 975,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "One-time approval",
"surface": "apple",
@@ -9091,7 +9091,7 @@
},
{
"kind": "conditional-branch",
"line": 984,
"line": 975,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Permission can be saved",
"surface": "apple",
@@ -9099,7 +9099,7 @@
},
{
"kind": "conditional-branch",
"line": 986,
"line": 977,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Medium",
"surface": "apple",
@@ -9107,7 +9107,7 @@
},
{
"kind": "conditional-branch",
"line": 986,
"line": 977,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Review",
"surface": "apple",
@@ -9115,7 +9115,7 @@
},
{
"kind": "conditional-branch",
"line": 1007,
"line": 998,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "\\(diagnosticsIssueCount)",
"surface": "apple",
@@ -9123,7 +9123,7 @@
},
{
"kind": "conditional-branch",
"line": 1018,
"line": 1009,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Location off",
"surface": "apple",
@@ -9131,7 +9131,7 @@
},
{
"kind": "conditional-branch",
"line": 1020,
"line": 1011,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Location While Using",
"surface": "apple",
@@ -9139,7 +9139,7 @@
},
{
"kind": "conditional-branch",
"line": 1022,
"line": 1013,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Location While Using, effective Off",
"surface": "apple",
@@ -9147,7 +9147,7 @@
},
{
"kind": "conditional-branch",
"line": 1024,
"line": 1015,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Location While Using, effective Always",
"surface": "apple",
@@ -9155,7 +9155,7 @@
},
{
"kind": "conditional-branch",
"line": 1026,
"line": 1017,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Location Always",
"surface": "apple",
@@ -9163,7 +9163,7 @@
},
{
"kind": "conditional-branch",
"line": 1028,
"line": 1019,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Location Always, effective While Using",
"surface": "apple",
@@ -9171,7 +9171,7 @@
},
{
"kind": "conditional-branch",
"line": 1030,
"line": 1021,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Location Always, effective Off",
"surface": "apple",
@@ -9179,7 +9179,7 @@
},
{
"kind": "conditional-branch",
"line": 1058,
"line": 1049,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Checking iOS notification permission.",
"surface": "apple",
@@ -9187,7 +9187,7 @@
},
{
"kind": "conditional-branch",
"line": 1060,
"line": 1051,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "OpenClaw can show approval prompts and event alerts when the app is not active.",
"surface": "apple",
@@ -9195,7 +9195,7 @@
},
{
"kind": "conditional-branch",
"line": 1062,
"line": 1053,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Notifications have been denied. Enable them in iOS Settings.",
"surface": "apple",
@@ -9203,7 +9203,7 @@
},
{
"kind": "conditional-branch",
"line": 1064,
"line": 1055,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "Enable notifications to receive approval prompts and event alerts outside the app.",
"surface": "apple",
@@ -9211,7 +9211,7 @@
},
{
"kind": "conditional-branch",
"line": 1066,
"line": 1057,
"path": "apps/ios/Sources/Design/SettingsProTabActions.swift",
"source": "OpenClaw cannot determine the current notification permission state.",
"surface": "apple",
@@ -9874,12 +9874,12 @@
"id": "native.apple.518cef9408771a92"
},
{
"kind": "ui-named-argument",
"line": 946,
"kind": "ui-call",
"line": 945,
"path": "apps/ios/Sources/Design/SettingsProTabSections.swift",
"source": "Wake Words",
"surface": "apple",
"id": "native.apple.e1383011b9ccc3a3"
"id": "native.apple.1604352fea16d495"
},
{
"kind": "ui-call",
@@ -9994,12 +9994,12 @@
"id": "native.apple.c695f785d4f3331a"
},
{
"kind": "ui-named-argument",
"kind": "ui-call",
"line": 1030,
"path": "apps/ios/Sources/Design/SettingsProTabSections.swift",
"source": "Discovery Logs",
"surface": "apple",
"id": "native.apple.2bb13c2d7465f99e"
"id": "native.apple.8584babe715b1133"
},
{
"kind": "ui-call",
@@ -10027,7 +10027,7 @@
},
{
"kind": "conditional-branch",
"line": 93,
"line": 118,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Enabled",
"surface": "apple",
@@ -10035,7 +10035,7 @@
},
{
"kind": "conditional-branch",
"line": 94,
"line": 119,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Denied",
"surface": "apple",
@@ -10043,7 +10043,7 @@
},
{
"kind": "conditional-branch",
"line": 95,
"line": 120,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Not Enabled",
"surface": "apple",
@@ -10051,7 +10051,7 @@
},
{
"kind": "conditional-branch",
"line": 96,
"line": 121,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Unknown",
"surface": "apple",
@@ -10059,7 +10059,7 @@
},
{
"kind": "conditional-branch",
"line": 102,
"line": 127,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Enable Notifications",
"surface": "apple",
@@ -10067,7 +10067,7 @@
},
{
"kind": "conditional-branch",
"line": 104,
"line": 129,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Checking",
"surface": "apple",
@@ -10075,7 +10075,7 @@
},
{
"kind": "conditional-branch",
"line": 106,
"line": 131,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Manage in iOS Settings",
"surface": "apple",
@@ -10083,7 +10083,7 @@
},
{
"kind": "conditional-branch",
"line": 108,
"line": 133,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Open iOS Settings",
"surface": "apple",
@@ -10091,7 +10091,7 @@
},
{
"kind": "ui-call",
"line": 250,
"line": 275,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Connected",
"surface": "apple",
@@ -10099,7 +10099,7 @@
},
{
"kind": "ui-named-argument",
"line": 252,
"line": 277,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Gateway online",
"surface": "apple",
@@ -10107,7 +10107,7 @@
},
{
"kind": "ui-named-argument",
"line": 253,
"line": 278,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Connected to openclaw-gateway.tailnet.ts.net.",
"surface": "apple",
@@ -10115,7 +10115,7 @@
},
{
"kind": "ui-call",
"line": 263,
"line": 288,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Loading",
"surface": "apple",
@@ -10123,7 +10123,7 @@
},
{
"kind": "ui-named-argument",
"line": 265,
"line": 290,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Checking gateway",
"surface": "apple",
@@ -10131,7 +10131,7 @@
},
{
"kind": "ui-named-argument",
"line": 266,
"line": 291,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Refreshing connection, discovery, and device trust state.",
"surface": "apple",
@@ -10139,7 +10139,7 @@
},
{
"kind": "ui-call",
"line": 272,
"line": 297,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Empty",
"surface": "apple",
@@ -10147,7 +10147,7 @@
},
{
"kind": "ui-named-argument",
"line": 274,
"line": 299,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "No gateway configured",
"surface": "apple",
@@ -10155,7 +10155,7 @@
},
{
"kind": "ui-named-argument",
"line": 275,
"line": 300,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Scan a setup QR code, paste a setup code, or choose a discovered gateway.",
"surface": "apple",
@@ -10163,7 +10163,7 @@
},
{
"kind": "ui-call",
"line": 281,
"line": 306,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Error",
"surface": "apple",
@@ -10171,7 +10171,7 @@
},
{
"kind": "ui-named-argument",
"line": 283,
"line": 308,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Tailscale warning",
"surface": "apple",
@@ -10179,7 +10179,7 @@
},
{
"kind": "ui-named-argument",
"line": 284,
"line": 309,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Tailscale is off on this device. Turn it on, then try again.",
"surface": "apple",
@@ -10187,7 +10187,7 @@
},
{
"kind": "ui-call",
"line": 333,
"line": 358,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Address",
"surface": "apple",
@@ -10195,7 +10195,7 @@
},
{
"kind": "ui-call",
"line": 335,
"line": 360,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Server",
"surface": "apple",
@@ -10203,7 +10203,7 @@
},
{
"kind": "ui-call",
"line": 337,
"line": 362,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Discovered",
"surface": "apple",
@@ -10211,7 +10211,7 @@
},
{
"kind": "ui-call",
"line": 339,
"line": 364,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Default Agent",
"surface": "apple",
@@ -10219,7 +10219,7 @@
},
{
"kind": "ui-call",
"line": 361,
"line": 386,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Reconnect",
"surface": "apple",
@@ -10227,7 +10227,7 @@
},
{
"kind": "ui-call",
"line": 362,
"line": 387,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Diagnose",
"surface": "apple",
@@ -10235,7 +10235,7 @@
},
{
"kind": "ui-call",
"line": 371,
"line": 396,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Scan QR",
"surface": "apple",
@@ -10243,7 +10243,7 @@
},
{
"kind": "ui-call",
"line": 372,
"line": 397,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Connect",
"surface": "apple",
@@ -10251,7 +10251,7 @@
},
{
"kind": "ui-call",
"line": 374,
"line": 399,
"path": "apps/ios/Sources/Design/SettingsProTabSupport.swift",
"source": "Discovered gateways and manual setup live here when the gateway has not connected yet.",
"surface": "apple",
@@ -108,15 +108,6 @@ extension SettingsProTab {
}
}
func detailRow(_ label: String, value: String) -> some View {
LabeledContent(label) {
Text(value)
.font(OpenClawType.subhead)
.lineLimit(1)
.truncationMode(.middle)
}
}
func reconnectGateway() async {
guard !self.appModel.isAppleReviewDemoModeEnabled else { return }
guard !self.isReconnectingGateway else { return }
@@ -113,9 +113,9 @@ extension SettingsProTab {
NavigationLink(value: SettingsRoute.gateway) {
self.gatewayConnectionRow
}
LabeledContent("Address", value: self.gatewayAddress)
LabeledContent("Server", value: self.gatewayServer)
LabeledContent("Agents", value: "\(self.appModel.gatewayAgents.count)")
SettingsDetailRow("Address", value: self.gatewayAddress)
SettingsDetailRow("Server", value: self.gatewayServer)
SettingsDetailRow("Agents", value: "\(self.appModel.gatewayAgents.count)")
self.gatewayActions
}
}
@@ -272,11 +272,11 @@ extension SettingsProTab {
color: self.gatewayStatusColor)
self.detailListCard {
self.detailRow("Address", value: self.gatewayAddress)
self.detailRow("Server", value: self.gatewayServer)
self.detailRow("Discovered", value: "\(self.gatewayController.gateways.count)")
self.detailRow("Default Agent", value: self.appModel.activeAgentName)
self.detailRow("Agents", value: "\(self.appModel.gatewayAgents.count)")
SettingsDetailRow("Address", value: self.gatewayAddress)
SettingsDetailRow("Server", value: self.gatewayServer)
SettingsDetailRow("Discovered", value: "\(self.gatewayController.gateways.count)")
SettingsDetailRow("Default Agent", value: self.appModel.activeAgentName)
SettingsDetailRow("Agents", value: "\(self.appModel.gatewayAgents.count)")
}
Section {
@@ -457,10 +457,10 @@ extension SettingsProTab {
self.diagnosticChecksCard
self.detailListCard {
self.detailRow("Device", value: DeviceInfoHelper.deviceFamily())
self.detailRow("Platform", value: DeviceInfoHelper.platformStringForDisplay())
self.detailRow("App", value: DeviceInfoHelper.openClawVersionString())
self.detailRow("Model", value: DeviceInfoHelper.modelIdentifier())
SettingsDetailRow("Device", value: DeviceInfoHelper.deviceFamily())
SettingsDetailRow("Platform", value: DeviceInfoHelper.platformStringForDisplay())
SettingsDetailRow("App", value: DeviceInfoHelper.openClawVersionString())
SettingsDetailRow("Model", value: DeviceInfoHelper.modelIdentifier())
}
self.diagnosticsAdvancedCard
@@ -638,9 +638,9 @@ extension SettingsProTab {
// Concise public details only; deep hardware identifiers live in Diagnostics.
detailListCard {
self.detailRow("OpenClaw app version", value: DeviceInfoHelper.openClawVersionString())
self.detailRow("Device", value: DeviceInfoHelper.deviceFamily())
self.detailRow("iOS", value: DeviceInfoHelper.iOSVersionStringForDisplay())
SettingsDetailRow("OpenClaw app version", value: DeviceInfoHelper.openClawVersionString())
SettingsDetailRow("Device", value: DeviceInfoHelper.deviceFamily())
SettingsDetailRow("iOS", value: DeviceInfoHelper.iOSVersionStringForDisplay())
}
Section {
@@ -942,8 +942,8 @@ extension SettingsProTab {
NavigationLink {
VoiceWakeWordsSettingsView()
} label: {
self.simpleSettingsRow(
title: "Wake Words",
SettingsDetailRow(
"Wake Words",
value: VoiceWakePreferences.displayString(for: self.voiceWake.triggerWords))
}
}
@@ -979,13 +979,13 @@ extension SettingsProTab {
}
.font(OpenClawType.body)
}
self.detailRow("Voice Mode", value: self.appModel.talkMode.gatewayTalkVoiceModeTitle)
self.detailRow("Active Voice", value: self.gatewayTalkActiveVoiceDetail)
SettingsDetailRow("Voice Mode", value: self.appModel.talkMode.gatewayTalkVoiceModeTitle)
SettingsDetailRow("Active Voice", value: self.gatewayTalkActiveVoiceDetail)
if let issue = self.gatewayTalkLastIssueDetail {
self.detailRow("Last Voice Issue", value: issue)
SettingsDetailRow("Last Voice Issue", value: issue)
}
self.detailRow("Transport", value: self.appModel.talkMode.gatewayTalkTransportLabel)
self.detailRow("API Key", value: self.talkApiKeyStatus)
SettingsDetailRow("Transport", value: self.appModel.talkMode.gatewayTalkTransportLabel)
SettingsDetailRow("API Key", value: self.talkApiKeyStatus)
}
}
}
@@ -1027,7 +1027,7 @@ extension SettingsProTab {
NavigationLink {
GatewayDiscoveryDebugLogView()
} label: {
self.simpleSettingsRow(title: "Discovery Logs", value: self.gatewayController.discoveryStatusText)
SettingsDetailRow("Discovery Logs", value: self.gatewayController.discoveryStatusText)
}
}
}
@@ -1036,7 +1036,7 @@ extension SettingsProTab {
Section("Device") {
TextField("Device Name", text: self.$displayName)
.font(OpenClawType.body)
self.detailRow("Instance ID", value: self.instanceId)
SettingsDetailRow("Instance ID", value: self.instanceId)
}
}
@@ -1047,19 +1047,10 @@ extension SettingsProTab {
{
Toggle(isOn: isOn) {
Text(title)
.font(OpenClawType.subhead)
.font(OpenClawType.body)
}
.onChange(of: isOn.wrappedValue) { _, enabled in
onChange?(enabled)
}
}
func simpleSettingsRow(title: String, value: String) -> some View {
LabeledContent(title) {
Text(value)
.font(OpenClawType.subhead)
.lineLimit(1)
.truncationMode(.middle)
}
}
}
@@ -21,6 +21,31 @@ enum SettingsLayout {
static let rowHeight: CGFloat = 58
}
/// Canonical label/value list row for Settings and Talk surfaces. Keep every
/// detail row on this view so row typography cannot drift between sections;
/// plain `LabeledContent(String, value:)` renders unbranded system fonts.
struct SettingsDetailRow: View {
let label: String
let value: String
init(_ label: String, value: String) {
self.label = label
self.value = value
}
var body: some View {
LabeledContent {
Text(self.value)
.font(OpenClawType.subhead)
.lineLimit(1)
.truncationMode(.middle)
} label: {
Text(self.label)
.font(OpenClawType.body)
}
}
}
struct SettingsApprovalItem: Identifiable {
let id: String
let icon: String
+9 -9
View File
@@ -150,22 +150,22 @@ struct TalkProTab: View {
private var conversationSection: some View {
Section("Conversation") {
LabeledContent("Agent", value: self.appModel.chatAgentName)
LabeledContent("Session", value: self.appModel.chatSessionKey)
LabeledContent("Runtime", value: self.appModel.talkMode.statusText)
SettingsDetailRow("Agent", value: self.appModel.chatAgentName)
SettingsDetailRow("Session", value: self.appModel.chatSessionKey)
SettingsDetailRow("Runtime", value: self.appModel.talkMode.statusText)
}
}
private var voiceModeSection: some View {
Section("Voice Mode") {
LabeledContent("Configured", value: self.appModel.talkMode.gatewayTalkVoiceModeTitle)
LabeledContent("Active", value: self.activeModeText)
LabeledContent("Transport", value: self.transportText)
SettingsDetailRow("Configured", value: self.appModel.talkMode.gatewayTalkVoiceModeTitle)
SettingsDetailRow("Active", value: self.activeModeText)
SettingsDetailRow("Transport", value: self.transportText)
if let issueText = self.talkIssueText {
LabeledContent("Last issue", value: issueText)
SettingsDetailRow("Last issue", value: issueText)
}
LabeledContent("Permission", value: self.permissionText)
LabeledContent("Speech language", value: self.speechLocaleText)
SettingsDetailRow("Permission", value: self.permissionText)
SettingsDetailRow("Speech language", value: self.speechLocaleText)
}
}
+2 -2
View File
@@ -216,7 +216,7 @@ struct OpenClawTypographyTests {
#expect(settingsSections.contains(".font(OpenClawType.subhead)"))
#expect(settingsSections.contains("private struct AppearanceSettingsScreen"))
#expect(settingsSections.contains("Section(\"Gateway\")"))
#expect(settingsSections.contains("LabeledContent(\"Address\", value: self.gatewayAddress)"))
#expect(settingsSections.contains("SettingsDetailRow(\"Address\", value: self.gatewayAddress)"))
#expect(settingsSections.contains("func gatewayActionButton"))
#expect(settingsSections.contains("func settingsToggle"))
#expect(settingsSections.contains(".font(OpenClawType.subheadSemiBold)"))
@@ -387,7 +387,7 @@ struct OpenClawTypographyTests {
private static func isShorthandControlCall(_ line: String) -> Bool {
line.range(
of: #"\b(Button|Link|Picker|Toggle|TextField|SecureField|Menu|DisclosureGroup)\s*\(""#,
of: #"\b(Button|Link|Picker|Toggle|TextField|SecureField|Menu|DisclosureGroup|LabeledContent)\s*\(""#,
options: .regularExpression) != nil
}
@@ -291,17 +291,17 @@ struct RootTabsSourceGuardTests {
#expect(!aboutDestination.contains("detailStatusCard("))
#expect(aboutDestination.contains("detailListCard"))
#expect(aboutDestination.contains("self.detailRow(\"OpenClaw app version\""))
#expect(aboutDestination.contains("self.detailRow(\"Device\", value: DeviceInfoHelper.deviceFamily())"))
#expect(aboutDestination.contains("SettingsDetailRow(\"OpenClaw app version\""))
#expect(aboutDestination.contains("SettingsDetailRow(\"Device\", value: DeviceInfoHelper.deviceFamily())"))
#expect(aboutDestination
.contains("self.detailRow(\"iOS\", value: DeviceInfoHelper.iOSVersionStringForDisplay())"))
#expect(!aboutDestination.contains("self.detailRow(\"Version\""))
#expect(!aboutDestination.contains("self.detailRow(\"Platform\""))
#expect(!aboutDestination.contains("self.detailRow(\"Model\""))
#expect(diagnosticsDestination.contains("self.detailRow(\"Device\", value: DeviceInfoHelper.deviceFamily())"))
.contains("SettingsDetailRow(\"iOS\", value: DeviceInfoHelper.iOSVersionStringForDisplay())"))
#expect(!aboutDestination.contains("SettingsDetailRow(\"Version\""))
#expect(!aboutDestination.contains("SettingsDetailRow(\"Platform\""))
#expect(!aboutDestination.contains("SettingsDetailRow(\"Model\""))
#expect(diagnosticsDestination.contains("SettingsDetailRow(\"Device\", value: DeviceInfoHelper.deviceFamily())"))
#expect(diagnosticsDestination
.contains("self.detailRow(\"Platform\", value: DeviceInfoHelper.platformStringForDisplay())"))
#expect(diagnosticsDestination.contains("self.detailRow(\"Model\", value: DeviceInfoHelper.modelIdentifier())"))
.contains("SettingsDetailRow(\"Platform\", value: DeviceInfoHelper.platformStringForDisplay())"))
#expect(diagnosticsDestination.contains("SettingsDetailRow(\"Model\", value: DeviceInfoHelper.modelIdentifier())"))
}
@Test func `routed headers use shared adaptive layout`() throws {