فهرست منبع

More readable reason

Ivan Valkou 4 سال پیش
والد
کامیت
4f49cedc9a

+ 4 - 0
FreeAPS.xcodeproj/project.pbxproj

@@ -166,6 +166,7 @@
 		38D0B3D925EC07C400CB6E88 /* CarbsEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38D0B3D825EC07C400CB6E88 /* CarbsEntry.swift */; };
 		38DAB280260CBB7F00F74C1A /* PumpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38DAB27F260CBB7F00F74C1A /* PumpView.swift */; };
 		38DAB28A260D349500F74C1A /* FetchGlucoseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38DAB289260D349500F74C1A /* FetchGlucoseManager.swift */; };
+		38DF1786276A73D400B3528F /* TagCloudView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38DF1785276A73D400B3528F /* TagCloudView.swift */; };
 		38E4451E274DB04600EC9A94 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E4451D274DB04600EC9A94 /* AppDelegate.swift */; };
 		38E44522274E3DDC00EC9A94 /* NetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E44521274E3DDC00EC9A94 /* NetworkReachabilityManager.swift */; };
 		38E44528274E401C00EC9A94 /* Protected.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E44527274E401C00EC9A94 /* Protected.swift */; };
@@ -565,6 +566,7 @@
 		38D0B3D825EC07C400CB6E88 /* CarbsEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbsEntry.swift; sourceTree = "<group>"; };
 		38DAB27F260CBB7F00F74C1A /* PumpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpView.swift; sourceTree = "<group>"; };
 		38DAB289260D349500F74C1A /* FetchGlucoseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchGlucoseManager.swift; sourceTree = "<group>"; };
+		38DF1785276A73D400B3528F /* TagCloudView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagCloudView.swift; sourceTree = "<group>"; };
 		38E4451D274DB04600EC9A94 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		38E44521274E3DDC00EC9A94 /* NetworkReachabilityManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkReachabilityManager.swift; sourceTree = "<group>"; };
 		38E44527274E401C00EC9A94 /* Protected.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Protected.swift; sourceTree = "<group>"; };
@@ -1181,6 +1183,7 @@
 				383420D825FFEB3F002D46C1 /* Popup.swift */,
 				389ECDFD2601061500D86C4F /* View+Snapshot.swift */,
 				38EA05FF262091870064E39B /* BolusProgressViewStyle.swift */,
+				38DF1785276A73D400B3528F /* TagCloudView.swift */,
 			);
 			path = Views;
 			sourceTree = "<group>";
@@ -2065,6 +2068,7 @@
 				3894873A2614928B004DF424 /* DispatchTimer.swift in Sources */,
 				3895E4C625B9E00D00214B37 /* Preferences.swift in Sources */,
 				386A124F271707F000DDC61C /* DexcomSource.swift in Sources */,
+				38DF1786276A73D400B3528F /* TagCloudView.swift in Sources */,
 				38B4F3CD25E5031100E76A18 /* Broadcaster.swift in Sources */,
 				383420D925FFEB3F002D46C1 /* Popup.swift in Sources */,
 				3811DE3025C9D49500A708ED /* HomeStateModel.swift in Sources */,

+ 10 - 0
FreeAPS/Sources/Models/Suggestion.swift

