Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions MinimedKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@
C1E34B3129C7ABF3009A50A5 /* UseMySentrySelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E34B1929C7ABF3009A50A5 /* UseMySentrySelectionView.swift */; };
C1E34B3229C7ABF3009A50A5 /* DataSourceSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E34B1A29C7ABF3009A50A5 /* DataSourceSelectionView.swift */; };
C1E34B3329C7ABF3009A50A5 /* BatteryTypeSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E34B1B29C7ABF3009A50A5 /* BatteryTypeSelectionView.swift */; };
B65C7B5E69AAD31D20C66C6A /* View+UIKitNavigationTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4918419DB490FB27EA2EC8FF /* View+UIKitNavigationTitle.swift */; };
C1E34B3429C7ABF3009A50A5 /* ReservoirHUDView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C1E34B1C29C7ABF3009A50A5 /* ReservoirHUDView.xib */; };
C1E34B3529C7ABF3009A50A5 /* MinimedPumpSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E34B1D29C7ABF3009A50A5 /* MinimedPumpSettingsView.swift */; };
C1E34B3629C7ABF3009A50A5 /* ReservoirHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E34B1E29C7ABF3009A50A5 /* ReservoirHUDView.swift */; };
Expand Down Expand Up @@ -614,6 +615,7 @@
C1E34B1929C7ABF3009A50A5 /* UseMySentrySelectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UseMySentrySelectionView.swift; sourceTree = "<group>"; };
C1E34B1A29C7ABF3009A50A5 /* DataSourceSelectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataSourceSelectionView.swift; sourceTree = "<group>"; };
C1E34B1B29C7ABF3009A50A5 /* BatteryTypeSelectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatteryTypeSelectionView.swift; sourceTree = "<group>"; };
4918419DB490FB27EA2EC8FF /* View+UIKitNavigationTitle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+UIKitNavigationTitle.swift"; sourceTree = "<group>"; };
C1E34B1C29C7ABF3009A50A5 /* ReservoirHUDView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ReservoirHUDView.xib; sourceTree = "<group>"; };
C1E34B1D29C7ABF3009A50A5 /* MinimedPumpSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimedPumpSettingsView.swift; sourceTree = "<group>"; };
C1E34B1E29C7ABF3009A50A5 /* ReservoirHUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReservoirHUDView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1148,6 +1150,7 @@
C1E34B1929C7ABF3009A50A5 /* UseMySentrySelectionView.swift */,
C1E34B1A29C7ABF3009A50A5 /* DataSourceSelectionView.swift */,
C1E34B1B29C7ABF3009A50A5 /* BatteryTypeSelectionView.swift */,
4918419DB490FB27EA2EC8FF /* View+UIKitNavigationTitle.swift */,
C1E34B1C29C7ABF3009A50A5 /* ReservoirHUDView.xib */,
C1E34B1D29C7ABF3009A50A5 /* MinimedPumpSettingsView.swift */,
C1E34B1E29C7ABF3009A50A5 /* ReservoirHUDView.swift */,
Expand Down Expand Up @@ -1681,6 +1684,7 @@
C1E34B2F29C7ABF3009A50A5 /* CommandResponseViewController.swift in Sources */,
C1E34B3529C7ABF3009A50A5 /* MinimedPumpSettingsView.swift in Sources */,
C1E34B3329C7ABF3009A50A5 /* BatteryTypeSelectionView.swift in Sources */,
B65C7B5E69AAD31D20C66C6A /* View+UIKitNavigationTitle.swift in Sources */,
C1E34B2929C7ABF3009A50A5 /* MinimedPumpSentrySetupViewController.swift in Sources */,
C1E34B9229C7B46C009A50A5 /* TimeZone.swift in Sources */,
C1E34B8E29C7B34F009A50A5 /* NibLoadable.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion MinimedKitUI/Views/BatteryTypeSelectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ struct BatteryTypeSelectionView: View {
}
}
.insetGroupedListStyle()
.navigationTitle(LocalizedString("Pump Battery Type", comment: "navigation title for pump battery type selection"))
.uikitNavigationTitle(LocalizedString("Pump Battery Type", comment: "navigation title for pump battery type selection"))
}
}
2 changes: 1 addition & 1 deletion MinimedKitUI/Views/DataSourceSelectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ struct DataSourceSelectionView: View {
}
}
.insetGroupedListStyle()
.navigationTitle(LocalizedString("Preferred Data Source", comment: "navigation title for pump battery type selection"))
.uikitNavigationTitle(LocalizedString("Preferred Data Source", comment: "navigation title for pump battery type selection"))
}
}
3 changes: 2 additions & 1 deletion MinimedKitUI/Views/MinimedPumpSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ struct MinimedPumpSettingsView: View {

Section(header: Text(LocalizedString("Configuration", comment: "The title of the configuration section in MinimedPumpManager settings")))
{
NavigationLink(destination: InsulinTypeSetting(initialValue: viewModel.pumpManager.state.insulinType, supportedInsulinTypes: supportedInsulinTypes, allowUnsetInsulinType: false, didChange: viewModel.didChangeInsulinType)) {
NavigationLink(destination: InsulinTypeSetting(initialValue: viewModel.pumpManager.state.insulinType, supportedInsulinTypes: supportedInsulinTypes, allowUnsetInsulinType: false, didChange: viewModel.didChangeInsulinType)
.uikitNavigationTitle(LocalizedString("Insulin Type", comment: "Text for confidence reminders navigation link"))) {
HStack {
Text(LocalizedString("Insulin Type", comment: "Text for confidence reminders navigation link")).foregroundColor(Color.primary)
if let currentTitle = viewModel.pumpManager.state.insulinType?.brandName {
Expand Down
2 changes: 1 addition & 1 deletion MinimedKitUI/Views/UseMySentrySelectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ struct UseMySentrySelectionView: View {
}
}
.insetGroupedListStyle()
.navigationTitle(LocalizedString("Use MySentry", comment: "navigation title for pump battery type selection"))
.uikitNavigationTitle(LocalizedString("Use MySentry", comment: "navigation title for pump battery type selection"))
}
}
91 changes: 91 additions & 0 deletions MinimedKitUI/Views/View+UIKitNavigationTitle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// View+UIKitNavigationTitle.swift
// MinimedKitUI
//
// 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 Medtronic settings screens are, via `MinimedUICoordinator`).
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
}
}
}