Remove IOSOnlyNavBar, macNavigationHeader, offlineMacHeader and all navigationBarHidden conditionals that caused doubled or missing controls on Mac Catalyst and iPad. Apply .navigationBarTitleDisplayMode(.inline) consistently across every detail, session and wizard view. Bump nav bar title font to 19pt semibold via UINavigationBarAppearance. Add Documentation/Navigation Style Decisions.md describing the deviations from SwiftUI defaults and the rationale for each. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@@ -0,0 +1,56 @@ |
||
| 1 |
+# Navigation Style Decisions |
|
| 2 |
+ |
|
| 3 |
+## Obiectiv |
|
| 4 |
+ |
|
| 5 |
+Navigația aplicației folosește stilul SwiftUI implicit, cu un singur set de modificatori aplicat consistent în toate view-urile. Nu există logică condiționată per platformă pentru controlul navigației. |
|
| 6 |
+ |
|
| 7 |
+## Deviații de la comportamentul SwiftUI implicit |
|
| 8 |
+ |
|
| 9 |
+### 1. Titlu inline (`.navigationBarTitleDisplayMode(.inline)`) |
|
| 10 |
+ |
|
| 11 |
+**Aplicat pe:** toate view-urile care au `.navigationTitle(...)`. |
|
| 12 |
+ |
|
| 13 |
+**Motivație:** Implicit, SwiftUI afișează titlul mare (`.large`) în prima fereastră a unui NavigationStack sau NavigationView. Stilul large nu se potrivește layoutului aplicației, care folosește un tab bar custom imediat sub navigation bar — titlul mare consumă spațiu vertical fără beneficiu. Stilul inline plasează titlul centrat în toolbar, aliniind aspectul pe iPhone, iPad și Mac Catalyst. |
|
| 14 |
+ |
|
| 15 |
+**Fișiere afectate:** |
|
| 16 |
+- `Views/Meter/MeterView.swift` — live body și offline body |
|
| 17 |
+- `Views/ChargedDevices/Details/ChargedDeviceDetailView.swift` |
|
| 18 |
+- `Views/ChargedDevices/Sessions/ChargeSessionDetailView.swift` |
|
| 19 |
+- `Views/ChargedDevices/Sessions/ChargedDeviceSessionsView.swift` |
|
| 20 |
+- `Views/Meter/Tabs/Live/ChargerStandbyPowerWizardView.swift` |
|
| 21 |
+- `Views/MeterMappingDebugView.swift` |
|
| 22 |
+- `Views/DeviceHelpView.swift` |
|
| 23 |
+- Sheets (deja aveau `.inline`): `ChargedDeviceEditorScaffoldView`, `SidebarChargedDeviceLibraryView`, și altele |
|
| 24 |
+ |
|
| 25 |
+### 2. Font titlu navigation bar (19pt semibold) |
|
| 26 |
+ |
|
| 27 |
+**Aplicat în:** `AppDelegate.configureNavigationBarAppearance()` via `UINavigationBarAppearance`. |
|
| 28 |
+ |
|
| 29 |
+**Motivație:** Fontul implicit al titlului inline este `.headline` (17pt semibold), perceput ca prea mic față de densitatea vizuală a conținutului. 19pt semibold oferă mai multă prezență fără a afecta spațiul disponibil, întrucât titlul rămâne pe un singur rând. |
|
| 30 |
+ |
|
| 31 |
+**Configurare:** |
|
| 32 |
+```swift |
|
| 33 |
+let titleFont = UIFont.systemFont(ofSize: 19, weight: .semibold) |
|
| 34 |
+let appearance = UINavigationBarAppearance() |
|
| 35 |
+appearance.configureWithDefaultBackground() |
|
| 36 |
+appearance.titleTextAttributes = [.font: titleFont] |
|
| 37 |
+UINavigationBar.appearance().standardAppearance = appearance |
|
| 38 |
+UINavigationBar.appearance().scrollEdgeAppearance = appearance |
|
| 39 |
+UINavigationBar.appearance().compactAppearance = appearance |
|
| 40 |
+``` |
|
| 41 |
+ |
|
| 42 |
+## Ce NU s-a schimbat față de implicit |
|
| 43 |
+ |
|
| 44 |
+- `NavigationView` cu `.navigationViewStyle(.stack)` pe iPhone și `.navigationViewStyle(.columns)` pe iPad/Mac — arhitectural, nu cosmetic |
|
| 45 |
+- Toolbar items (`.toolbar { }`) — plasate standard pe `.navigationBarTrailing` / `.cancellationAction` / `.confirmationAction`
|
|
| 46 |
+- Fundalul navigation bar — `configureWithDefaultBackground()` păstrează comportamentul implicit al sistemului (translucid/blur) |
|
| 47 |
+ |
|
| 48 |
+## Istoric |
|
| 49 |
+ |
|
| 50 |
+Anterior existau mai multe straturi de modificatori conflictuali adăugați în tentative de a obține un layout compact "Nav Control – Title – Tools" pe Mac Catalyst și iPad: |
|
| 51 |
+- `navigationBarHidden(landscape)` — ascundea bara în landscape pe Catalyst |
|
| 52 |
+- `IOSOnlyNavBar` (ViewModifier) — aplica titlu și toolbar condițional pe `!isTrueMacApp` |
|
| 53 |
+- `macNavigationHeader` și `offlineMacHeader` — headere custom inline în VStack care dublau controalele când bara de sistem era vizibilă |
|
| 54 |
+- `ToolbarItemGroup(placement: .primaryAction) {}` gol pe Catalyst — crea artefacte vizuale
|
|
| 55 |
+ |
|
| 56 |
+Toate au fost eliminate în aprilie 2026. Soluția corectă a fost `.navigationBarTitleDisplayMode(.inline)` aplicat consistent. |
|
@@ -136,9 +136,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD |
||
| 136 | 136 |
UNUserNotificationCenter.current().delegate = self |
| 137 | 137 |
application.registerForRemoteNotifications() |
| 138 | 138 |
appData.activateChargeInsights(context: persistentContainer.viewContext) |
| 139 |
+ configureNavigationBarAppearance() |
|
| 139 | 140 |
return true |
| 140 | 141 |
} |
| 141 | 142 |
|
| 143 |
+ private func configureNavigationBarAppearance() {
|
|
| 144 |
+ let titleFont = UIFont.systemFont(ofSize: 19, weight: .semibold) |
|
| 145 |
+ let appearance = UINavigationBarAppearance() |
|
| 146 |
+ appearance.configureWithDefaultBackground() |
|
| 147 |
+ appearance.titleTextAttributes = [.font: titleFont] |
|
| 148 |
+ UINavigationBar.appearance().standardAppearance = appearance |
|
| 149 |
+ UINavigationBar.appearance().scrollEdgeAppearance = appearance |
|
| 150 |
+ UINavigationBar.appearance().compactAppearance = appearance |
|
| 151 |
+ } |
|
| 152 |
+ |
|
| 142 | 153 |
private func logRuntimeICloudDiagnostics() {
|
| 143 | 154 |
#if DEBUG |
| 144 | 155 |
let hasUbiquityIdentityToken = FileManager.default.ubiquityIdentityToken != nil |
@@ -7,27 +7,3 @@ |
||
| 7 | 7 |
// |
| 8 | 8 |
|
| 9 | 9 |
import SwiftUI |
| 10 |
- |
|
| 11 |
-/* MARK: Iusless... |
|
| 12 |
-enum XNavigationViewStyle {
|
|
| 13 |
- case auto |
|
| 14 |
- case doubleColumn |
|
| 15 |
- case stack |
|
| 16 |
-} |
|
| 17 |
- |
|
| 18 |
-extension View {
|
|
| 19 |
- func xNavigationViewStyle(_ style: XNavigationViewStyle) -> some View {
|
|
| 20 |
- switch style {
|
|
| 21 |
- case .auto: |
|
| 22 |
- track("auto")
|
|
| 23 |
- return AnyView(self.navigationViewStyle(DefaultNavigationViewStyle())) |
|
| 24 |
- case .doubleColumn: |
|
| 25 |
- track("doubleColumn")
|
|
| 26 |
- return AnyView(self.navigationViewStyle(DoubleColumnNavigationViewStyle())) |
|
| 27 |
- case .stack: |
|
| 28 |
- track("stack")
|
|
| 29 |
- return AnyView(self.navigationViewStyle(StackNavigationViewStyle())) |
|
| 30 |
- } |
|
| 31 |
- } |
|
| 32 |
-} |
|
| 33 |
-*/ |
|
@@ -33,10 +33,12 @@ struct ChargedDeviceDetailView: View {
|
||
| 33 | 33 |
if let chargedDevice = appData.chargedDeviceSummary(id: chargedDeviceID) {
|
| 34 | 34 |
tabbedDetailView(chargedDevice) |
| 35 | 35 |
.navigationTitle(chargedDevice.name) |
| 36 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 36 | 37 |
} else {
|
| 37 | 38 |
Text("This device is no longer available.")
|
| 38 | 39 |
.foregroundColor(.secondary) |
| 39 | 40 |
.navigationTitle("Device")
|
| 41 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 40 | 42 |
} |
| 41 | 43 |
} |
| 42 | 44 |
.sidebarToggleToolbarItem() |
@@ -233,6 +233,7 @@ struct ChargeSessionDetailView: View {
|
||
| 233 | 233 |
.ignoresSafeArea() |
| 234 | 234 |
) |
| 235 | 235 |
.navigationTitle(session.status.isOpen ? "Current Session" : "Session Details") |
| 236 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 236 | 237 |
.toolbar {
|
| 237 | 238 |
ToolbarItemGroup(placement: .primaryAction) {
|
| 238 | 239 |
if session.status.isOpen == false {
|
@@ -262,6 +263,7 @@ struct ChargeSessionDetailView: View {
|
||
| 262 | 263 |
.frame(maxWidth: .infinity, maxHeight: .infinity) |
| 263 | 264 |
.padding(24) |
| 264 | 265 |
.navigationTitle("Session")
|
| 266 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 265 | 267 |
} |
| 266 | 268 |
|
| 267 | 269 |
private func monitoringSessionCard( |
@@ -64,10 +64,12 @@ struct ChargedDeviceSessionsView: View {
|
||
| 64 | 64 |
.ignoresSafeArea() |
| 65 | 65 |
) |
| 66 | 66 |
.navigationTitle("Sessions")
|
| 67 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 67 | 68 |
} else {
|
| 68 | 69 |
Text("This device is no longer available.")
|
| 69 | 70 |
.foregroundColor(.secondary) |
| 70 | 71 |
.navigationTitle("Sessions")
|
| 72 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 71 | 73 |
} |
| 72 | 74 |
} |
| 73 | 75 |
.alert(item: $pendingSessionDeletion) { session in
|
@@ -43,6 +43,7 @@ struct DeviceHelpView: View {
|
||
| 43 | 43 |
.ignoresSafeArea() |
| 44 | 44 |
) |
| 45 | 45 |
.navigationTitle("Device Help")
|
| 46 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 46 | 47 |
.sidebarToggleToolbarItem() |
| 47 | 48 |
} |
| 48 | 49 |
|
@@ -106,13 +106,7 @@ struct MeterView: View {
|
||
| 106 | 106 |
private static let isPhone: Bool = false |
| 107 | 107 |
#endif |
| 108 | 108 |
|
| 109 |
- // True only on Mac iPad App (Designed for iPad), false on Catalyst |
|
| 110 |
- private static let isTrueMacApp: Bool = ProcessInfo.processInfo.isiOSAppOnMac && !ProcessInfo.processInfo.isMacCatalystApp |
|
| 111 |
- |
|
| 112 | 109 |
@State private var selectedMeterTab: MeterTab = .home |
| 113 |
- @State private var navBarTitle: String = "Meter" |
|
| 114 |
- @State private var navBarShowRSSI: Bool = false |
|
| 115 |
- @State private var navBarRSSI: Int = 0 |
|
| 116 | 110 |
@State private var landscapeTabBarHeight: CGFloat = 0 |
| 117 | 111 |
|
| 118 | 112 |
// Offline mode state |
@@ -151,10 +145,6 @@ struct MeterView: View {
|
||
| 151 | 145 |
) |
| 152 | 146 |
|
| 153 | 147 |
VStack(spacing: 0) {
|
| 154 |
- // Use custom header only on true Mac iPad App (Designed for iPad on Mac) |
|
| 155 |
- if Self.isTrueMacApp {
|
|
| 156 |
- macNavigationHeader |
|
| 157 |
- } |
|
| 158 | 148 |
Group {
|
| 159 | 149 |
if landscape {
|
| 160 | 150 |
landscapeDeck( |
@@ -173,34 +163,23 @@ struct MeterView: View {
|
||
| 173 | 163 |
} |
| 174 | 164 |
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) |
| 175 | 165 |
} |
| 176 |
- #if !targetEnvironment(macCatalyst) |
|
| 177 |
- .navigationBarHidden(Self.isTrueMacApp && landscape) |
|
| 178 |
- #else |
|
| 179 |
- .navigationBarHidden(landscape) |
|
| 180 |
- #endif |
|
| 181 | 166 |
} |
| 182 | 167 |
.background(meterBackground) |
| 183 |
- .modifier(IOSOnlyNavBar( |
|
| 184 |
- apply: !Self.isTrueMacApp, |
|
| 185 |
- title: navBarTitle, |
|
| 186 |
- showRSSI: navBarShowRSSI, |
|
| 187 |
- rssi: navBarRSSI, |
|
| 188 |
- meter: meter |
|
| 189 |
- )) |
|
| 190 |
- .onAppear {
|
|
| 191 |
- navBarTitle = meter.name.isEmpty ? "Meter" : meter.name |
|
| 192 |
- navBarShowRSSI = meter.operationalState > .notPresent |
|
| 193 |
- navBarRSSI = meter.btSerial.averageRSSI |
|
| 194 |
- } |
|
| 195 |
- .onChange(of: meter.name) { name in
|
|
| 196 |
- navBarTitle = name.isEmpty ? "Meter" : name |
|
| 197 |
- } |
|
| 198 |
- .onChange(of: meter.operationalState) { state in
|
|
| 199 |
- navBarShowRSSI = state > .notPresent |
|
| 200 |
- } |
|
| 201 |
- .onChange(of: meter.btSerial.averageRSSI) { newRSSI in
|
|
| 202 |
- if abs(newRSSI - navBarRSSI) >= 5 {
|
|
| 203 |
- navBarRSSI = newRSSI |
|
| 168 |
+ .navigationTitle(meter.name.isEmpty ? "Meter" : meter.name) |
|
| 169 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 170 |
+ .toolbar {
|
|
| 171 |
+ ToolbarItemGroup(placement: .navigationBarTrailing) {
|
|
| 172 |
+ MeterConnectionToolbarButton( |
|
| 173 |
+ operationalState: meter.operationalState, |
|
| 174 |
+ showsTitle: false, |
|
| 175 |
+ connectAction: { meter.connect() },
|
|
| 176 |
+ disconnectAction: { meter.disconnect() }
|
|
| 177 |
+ ) |
|
| 178 |
+ .font(.body.weight(.semibold)) |
|
| 179 |
+ if meter.operationalState > .notPresent {
|
|
| 180 |
+ RSSIView(RSSI: meter.btSerial.averageRSSI) |
|
| 181 |
+ .frame(width: 18, height: 18) |
|
| 182 |
+ } |
|
| 204 | 183 |
} |
| 205 | 184 |
} |
| 206 | 185 |
.onChange(of: selectedMeterTab) { newTab in
|
@@ -208,55 +187,6 @@ struct MeterView: View {
|
||
| 208 | 187 |
} |
| 209 | 188 |
} |
| 210 | 189 |
|
| 211 |
- // MARK: - Custom navigation header for Designed-for-iPad on Mac |
|
| 212 |
- |
|
| 213 |
- private var macNavigationHeader: some View {
|
|
| 214 |
- HStack(spacing: 12) {
|
|
| 215 |
- Button {
|
|
| 216 |
- dismiss() |
|
| 217 |
- } label: {
|
|
| 218 |
- HStack(spacing: 4) {
|
|
| 219 |
- Image(systemName: "chevron.left") |
|
| 220 |
- .font(.body.weight(.semibold)) |
|
| 221 |
- Text("USB Meters")
|
|
| 222 |
- } |
|
| 223 |
- .foregroundColor(.accentColor) |
|
| 224 |
- } |
|
| 225 |
- .buttonStyle(.plain) |
|
| 226 |
- |
|
| 227 |
- Text(meter.name.isEmpty ? "Meter" : meter.name) |
|
| 228 |
- .font(.headline) |
|
| 229 |
- .lineLimit(1) |
|
| 230 |
- |
|
| 231 |
- Spacer() |
|
| 232 |
- |
|
| 233 |
- MeterConnectionToolbarButton( |
|
| 234 |
- operationalState: meter.operationalState, |
|
| 235 |
- showsTitle: true, |
|
| 236 |
- connectAction: { meter.connect() },
|
|
| 237 |
- disconnectAction: { meter.disconnect() }
|
|
| 238 |
- ) |
|
| 239 |
- |
|
| 240 |
- if meter.operationalState > .notPresent {
|
|
| 241 |
- RSSIView(RSSI: meter.btSerial.averageRSSI) |
|
| 242 |
- .frame(width: 18, height: 18) |
|
| 243 |
- } |
|
| 244 |
- |
|
| 245 |
- } |
|
| 246 |
- .padding(.horizontal, 16) |
|
| 247 |
- .padding(.vertical, 10) |
|
| 248 |
- .background( |
|
| 249 |
- Rectangle() |
|
| 250 |
- .fill(.ultraThinMaterial) |
|
| 251 |
- .ignoresSafeArea(edges: .top) |
|
| 252 |
- ) |
|
| 253 |
- .overlay(alignment: .bottom) {
|
|
| 254 |
- Rectangle() |
|
| 255 |
- .fill(Color.secondary.opacity(0.12)) |
|
| 256 |
- .frame(height: 1) |
|
| 257 |
- } |
|
| 258 |
- } |
|
| 259 |
- |
|
| 260 | 190 |
private func portraitContent( |
| 261 | 191 |
size: CGSize, |
| 262 | 192 |
tabBarStyle: TabBarStyle, |
@@ -684,9 +614,6 @@ struct MeterView: View {
|
||
| 684 | 614 |
@ViewBuilder |
| 685 | 615 |
private func offlineBody(summary: AppData.MeterSummary) -> some View {
|
| 686 | 616 |
VStack(spacing: 0) {
|
| 687 |
- if Self.isTrueMacApp {
|
|
| 688 |
- offlineMacHeader(name: summary.displayName) |
|
| 689 |
- } |
|
| 690 | 617 |
offlineTabBar(tint: summary.tint) |
| 691 | 618 |
offlineTabContent(summary: summary) |
| 692 | 619 |
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) |
@@ -695,12 +622,8 @@ struct MeterView: View {
|
||
| 695 | 622 |
.animation(.easeInOut(duration: 0.22), value: selectedOfflineTab) |
| 696 | 623 |
} |
| 697 | 624 |
.background(offlineBackground(tint: summary.tint)) |
| 698 |
- #if !targetEnvironment(macCatalyst) |
|
| 699 |
- .navigationBarHidden(Self.isTrueMacApp) |
|
| 700 |
- #else |
|
| 701 |
- .navigationBarHidden(false) |
|
| 702 |
- #endif |
|
| 703 |
- .navigationBarTitle(summary.displayName, displayMode: .inline) |
|
| 625 |
+ .navigationTitle(summary.displayName) |
|
| 626 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 704 | 627 |
.onAppear {
|
| 705 | 628 |
offlineName = summary.displayName |
| 706 | 629 |
offlineTemperatureUnit = appData.temperatureUnitPreference(for: summary.macAddress) |
@@ -873,34 +796,6 @@ struct MeterView: View {
|
||
| 873 | 796 |
.meterCard(tint: tint, fillOpacity: 0.18, strokeOpacity: 0.24) |
| 874 | 797 |
} |
| 875 | 798 |
|
| 876 |
- private func offlineMacHeader(name: String) -> some View {
|
|
| 877 |
- HStack(spacing: 12) {
|
|
| 878 |
- Button { dismiss() } label: {
|
|
| 879 |
- HStack(spacing: 4) {
|
|
| 880 |
- Image(systemName: "chevron.left") |
|
| 881 |
- .font(.body.weight(.semibold)) |
|
| 882 |
- Text("USB Meters")
|
|
| 883 |
- } |
|
| 884 |
- .foregroundColor(.accentColor) |
|
| 885 |
- } |
|
| 886 |
- .buttonStyle(.plain) |
|
| 887 |
- Text(name).font(.headline).lineLimit(1) |
|
| 888 |
- Spacer() |
|
| 889 |
- } |
|
| 890 |
- .padding(.horizontal, 16) |
|
| 891 |
- .padding(.vertical, 10) |
|
| 892 |
- .background( |
|
| 893 |
- Rectangle() |
|
| 894 |
- .fill(.ultraThinMaterial) |
|
| 895 |
- .ignoresSafeArea(edges: .top) |
|
| 896 |
- ) |
|
| 897 |
- .overlay(alignment: .bottom) {
|
|
| 898 |
- Rectangle() |
|
| 899 |
- .fill(Color.secondary.opacity(0.12)) |
|
| 900 |
- .frame(height: 1) |
|
| 901 |
- } |
|
| 902 |
- } |
|
| 903 |
- |
|
| 904 | 799 |
private func offlineStatusHeader(summary: AppData.MeterSummary) -> some View {
|
| 905 | 800 |
HStack(spacing: 12) {
|
| 906 | 801 |
Image(systemName: "sensor.tag.radiowaves.forward.fill") |
@@ -954,42 +849,3 @@ private struct MeterTabBarHeightPreferenceKey: PreferenceKey {
|
||
| 954 | 849 |
} |
| 955 | 850 |
} |
| 956 | 851 |
|
| 957 |
-// MARK: - Conditional navigation bar modifier (skipped on Designed-for-iPad / Mac) |
|
| 958 |
- |
|
| 959 |
-private struct IOSOnlyNavBar: ViewModifier {
|
|
| 960 |
- let apply: Bool |
|
| 961 |
- let title: String |
|
| 962 |
- let showRSSI: Bool |
|
| 963 |
- let rssi: Int |
|
| 964 |
- let meter: Meter |
|
| 965 |
- |
|
| 966 |
- @ViewBuilder |
|
| 967 |
- func body(content: Content) -> some View {
|
|
| 968 |
- if apply {
|
|
| 969 |
- content |
|
| 970 |
- .navigationBarTitle(title, displayMode: .inline) |
|
| 971 |
- .toolbar {
|
|
| 972 |
- ToolbarItemGroup(placement: .navigationBarTrailing) {
|
|
| 973 |
- MeterConnectionToolbarButton( |
|
| 974 |
- operationalState: meter.operationalState, |
|
| 975 |
- showsTitle: false, |
|
| 976 |
- connectAction: { meter.connect() },
|
|
| 977 |
- disconnectAction: { meter.disconnect() }
|
|
| 978 |
- ) |
|
| 979 |
- .font(.body.weight(.semibold)) |
|
| 980 |
- if showRSSI {
|
|
| 981 |
- RSSIView(RSSI: rssi) |
|
| 982 |
- .frame(width: 18, height: 18) |
|
| 983 |
- } |
|
| 984 |
- } |
|
| 985 |
- } |
|
| 986 |
- #if targetEnvironment(macCatalyst) |
|
| 987 |
- .toolbar {
|
|
| 988 |
- ToolbarItemGroup(placement: .primaryAction) {}
|
|
| 989 |
- } |
|
| 990 |
- #endif |
|
| 991 |
- } else {
|
|
| 992 |
- content |
|
| 993 |
- } |
|
| 994 |
- } |
|
| 995 |
-} |
|
@@ -53,6 +53,7 @@ struct ChargerStandbyPowerWizardView: View {
|
||
| 53 | 53 |
.ignoresSafeArea() |
| 54 | 54 |
) |
| 55 | 55 |
.navigationTitle(navigationTitleText) |
| 56 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 56 | 57 |
.sheet(isPresented: $chargerLibraryVisibility) {
|
| 57 | 58 |
ChargedDeviceLibrarySheetView( |
| 58 | 59 |
meterMACAddress: selectedMeterSummary?.macAddress ?? "", |
@@ -699,6 +700,7 @@ struct ChargerStandbyPowerMeasurementsView: View {
|
||
| 699 | 700 |
Text("This charger is no longer available.")
|
| 700 | 701 |
.foregroundColor(.secondary) |
| 701 | 702 |
.navigationTitle("Saved Measurements")
|
| 703 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 702 | 704 |
} |
| 703 | 705 |
} |
| 704 | 706 |
} |
@@ -752,6 +754,7 @@ struct ChargerStandbyPowerMeasurementsView: View {
|
||
| 752 | 754 |
} |
| 753 | 755 |
.environment(\.editMode, $editMode) |
| 754 | 756 |
.navigationTitle("Saved Measurements")
|
| 757 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 755 | 758 |
.toolbar {
|
| 756 | 759 |
ToolbarItem(placement: .primaryAction) {
|
| 757 | 760 |
Button(editMode.isEditing ? "Done" : "Select") {
|
@@ -53,6 +53,7 @@ struct MeterMappingDebugView: View {
|
||
| 53 | 53 |
} |
| 54 | 54 |
.listStyle(.insetGrouped) |
| 55 | 55 |
.navigationTitle("Meter Sync Debug")
|
| 56 |
+ .navigationBarTitleDisplayMode(.inline) |
|
| 56 | 57 |
.onAppear(perform: reload) |
| 57 | 58 |
.onReceive(changePublisher) { _ in reload() }
|
| 58 | 59 |
.toolbar {
|