@@ -67,3 +67,13 @@ protocol SuggestionObserver {
 protocol EnactedSuggestionObserver {
     func enactedSuggestionDidUpdate(_ suggestion: Suggestion)
 }
+
+extension Suggestion {
+    var reasonParts: [String] {
+        reason.components(separatedBy: "; ").first?.components(separatedBy: ", ") ?? []
+    }
+
+    var reasonConclusion: String {
+        reason.components(separatedBy: "; ").last ?? ""
+    }
+}

+ 12 - 5
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -325,16 +325,23 @@ extension Home {
             .navigationBarHidden(true)
             .ignoresSafeArea(.keyboard)
             .popup(isPresented: isStatusPopupPresented, alignment: .top, direction: .top) {
-                VStack(alignment: .leading) {
-                    Text(state.statusTitle).foregroundColor(.white)
+                VStack(alignment: .leading, spacing: 4) {
+                    Text(state.statusTitle).font(.headline).foregroundColor(.white)
                         .padding(.bottom, 4)
-                    Text(state.suggestion?.reason ?? "No sugestion found").font(.caption).foregroundColor(.white)
+                    if let suggestion = state.suggestion {
+                        TagCloudView(tags: suggestion.reasonParts).animation(.none, value: false)
+                        Text(suggestion.reasonConclusion.capitalizingFirstLetter()).font(.body).foregroundColor(.white)
+                    } else {
+                        Text("No sugestion found").font(.body).foregroundColor(.white)
+                    }
 
                     if let errorMessage = state.errorMessage, let date = state.errorDate {
-                        Text("Error at \(dateFormatter.string(from: date))").foregroundColor(.white)
+                        Text("Error at \(dateFormatter.string(from: date))")
+                            .foregroundColor(.white)
+                            .font(.headline)
                             .padding(.bottom, 4)
                             .padding(.top, 8)
-                        Text(errorMessage).font(.caption).foregroundColor(.white)
+                        Text(errorMessage).font(.caption).foregroundColor(.loopRed)
                     }
                 }
                 .padding()

+ 84 - 0
FreeAPS/Sources/Views/TagCloudView.swift

@@ -0,0 +1,84 @@
+import SwiftUI
+
+struct TagCloudView: View {
+    var tags: [String]
+
+    @State private var totalHeight
+//          = CGFloat.zero       // << variant for ScrollView/List
+        = CGFloat.infinity // << variant for VStack
+
+    var body: some View {
+        VStack {
+            GeometryReader { geometry in
+                self.generateContent(in: geometry)
+            }
+        }
+//        .frame(height: totalHeight)// << variant for ScrollView/List
+        .frame(maxHeight: totalHeight) // << variant for VStack
+    }
+
+    private func generateContent(in g: GeometryProxy) -> some View {
+        var width = CGFloat.zero
+        var height = CGFloat.zero
+
+        return ZStack(alignment: .topLeading) {
+            ForEach(self.tags, id: \.self) { tag in
+                self.item(for: tag)
+                    .padding([.horizontal, .vertical], 4)
+                    .alignmentGuide(.leading, computeValue: { d in
+                        if abs(width - d.width) > g.size.width
+                        {
+                            width = 0
+                            height -= d.height
+                        }
+                        let result = width
+                        if tag == self.tags.last! {
+                            width = 0 // last item
+                        } else {
+                            width -= d.width
+                        }
+                        return result
+                    })
+                    .alignmentGuide(.top, computeValue: { _ in
+                        let result = height
+                        if tag == self.tags.last! {
+                            height = 0 // last item
+                        }
+                        return result
+                    })
+            }
+        }.background(viewHeightReader($totalHeight))
+    }
+
+    private func item(for text: String) -> some View {
+        Text(text)
+            .padding(.all, 5)
+            .font(.body)
+            .background(Color.insulin)
+            .foregroundColor(Color.white)
+            .cornerRadius(5)
+    }
+
+    private func viewHeightReader(_ binding: Binding<CGFloat>) -> some View {
+        GeometryReader { geometry -> Color in
+            let rect = geometry.frame(in: .local)
+            DispatchQueue.main.async {
+                binding.wrappedValue = rect.size.height
+            }
+            return .clear
+        }
+    }
+}
+
+struct TestTagCloudView: View {
+    var body: some View {
+        VStack {
+            Text("Header").font(.largeTitle)
+            TagCloudView(tags: ["Ninetendo", "XBox", "PlayStation", "PlayStation 2", "PlayStation 3", "PlayStation 4"])
+            Text("Some other text")
+            Divider()
+            Text("Some other cloud")
+            TagCloudView(tags: ["Apple", "Google", "Amazon", "Microsoft", "Oracle", "Facebook"])
+        }
+    }
+}