DismissibleHostingController.swift 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. //
  2. // DismissibleHostingController.swift
  3. // LoopKitUI
  4. //
  5. // Created by Michael Pangburn on 5/7/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import SwiftUI
  9. public struct _DismissibleHostingView<Content: View>: View {
  10. let content: Content
  11. let guidanceColors: GuidanceColors
  12. let carbTintColor: Color
  13. let glucoseTintColor: Color
  14. let insulinTintColor: Color
  15. public var dismiss: () -> Void = {}
  16. public init(
  17. content: Content,
  18. guidanceColors: GuidanceColors,
  19. carbTintColor: Color,
  20. glucoseTintColor: Color,
  21. insulinTintColor: Color
  22. ) {
  23. self.content = content
  24. self.guidanceColors = guidanceColors
  25. self.carbTintColor = carbTintColor
  26. self.glucoseTintColor = glucoseTintColor
  27. self.insulinTintColor = insulinTintColor
  28. }
  29. public var body: some View {
  30. content
  31. .environment(\.dismissAction, dismiss)
  32. .environment(\.guidanceColors, guidanceColors)
  33. .environment(\.carbTintColor, carbTintColor)
  34. .environment(\.glucoseTintColor, glucoseTintColor)
  35. .environment(\.insulinTintColor, insulinTintColor)
  36. }
  37. }
  38. public class DismissibleHostingController<Content: View>: UIHostingController<_DismissibleHostingView<Content>> {
  39. public enum DismissalMode {
  40. case modalDismiss
  41. case pop(to: UIViewController.Type)
  42. }
  43. private var onDisappear: () -> Void = {}
  44. public convenience init (
  45. content: Content,
  46. dismissalMode: DismissalMode = .modalDismiss,
  47. isModalInPresentation: Bool = true,
  48. onDisappear: @escaping () -> Void = {},
  49. colorPalette: LoopUIColorPalette
  50. ) {
  51. self.init(content: content,
  52. dismissalMode: dismissalMode,
  53. isModalInPresentation: isModalInPresentation,
  54. onDisappear: onDisappear,
  55. guidanceColors: colorPalette.guidanceColors,
  56. carbTintColor: colorPalette.carbTintColor,
  57. glucoseTintColor: colorPalette.glucoseTintColor,
  58. insulinTintColor: colorPalette.insulinTintColor)
  59. }
  60. public convenience init(
  61. content: Content,
  62. dismissalMode: DismissalMode = .modalDismiss,
  63. isModalInPresentation: Bool = true,
  64. onDisappear: @escaping () -> Void = {},
  65. guidanceColors: GuidanceColors = GuidanceColors(),
  66. carbTintColor: Color = .green,
  67. glucoseTintColor: Color = Color(.systemTeal),
  68. insulinTintColor: Color = .orange
  69. ) {
  70. let view = _DismissibleHostingView(
  71. content: content,
  72. guidanceColors: guidanceColors,
  73. carbTintColor: carbTintColor,
  74. glucoseTintColor: glucoseTintColor,
  75. insulinTintColor: insulinTintColor
  76. )
  77. // Delay initialization of dismissal closure pushed into SwiftUI Environment until after calling the designated initializer
  78. self.init(rootView: view)
  79. switch dismissalMode {
  80. case .modalDismiss:
  81. self.rootView.dismiss = { [weak self] in self?.dismiss(animated: true) }
  82. case .pop(to: let PredecessorViewController):
  83. self.rootView.dismiss = { [weak self] in
  84. guard
  85. let navigationController = self?.navigationController,
  86. let predecessor = navigationController.viewControllers.last(where: { $0.isKind(of: PredecessorViewController) })
  87. else {
  88. return
  89. }
  90. navigationController.popToViewController(predecessor, animated: true)
  91. }
  92. }
  93. self.onDisappear = onDisappear
  94. self.isModalInPresentation = isModalInPresentation
  95. }
  96. public override func viewWillDisappear(_ animated: Bool) {
  97. super.viewWillDisappear(animated)
  98. onDisappear()
  99. }
  100. }