diff --git a/OmnipodKit/PumpManagerUI/ViewControllers/OmniUICoordinator.swift b/OmnipodKit/PumpManagerUI/ViewControllers/OmniUICoordinator.swift index 2f7b30d..a42499e 100644 --- a/OmnipodKit/PumpManagerUI/ViewControllers/OmniUICoordinator.swift +++ b/OmnipodKit/PumpManagerUI/ViewControllers/OmniUICoordinator.swift @@ -223,7 +223,7 @@ class OmniUICoordinator: UINavigationController, PumpManagerOnboarding, Completi self?.setupCanceled() } let controller = hostingController(rootView: view) - controller.navigationItem.title = pumpManager.localizedTitle + controller.navigationItem.title = LocalizedString("RileyLink Setup", comment: "Navigation title for RileyLinkSetupView") return controller case .deactivate: diff --git a/OmnipodKit/PumpManagerUI/Views/AttachPodView.swift b/OmnipodKit/PumpManagerUI/Views/AttachPodView.swift index ae0c9af..fc40690 100644 --- a/OmnipodKit/PumpManagerUI/Views/AttachPodView.swift +++ b/OmnipodKit/PumpManagerUI/Views/AttachPodView.swift @@ -57,7 +57,6 @@ struct AttachPodView: View { .zIndex(1) } .alert(item: $activeModal, content: self.alert(for:)) - .navigationTitle(LocalizedString("Attach Pod", comment: "navigation bar title attach pod")) .navigationBarTitleDisplayMode(.automatic) .navigationBarItems(trailing: cancelButton) .navigationBarBackButtonHidden(true) diff --git a/OmnipodKit/PumpManagerUI/Views/BeepPreferenceSelectionView.swift b/OmnipodKit/PumpManagerUI/Views/BeepPreferenceSelectionView.swift index 4befb76..56b0f6c 100644 --- a/OmnipodKit/PumpManagerUI/Views/BeepPreferenceSelectionView.swift +++ b/OmnipodKit/PumpManagerUI/Views/BeepPreferenceSelectionView.swift @@ -89,8 +89,7 @@ struct BeepPreferenceSelectionView: View { } .insetGroupedListStyle() - .navigationTitle(LocalizedString("Confidence Reminders", comment: "navigation title for confidence reminders")) - .navigationBarTitleDisplayMode(.inline) + .uikitNavigationTitle(LocalizedString("Confidence Reminders", comment: "navigation title for confidence reminders"), displayMode: .inline) .alert(isPresented: $alertIsPresented, content: { alert(error: error) }) } diff --git a/OmnipodKit/PumpManagerUI/Views/CheckInsertedCannulaView.swift b/OmnipodKit/PumpManagerUI/Views/CheckInsertedCannulaView.swift index 7c07243..f8e320b 100644 --- a/OmnipodKit/PumpManagerUI/Views/CheckInsertedCannulaView.swift +++ b/OmnipodKit/PumpManagerUI/Views/CheckInsertedCannulaView.swift @@ -74,7 +74,6 @@ struct CheckInsertedCannulaView: View { } .animation(.default, value: flashlightOn) .alert(isPresented: $cancelModalIsPresented) { cancelPairingModal } - .navigationTitle(LocalizedString("Check Cannula", comment: "navigation title for Check Cannula")) .navigationBarTitleDisplayMode(.automatic) .navigationBarItems(trailing: cancelButton) .navigationBarBackButtonHidden(true) diff --git a/OmnipodKit/PumpManagerUI/Views/DeactivatePodView.swift b/OmnipodKit/PumpManagerUI/Views/DeactivatePodView.swift index 1724dfa..7b08f02 100644 --- a/OmnipodKit/PumpManagerUI/Views/DeactivatePodView.swift +++ b/OmnipodKit/PumpManagerUI/Views/DeactivatePodView.swift @@ -72,7 +72,6 @@ struct DeactivatePodView: View { .padding() } .alert(isPresented: $removePodModalIsPresented) { removePodModal } - .navigationTitle(LocalizedString("Deactivate Pod", comment: "navigation title for Deactivate Pod")) .navigationBarTitleDisplayMode(.automatic) .navigationBarBackButtonHidden(true) .navigationBarItems(trailing: diff --git a/OmnipodKit/PumpManagerUI/Views/DeliveryUncertaintyRecoveryView.swift b/OmnipodKit/PumpManagerUI/Views/DeliveryUncertaintyRecoveryView.swift index f7fea89..97fb7d3 100644 --- a/OmnipodKit/PumpManagerUI/Views/DeliveryUncertaintyRecoveryView.swift +++ b/OmnipodKit/PumpManagerUI/Views/DeliveryUncertaintyRecoveryView.swift @@ -44,7 +44,7 @@ struct DeliveryUncertaintyRecoveryView: View { } } } - .navigationBarTitle(Text(LocalizedString("Unable to Reach Pod", comment: "Title of delivery uncertainty recovery page")), displayMode: .large) + .navigationBarTitleDisplayMode(.large) .navigationBarItems(leading: backButton) } diff --git a/OmnipodKit/PumpManagerUI/Views/ExpirationReminderSetupView.swift b/OmnipodKit/PumpManagerUI/Views/ExpirationReminderSetupView.swift index 70de0fa..835c4e8 100644 --- a/OmnipodKit/PumpManagerUI/Views/ExpirationReminderSetupView.swift +++ b/OmnipodKit/PumpManagerUI/Views/ExpirationReminderSetupView.swift @@ -40,7 +40,6 @@ struct ExpirationReminderSetupView: View { } .padding() } - .navigationTitle(LocalizedString("Expiration Reminder", comment: "navigation title for Expiration Reminder")) .navigationBarTitleDisplayMode(.automatic) .navigationBarHidden(false) .toolbar { diff --git a/OmnipodKit/PumpManagerUI/Views/InsertCannulaView.swift b/OmnipodKit/PumpManagerUI/Views/InsertCannulaView.swift index f52fca6..06b8635 100644 --- a/OmnipodKit/PumpManagerUI/Views/InsertCannulaView.swift +++ b/OmnipodKit/PumpManagerUI/Views/InsertCannulaView.swift @@ -78,7 +78,6 @@ struct InsertCannulaView: View { .padding() } .alert(isPresented: $cancelModalIsPresented) { cancelPairingModal } - .navigationTitle(LocalizedString("Insert Cannula", comment: "navigation bar title for insert cannula")) .navigationBarTitleDisplayMode(.automatic) .navigationBarBackButtonHidden(true) .navigationBarItems(trailing: cancelButton) diff --git a/OmnipodKit/PumpManagerUI/Views/LowReservoirView.swift b/OmnipodKit/PumpManagerUI/Views/LowReservoirView.swift index caeac3e..ff2757c 100644 --- a/OmnipodKit/PumpManagerUI/Views/LowReservoirView.swift +++ b/OmnipodKit/PumpManagerUI/Views/LowReservoirView.swift @@ -120,7 +120,6 @@ struct LowReservoirView: View { } } } - .navigationTitle(title) .navigationBarTitleDisplayMode(.automatic) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { diff --git a/OmnipodKit/PumpManagerUI/Views/NotificationSettingsView.swift b/OmnipodKit/PumpManagerUI/Views/NotificationSettingsView.swift index f339f9e..b3fc530 100644 --- a/OmnipodKit/PumpManagerUI/Views/NotificationSettingsView.swift +++ b/OmnipodKit/PumpManagerUI/Views/NotificationSettingsView.swift @@ -106,7 +106,7 @@ struct NotificationSettingsView: View { comment: "Description text for Critical Alerts section") ) } - .navigationTitle( + .uikitNavigationTitle( LocalizedString("Notification Settings", comment: "navigation title for notification settings") ) } diff --git a/OmnipodKit/PumpManagerUI/Views/OmniSettingsView.swift b/OmnipodKit/PumpManagerUI/Views/OmniSettingsView.swift index 7ccc3b3..fd25a5c 100644 --- a/OmnipodKit/PumpManagerUI/Views/OmniSettingsView.swift +++ b/OmnipodKit/PumpManagerUI/Views/OmniSettingsView.swift @@ -550,7 +550,8 @@ struct OmniSettingsView: View { } } - NavigationLink(destination: InsulinTypeSetting(initialValue: viewModel.insulinType, supportedInsulinTypes: supportedInsulinTypes, allowUnsetInsulinType: false, didChange: viewModel.didChangeInsulinType)) { + NavigationLink(destination: InsulinTypeSetting(initialValue: viewModel.insulinType, supportedInsulinTypes: supportedInsulinTypes, allowUnsetInsulinType: false, didChange: viewModel.didChangeInsulinType) + .uikitNavigationTitle(LocalizedString("Insulin Type", comment: "navigation title for insulin type"), displayMode: .inline)) { HStack { FrameworkLocalText("Insulin Type", comment: "Text for insulin type navigation link") .foregroundColor(Color.primary) diff --git a/OmnipodKit/PumpManagerUI/Views/PairPodView.swift b/OmnipodKit/PumpManagerUI/Views/PairPodView.swift index 9082d65..0e6a176 100644 --- a/OmnipodKit/PumpManagerUI/Views/PairPodView.swift +++ b/OmnipodKit/PumpManagerUI/Views/PairPodView.swift @@ -109,7 +109,6 @@ struct PairPodView: View { } .alert(isPresented: $cancelModalIsPresented) { cancelPairingModal } - .navigationTitle(String(format: LocalizedString("Pair %1$@ Pod", comment: "Title for pod pairing screen (1: pod type brief name)"), self.viewModel.podType.briefName)) .navigationBarTitleDisplayMode(.automatic) .navigationBarBackButtonHidden(self.viewModel.backButtonHidden) .navigationBarItems(trailing: self.viewModel.state.navBarVisible ? cancelButton : nil) diff --git a/OmnipodKit/PumpManagerUI/Views/PlayTestBeepsView.swift b/OmnipodKit/PumpManagerUI/Views/PlayTestBeepsView.swift index 6f1d115..75e4ca6 100644 --- a/OmnipodKit/PumpManagerUI/Views/PlayTestBeepsView.swift +++ b/OmnipodKit/PumpManagerUI/Views/PlayTestBeepsView.swift @@ -49,8 +49,7 @@ struct PlayTestBeepsView: View { .background(Color(UIColor.secondarySystemGroupedBackground).shadow(radius: 5)) } .insetGroupedListStyle() - .navigationTitle(title) - .navigationBarTitleDisplayMode(.inline) + .uikitNavigationTitle(title, displayMode: .inline) .alert(isPresented: $alertIsPresented, content: { alert(error: error) }) .task { await playTestBeepsAndHandleError() diff --git a/OmnipodKit/PumpManagerUI/Views/PodDetailsView.swift b/OmnipodKit/PumpManagerUI/Views/PodDetailsView.swift index bf9a8fa..67d79f5 100644 --- a/OmnipodKit/PumpManagerUI/Views/PodDetailsView.swift +++ b/OmnipodKit/PumpManagerUI/Views/PodDetailsView.swift @@ -151,8 +151,7 @@ struct PodDetailsView: View { } } } - .navigationTitle(title) - .navigationBarTitleDisplayMode(.automatic) + .uikitNavigationTitle(title) } } diff --git a/OmnipodKit/PumpManagerUI/Views/PodDiagnosticsView.swift b/OmnipodKit/PumpManagerUI/Views/PodDiagnosticsView.swift index 97a9e71..a2b3729 100644 --- a/OmnipodKit/PumpManagerUI/Views/PodDiagnosticsView.swift +++ b/OmnipodKit/PumpManagerUI/Views/PodDiagnosticsView.swift @@ -99,6 +99,6 @@ struct PodDiagnosticsView: View { } .insetGroupedListStyle() - .navigationTitle(title) + .uikitNavigationTitle(title) } } diff --git a/OmnipodKit/PumpManagerUI/Views/PodKeepAliveView.swift b/OmnipodKit/PumpManagerUI/Views/PodKeepAliveView.swift index 80f6b2d..525f062 100644 --- a/OmnipodKit/PumpManagerUI/Views/PodKeepAliveView.swift +++ b/OmnipodKit/PumpManagerUI/Views/PodKeepAliveView.swift @@ -42,7 +42,7 @@ struct PodKeepAliveView: View { self.forceRefresh.toggle() } .insetGroupedListStyle() - .navigationBarTitle(Text(title), displayMode: .automatic) + .uikitNavigationTitle(title) } // MARK: - Subviews / Computed Properties diff --git a/OmnipodKit/PumpManagerUI/Views/PumpManagerDetailsView.swift b/OmnipodKit/PumpManagerUI/Views/PumpManagerDetailsView.swift index 5c08066..6bc8f1f 100644 --- a/OmnipodKit/PumpManagerUI/Views/PumpManagerDetailsView.swift +++ b/OmnipodKit/PumpManagerUI/Views/PumpManagerDetailsView.swift @@ -63,8 +63,7 @@ struct PumpManagerDetailsView: View { .background(Color(UIColor.secondarySystemGroupedBackground).shadow(radius: 5)) } .insetGroupedListStyle() - .navigationTitle(title) - .navigationBarTitleDisplayMode(.inline) + .uikitNavigationTitle(title, displayMode: .inline) .task { self.displayString = getPumpManagerDetails() } diff --git a/OmnipodKit/PumpManagerUI/Views/ReadPodInfoView.swift b/OmnipodKit/PumpManagerUI/Views/ReadPodInfoView.swift index 2995bfb..49d216c 100644 --- a/OmnipodKit/PumpManagerUI/Views/ReadPodInfoView.swift +++ b/OmnipodKit/PumpManagerUI/Views/ReadPodInfoView.swift @@ -66,8 +66,7 @@ struct ReadPodInfoView: View { .background(Color(UIColor.secondarySystemGroupedBackground).shadow(radius: 5)) } .insetGroupedListStyle() - .navigationTitle(title) - .navigationBarTitleDisplayMode(.inline) + .uikitNavigationTitle(title, displayMode: .inline) .alert(isPresented: $alertIsPresented, content: { alert(error: error) }) .task { await attemptAction() diff --git a/OmnipodKit/PumpManagerUI/Views/ReadPodStatusView.swift b/OmnipodKit/PumpManagerUI/Views/ReadPodStatusView.swift index f034b5c..3682870 100644 --- a/OmnipodKit/PumpManagerUI/Views/ReadPodStatusView.swift +++ b/OmnipodKit/PumpManagerUI/Views/ReadPodStatusView.swift @@ -62,8 +62,7 @@ struct ReadPodStatusView: View { .background(Color(UIColor.secondarySystemGroupedBackground).shadow(radius: 5)) } .insetGroupedListStyle() - .navigationTitle(title) - .navigationBarTitleDisplayMode(.inline) + .uikitNavigationTitle(title, displayMode: .inline) .alert(isPresented: $alertIsPresented, content: { alert(error: error) }) .task { await fetchDetailedStatus() diff --git a/OmnipodKit/PumpManagerUI/Views/RileyLinkSetupView.swift b/OmnipodKit/PumpManagerUI/Views/RileyLinkSetupView.swift index 0b65e2d..9c094cf 100644 --- a/OmnipodKit/PumpManagerUI/Views/RileyLinkSetupView.swift +++ b/OmnipodKit/PumpManagerUI/Views/RileyLinkSetupView.swift @@ -61,7 +61,6 @@ struct RileyLinkSetupView: View { .padding([.bottom, .horizontal]) } - .navigationTitle(LocalizedString("RileyLink Setup", comment: "Navigation title for RileyLinkSetupView")) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button(LocalizedString("Cancel", comment: "Cancel button title"), action: { diff --git a/OmnipodKit/PumpManagerUI/Views/SetupCompleteView.swift b/OmnipodKit/PumpManagerUI/Views/SetupCompleteView.swift index 14577d7..cd92cd9 100644 --- a/OmnipodKit/PumpManagerUI/Views/SetupCompleteView.swift +++ b/OmnipodKit/PumpManagerUI/Views/SetupCompleteView.swift @@ -85,7 +85,6 @@ struct SetupCompleteView: View { .background(Color(UIColor.systemBackground)) .zIndex(1) } - .navigationTitle(LocalizedString("Setup Complete", comment: "Title of SetupCompleteView")) .navigationBarTitleDisplayMode(.automatic) } diff --git a/OmnipodKit/PumpManagerUI/Views/SilencePodSelectionView.swift b/OmnipodKit/PumpManagerUI/Views/SilencePodSelectionView.swift index f998822..df563ac 100644 --- a/OmnipodKit/PumpManagerUI/Views/SilencePodSelectionView.swift +++ b/OmnipodKit/PumpManagerUI/Views/SilencePodSelectionView.swift @@ -114,8 +114,7 @@ struct SilencePodSelectionView: View { } } .insetGroupedListStyle() - .navigationTitle(LocalizedString("Silence Pod", comment: "navigation title for Silence Pod")) - .navigationBarTitleDisplayMode(.inline) + .uikitNavigationTitle(LocalizedString("Silence Pod", comment: "navigation title for Silence Pod"), displayMode: .inline) .alert(isPresented: $alertIsPresented, content: { alert(error: error) }) } diff --git a/OmnipodKit/PumpManagerUI/Views/UncertaintyRecoveredView.swift b/OmnipodKit/PumpManagerUI/Views/UncertaintyRecoveredView.swift index 981a1f2..3443424 100644 --- a/OmnipodKit/PumpManagerUI/Views/UncertaintyRecoveredView.swift +++ b/OmnipodKit/PumpManagerUI/Views/UncertaintyRecoveredView.swift @@ -31,7 +31,6 @@ struct UncertaintyRecoveredView: View { } } } - .navigationTitle(LocalizedString("Comms Recovered", comment: "navigation title for comms recovered")) .navigationBarTitleDisplayMode(.large) .navigationBarBackButtonHidden(true) } diff --git a/OmnipodKit/PumpManagerUI/Views/View+UIKitNavigationTitle.swift b/OmnipodKit/PumpManagerUI/Views/View+UIKitNavigationTitle.swift new file mode 100644 index 0000000..c0a4333 --- /dev/null +++ b/OmnipodKit/PumpManagerUI/Views/View+UIKitNavigationTitle.swift @@ -0,0 +1,91 @@ +// +// View+UIKitNavigationTitle.swift +// OmnipodKit +// +// Copyright © 2026 LoopKit Authors. All rights reserved. +// + +import SwiftUI +import UIKit + +extension View { + /// Sets the navigation bar title (and large-title display mode) for a SwiftUI screen pushed + /// via `NavigationLink` while the flow is hosted inside a UIKit `UINavigationController` + /// (as the Omnipod settings screens are, via `OmniUICoordinator`). + func uikitNavigationTitle( + _ title: String, + displayMode: NavigationBarItem.TitleDisplayMode = .automatic + ) -> some View { + self + .navigationTitle(title) + .navigationBarTitleDisplayMode(displayMode) + .background(NavigationItemTitleSetter(title: title, largeTitleDisplayMode: displayMode.uiKitLargeTitleDisplayMode)) + } +} + +private extension NavigationBarItem.TitleDisplayMode { + var uiKitLargeTitleDisplayMode: UINavigationItem.LargeTitleDisplayMode { + switch self { + case .inline: return .never + case .large: return .always + case .automatic: return .automatic + @unknown default: return .automatic + } + } +} + +/// Sets `navigationItem.title` and `largeTitleDisplayMode` on the enclosing navigation +/// controller's top view controller. See `View.uikitNavigationTitle(_:displayMode:)`. +private struct NavigationItemTitleSetter: UIViewControllerRepresentable { + let title: String + let largeTitleDisplayMode: UINavigationItem.LargeTitleDisplayMode + + func makeUIViewController(context: Context) -> TitleProxyViewController { + TitleProxyViewController(title: title, largeTitleDisplayMode: largeTitleDisplayMode) + } + + func updateUIViewController(_ uiViewController: TitleProxyViewController, context: Context) { + uiViewController.proxyTitle = title + uiViewController.largeTitleDisplayMode = largeTitleDisplayMode + } + + final class TitleProxyViewController: UIViewController { + var proxyTitle: String { + didSet { applyTitle() } + } + + var largeTitleDisplayMode: UINavigationItem.LargeTitleDisplayMode { + didSet { applyTitle() } + } + + init(title: String, largeTitleDisplayMode: UINavigationItem.LargeTitleDisplayMode) { + self.proxyTitle = title + self.largeTitleDisplayMode = largeTitleDisplayMode + super.init(nibName: nil, bundle: nil) + view.isHidden = true + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + applyTitle() + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + applyTitle() + } + + private func applyTitle() { + // The pushed SwiftUI screen is the navigation controller's top view controller; + // set the title and display mode the navigation bar actually uses. + guard let host = navigationController?.topViewController else { return } + host.navigationItem.title = proxyTitle + host.navigationItem.largeTitleDisplayMode = largeTitleDisplayMode + } + } +}