ReadPodInfoView.swift 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. //
  2. // ReadPodInfoView.swift
  3. // OmniKit
  4. //
  5. // Created by Joe Moran on 11/25/23.
  6. // Copyright © 2023 LoopKit Authors. All rights reserved.
  7. //
  8. import SwiftUI
  9. import LoopKit
  10. import OmniKit
  11. struct ReadPodInfoView: View {
  12. @Environment(\.horizontalSizeClass) var horizontalSizeClass
  13. @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
  14. var title: String // e.g., "Read Pulse Log"
  15. var actionString: String // e.g., "Reading Pulse Log..."
  16. var failedString: String // e.g., "Failed to read pulse log."
  17. var toRun: ((_ completion: @escaping (_ result: Result<String, Error>) -> Void) -> Void)?
  18. @State private var alertIsPresented: Bool = false
  19. @State private var displayString: String = ""
  20. @State private var error: Error? = nil
  21. @State private var executing: Bool = false
  22. @State private var showActivityView: Bool = false
  23. var body: some View {
  24. VStack {
  25. List {
  26. Section {
  27. let myFont = Font
  28. .system(size: 12)
  29. .monospaced()
  30. Text(self.displayString)
  31. .font(myFont)
  32. }
  33. }
  34. .toolbar {
  35. ToolbarItem(placement: .navigationBarTrailing) {
  36. Button(action: {
  37. self.showActivityView = true
  38. }) {
  39. Image(systemName: "square.and.arrow.up")
  40. }
  41. }
  42. }.sheet(isPresented: $showActivityView) {
  43. ActivityView(isPresented: $showActivityView, activityItems: [self.displayString])
  44. }
  45. VStack {
  46. Button(action: {
  47. asyncAction()
  48. }) {
  49. Text(buttonText)
  50. .actionButtonStyle(.primary)
  51. }
  52. .padding()
  53. .disabled(executing)
  54. }
  55. .padding(self.horizontalSizeClass == .regular ? .bottom : [])
  56. .background(Color(UIColor.secondarySystemGroupedBackground).shadow(radius: 5))
  57. }
  58. .insetGroupedListStyle()
  59. .navigationTitle(title)
  60. .navigationBarTitleDisplayMode(.automatic)
  61. .alert(isPresented: $alertIsPresented, content: { alert(error: error) })
  62. .onFirstAppear {
  63. asyncAction()
  64. }
  65. }
  66. private func asyncAction () {
  67. DispatchQueue.global(qos: .utility).async {
  68. executing = true
  69. self.displayString = ""
  70. toRun?() { (result) in
  71. executing = false
  72. switch result {
  73. case .success(let resultString):
  74. self.displayString = resultString
  75. case .failure(let error):
  76. self.displayString = ""
  77. self.error = error
  78. self.alertIsPresented = true
  79. }
  80. }
  81. }
  82. }
  83. private var buttonText: String {
  84. if executing {
  85. return actionString
  86. } else {
  87. return title
  88. }
  89. }
  90. private func alert(error: Error?) -> SwiftUI.Alert {
  91. return SwiftUI.Alert(
  92. title: Text(failedString),
  93. message: Text(error?.localizedDescription ?? "No Error")
  94. )
  95. }
  96. }
  97. struct ReadPodInfoView_Previews: PreviewProvider {
  98. static var previews: some View {
  99. NavigationView {
  100. ReadPodInfoView(
  101. title: "Read Pulse Log",
  102. actionString: "Reading Pulse Log...",
  103. failedString: "Failed to read pulse log"
  104. ) { completion in
  105. let podInfoPulseLogRecent = try! PodInfoPulseLogRecent(encodedData: Data([0x50, 0x03, 0x17,
  106. 0x39, 0x72, 0x58, 0x01, 0x3c, 0x72, 0x43, 0x01, 0x41, 0x72, 0x5a, 0x01, 0x44, 0x71, 0x47, 0x01,
  107. 0x49, 0x51, 0x59, 0x01, 0x4c, 0x51, 0x44, 0x01, 0x51, 0x73, 0x59, 0x01, 0x54, 0x50, 0x43, 0x01,
  108. 0x59, 0x50, 0x5a, 0x81, 0x5c, 0x51, 0x42, 0x81, 0x61, 0x73, 0x59, 0x81, 0x00, 0x75, 0x43, 0x80,
  109. 0x05, 0x70, 0x5a, 0x80, 0x08, 0x50, 0x44, 0x80, 0x0d, 0x50, 0x5b, 0x80, 0x10, 0x75, 0x43, 0x80,
  110. 0x15, 0x72, 0x5e, 0x80, 0x18, 0x73, 0x45, 0x80, 0x1d, 0x72, 0x5b, 0x00, 0x20, 0x70, 0x43, 0x00,
  111. 0x25, 0x50, 0x5c, 0x00, 0x28, 0x50, 0x46, 0x00, 0x2d, 0x50, 0x5a, 0x00, 0x30, 0x75, 0x47, 0x00,
  112. 0x35, 0x72, 0x59, 0x00, 0x38, 0x70, 0x46, 0x00, 0x3d, 0x75, 0x57, 0x00, 0x40, 0x72, 0x43, 0x00,
  113. 0x45, 0x73, 0x55, 0x00, 0x48, 0x73, 0x41, 0x00, 0x4d, 0x70, 0x52, 0x00, 0x50, 0x73, 0x3f, 0x00,
  114. 0x55, 0x74, 0x4d, 0x00, 0x58, 0x72, 0x3d, 0x80, 0x5d, 0x73, 0x4d, 0x80, 0x60, 0x71, 0x3d, 0x80,
  115. 0x01, 0x51, 0x50, 0x80, 0x04, 0x72, 0x3d, 0x80, 0x09, 0x50, 0x4e, 0x80, 0x0c, 0x51, 0x40, 0x80,
  116. 0x11, 0x74, 0x50, 0x80, 0x14, 0x71, 0x40, 0x80, 0x19, 0x50, 0x4d, 0x80, 0x1c, 0x75, 0x3f, 0x00,
  117. 0x21, 0x72, 0x52, 0x00, 0x24, 0x72, 0x40, 0x00, 0x29, 0x71, 0x53, 0x00, 0x2c, 0x50, 0x42, 0x00,
  118. 0x31, 0x51, 0x55, 0x00, 0x34, 0x50, 0x42, 0x00 ]))
  119. let lastPulseNumber = Int(podInfoPulseLogRecent.indexLastEntry)
  120. completion(.success(pulseLogString(pulseLogEntries: podInfoPulseLogRecent.pulseLog, lastPulseNumber: lastPulseNumber)))
  121. }
  122. }
  123. }
  124. }