Browse Source

Merge branch 'dev' into alpha

Ivan Valkou 4 years ago
parent
commit
12df521292
29 changed files with 9363 additions and 35 deletions
  1. 84 0
      FreeAPS.xcodeproj/project.pbxproj
  2. 504 0
      FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings
  3. 504 0
      FreeAPS/Sources/Localizations/Main/ca.lproj/Localizable.strings
  4. 504 0
      FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings
  5. 504 0
      FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings
  6. 504 0
      FreeAPS/Sources/Localizations/Main/el.lproj/Localizable.strings
  7. 504 0
      FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings
  8. 504 0
      FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings
  9. 504 0
      FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings
  10. 504 0
      FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings
  11. 504 0
      FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings
  12. 504 0
      FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings
  13. 504 0
      FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings
  14. 504 0
      FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings
  15. 504 0
      FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings
  16. 504 0
      FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings
  17. 486 0
      FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings
  18. 504 0
      FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings
  19. 504 0
      FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings
  20. 1 1
      FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift
  21. 13 4
      FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift
  22. 4 3
      FreeAPS/Sources/Modules/DataTable/DataTableDataFlow.swift
  23. 7 6
      FreeAPS/Sources/Modules/Home/View/Header/PumpView.swift
  24. 16 7
      FreeAPS/Sources/Modules/Home/View/HomeRootView.swift
  25. 9 1
      FreeAPS/Sources/Modules/PreferencesEditor/PreferencesEditorDataFlow.swift
  26. 148 8
      FreeAPS/Sources/Modules/PreferencesEditor/PreferencesEditorViewModel.swift
  27. 24 2
      FreeAPS/Sources/Modules/PreferencesEditor/View/PreferencesEditorRootView.swift
  28. 2 2
      FreeAPS/Sources/Views/DecimalTextField.swift
  29. 1 1
      README.md

+ 84 - 0
FreeAPS.xcodeproj/project.pbxproj

@@ -12,6 +12,7 @@
 		0D9A5E34A899219C5C4CDFAF /* DataTableViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9455FA2D92E77A6C4AFED8A3 /* DataTableViewModel.swift */; };
 		17A9D0899046B45E87834820 /* CREditorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C8D5F457B5AFF763F8CF3DF /* CREditorProvider.swift */; };
 		19434C14DF3F4816F4E4BF2E /* BolusBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FAEF7B34EEC71B3A7B800C /* BolusBuilder.swift */; };
+		19BE6CBA2674132500624F4A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 19BE6CBC2674132500624F4A /* Localizable.strings */; };
 		1BBB001DAD60F3B8CEA4B1C7 /* ISFEditorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505E09DC17A0C3D0AF4B66FE /* ISFEditorViewModel.swift */; };
 		1D086541F369D339A74893AC /* BasalProfileEditorBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BA56D2DCAB9E0A8AF24D984 /* BasalProfileEditorBuilder.swift */; };
 		1D845DF2E3324130E1D95E67 /* DataTableProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60744C3E9BB3652895C908CC /* DataTableProvider.swift */; };
@@ -314,6 +315,24 @@
 		10CAE3534904CDCA0F367017 /* PumpSettingsEditorBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PumpSettingsEditorBuilder.swift; sourceTree = "<group>"; };
 		111579A6E3AC6BFA79C4DD43 /* NightscoutConfigBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NightscoutConfigBuilder.swift; sourceTree = "<group>"; };
 		12204445D7632AF09264A979 /* PreferencesEditorDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PreferencesEditorDataFlow.swift; sourceTree = "<group>"; };
+		19BE6CBD2674152700624F4A /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CBE2674152D00624F4A /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CBF2674153200624F4A /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
+		19BE6CC02674153800624F4A /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CC12674153C00624F4A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CC22674154300624F4A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CC42674155000624F4A /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CC52674155A00624F4A /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CC62674156100624F4A /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CC72674156600624F4A /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CC82674156E00624F4A /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CC92674157400624F4A /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CCA2674158400624F4A /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CCB2674158900624F4A /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CCC2674158F00624F4A /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CCD2674159600624F4A /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CCE2674159C00624F4A /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
+		19BE6CCF267559A100624F4A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
 		223EC0494F55A91E3EA69EF4 /* BolusViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BolusViewModel.swift; sourceTree = "<group>"; };
 		2AD22C985B79A2F0D2EA3D9D /* PumpConfigRootView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PumpConfigRootView.swift; sourceTree = "<group>"; };
 		2F2A13DF0EDEEEDC4106AA2A /* NightscoutConfigDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NightscoutConfigDataFlow.swift; sourceTree = "<group>"; };
@@ -624,6 +643,22 @@
 			path = View;
 			sourceTree = "<group>";
 		};
+		19BE6CB6267412C200624F4A /* Localizations */ = {
+			isa = PBXGroup;
+			children = (
+				19BE6CB7267412CF00624F4A /* Main */,
+			);
+			path = Localizations;
+			sourceTree = "<group>";
+		};
+		19BE6CB7267412CF00624F4A /* Main */ = {
+			isa = PBXGroup;
+			children = (
+				19BE6CBC2674132500624F4A /* Localizable.strings */,
+			);
+			path = Main;
+			sourceTree = "<group>";
+		};
 		34CA4DF169B53D67EF18ED8A /* View */ = {
 			isa = PBXGroup;
 			children = (
@@ -676,6 +711,7 @@
 		3811DE1325C9D39E00A708ED /* Sources */ = {
 			isa = PBXGroup;
 			children = (
+				19BE6CB6267412C200624F4A /* Localizations */,
 				3811DEDE25C9E2DD00A708ED /* Application */,
 				3811DF0A25CAAAA500A708ED /* APS */,
 				38E98A3225F5300800C0CED0 /* Config */,
@@ -1556,6 +1592,23 @@
 			knownRegions = (
 				en,
 				Base,
+				ar,
+				ca,
+				"zh-Hans",
+				da,
+				nl,
+				fr,
+				fi,
+				de,
+				el,
+				he,
+				it,
+				nb,
+				pl,
+				ru,
+				sv,
+				uk,
+				es,
 			);
 			mainGroup = 388E594F25AD948C0019842D;
 			packageReferences = (
@@ -1581,6 +1634,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				388E596025AD948E0019842D /* Assets.xcassets in Resources */,
+				19BE6CBA2674132500624F4A /* Localizable.strings in Resources */,
 				388E597225AD9CF10019842D /* json in Resources */,
 				388E596F25AD96040019842D /* javascript in Resources */,
 			);
@@ -1865,12 +1919,41 @@
 		};
 /* End PBXTargetDependency section */
 
+/* Begin PBXVariantGroup section */
+		19BE6CBC2674132500624F4A /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				19BE6CBD2674152700624F4A /* ar */,
+				19BE6CBE2674152D00624F4A /* ca */,
+				19BE6CBF2674153200624F4A /* zh-Hans */,
+				19BE6CC02674153800624F4A /* da */,
+				19BE6CC12674153C00624F4A /* nl */,
+				19BE6CC22674154300624F4A /* fr */,
+				19BE6CC42674155000624F4A /* fi */,
+				19BE6CC52674155A00624F4A /* de */,
+				19BE6CC62674156100624F4A /* el */,
+				19BE6CC72674156600624F4A /* he */,
+				19BE6CC82674156E00624F4A /* it */,
+				19BE6CC92674157400624F4A /* nb */,
+				19BE6CCA2674158400624F4A /* pl */,
+				19BE6CCB2674158900624F4A /* ru */,
+				19BE6CCC2674158F00624F4A /* sv */,
+				19BE6CCD2674159600624F4A /* uk */,
+				19BE6CCE2674159C00624F4A /* es */,
+				19BE6CCF267559A100624F4A /* en */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
 /* Begin XCBuildConfiguration section */
 		388E596525AD948E0019842D /* Debug */ = {
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 38F3783A2613555C009DB701 /* Config.xcconfig */;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@@ -1934,6 +2017,7 @@
 			baseConfigurationReference = 38F3783A2613555C009DB701 /* Config.xcconfig */;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";

File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/ca.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/el.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings


File diff suppressed because it is too large
+ 486 - 0
FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings


File diff suppressed because it is too large
+ 504 - 0
FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings


+ 1 - 1
FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift

@@ -113,7 +113,7 @@ extension AddTempTarget {
                     .padding(.vertical)
                     .onTapGesture {
                         removeAlert = Alert(
-                            title: Text("A you sure?"),
+                            title: Text("Are you sure?"),
                             message: Text("Delete preset \"\(preset.displayName)\""),
                             primaryButton: .destructive(Text("Delete"), action: { viewModel.removePreset(id: preset.id) }),
                             secondaryButton: .cancel()

+ 13 - 4
FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift

@@ -25,7 +25,11 @@ extension Bolus {
                         HStack {
                             Text("Insulin required").foregroundColor(.secondary)
                             Spacer()
-                            Text(formatter.string(from: viewModel.inslinRequired as NSNumber)! + " U").foregroundColor(.secondary)
+                            Text(
+                                formatter
+                                    .string(from: viewModel.inslinRequired as NSNumber)! +
+                                    NSLocalizedString(" U", comment: "Insulin unit")
+                            ).foregroundColor(.secondary)
                         }.contentShape(Rectangle())
                             .onTapGesture {
                                 viewModel.amount = viewModel.inslinRecommended
@@ -33,7 +37,11 @@ extension Bolus {
                         HStack {
                             Text("Insulin recommended")
                             Spacer()
-                            Text(formatter.string(from: viewModel.inslinRecommended as NSNumber)! + " U")
+                            Text(
+                                formatter
+                                    .string(from: viewModel.inslinRequired as NSNumber)! +
+                                    NSLocalizedString(" U", comment: "Insulin unit")
+                            ).foregroundColor(.secondary)
                         }.contentShape(Rectangle())
                             .onTapGesture {
                                 viewModel.amount = viewModel.inslinRecommended
@@ -76,9 +84,10 @@ extension Bolus {
                 }
             }
             .alert(isPresented: $isAddInsulinAlertPresented) {
-                let amount = formatter.string(from: viewModel.amount as NSNumber)! + " U"
+                let amount = formatter
+                    .string(from: viewModel.amount as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit")
                 return Alert(
-                    title: Text("Are your sure?"),
+                    title: Text("Are you sure?"),
                     message: Text("Add \(amount) without bolusing"),
                     primaryButton: .destructive(
                         Text("Add"),

+ 4 - 3
FreeAPS/Sources/Modules/DataTable/DataTableDataFlow.swift

@@ -77,11 +77,12 @@ enum DataTable {
 
             switch type {
             case .carbs:
-                return numberFormater.string(from: amount as NSNumber)! + " g"
+                return numberFormater.string(from: amount as NSNumber)! + NSLocalizedString(" g", comment: "gram of carbs")
             case .bolus:
-                return numberFormater.string(from: amount as NSNumber)! + " U"
+                return numberFormater.string(from: amount as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit")
             case .tempBasal:
-                return numberFormater.string(from: amount as NSNumber)! + " U/hr"
+                return numberFormater
+                    .string(from: amount as NSNumber)! + NSLocalizedString(" U/hr", comment: "Unit insulin per hour")
             case .tempTarget:
                 var converted = amount
                 if units == .mmolL {

+ 7 - 6
FreeAPS/Sources/Modules/Home/View/Header/PumpView.swift

@@ -30,9 +30,9 @@ struct PumpView: View {
                         .frame(height: 8)
                         .foregroundColor(reservoirColor)
                     if reservoir == 0xDEAD_BEEF {
-                        Text("50+ U").font(.system(size: 12, weight: .bold))
+                        Text("50+ " + NSLocalizedString("U", comment: "Insulin unit")).font(.system(size: 12, weight: .bold))
                     } else {
-                        Text(reservoirFormatter.string(from: reservoir as NSNumber)! + " U")
+                        Text(reservoirFormatter.string(from: reservoir as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit"))
                             .font(.system(size: 12, weight: .bold))
                     }
                 }
@@ -63,7 +63,7 @@ struct PumpView: View {
 
     private func remainingTimeString(time: TimeInterval) -> String {
         guard time > 0 else {
-            return "Replace pod"
+            return NSLocalizedString("Replace pod", comment: "View/Header when pod expired")
         }
 
         var time = time
@@ -74,14 +74,15 @@ struct PumpView: View {
         let minutes = Int(time / 1.minutes.timeInterval)
 
         if days >= 1 {
-            return "\(days)d \(hours)h"
+            return "\(days)" + NSLocalizedString("d", comment: "abbreviation for days") + " \(hours)" +
+            NSLocalizedString("h", comment: "abbreviation for hours")
         }
 
         if hours >= 1 {
-            return "\(hours)h"
+            return "\(hours)" + NSLocalizedString("h", comment: "abbreviation for hours")
         }
 
-        return "\(minutes)m"
+        return "\(minutes)" + NSLocalizedString("m", comment: "abbreviation for minutes")
     }
 
     private var batteryColor: Color {

+ 16 - 7
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -32,13 +32,19 @@ extension Home {
                 VStack(alignment: .leading, spacing: 12) {
                     HStack {
                         Text("IOB").font(.caption2).foregroundColor(.secondary)
-                        Text((numberFormatter.string(from: (viewModel.suggestion?.iob ?? 0) as NSNumber) ?? "0") + " U")
-                            .font(.system(size: 12, weight: .bold))
+                        Text(
+                            (numberFormatter.string(from: (viewModel.suggestion?.iob ?? 0) as NSNumber) ?? "0") +
+                                NSLocalizedString(" U", comment: "Insulin unit")
+                        )
+                        .font(.system(size: 12, weight: .bold))
                     }
                     HStack {
                         Text("COB").font(.caption2).foregroundColor(.secondary)
-                        Text((numberFormatter.string(from: (viewModel.suggestion?.cob ?? 0) as NSNumber) ?? "0") + " g")
-                            .font(.system(size: 12, weight: .bold))
+                        Text(
+                            (numberFormatter.string(from: (viewModel.suggestion?.cob ?? 0) as NSNumber) ?? "0") +
+                                NSLocalizedString(" g", comment: "gram of carbs")
+                        )
+                        .font(.system(size: 12, weight: .bold))
                     }
                 }
                 Spacer()
@@ -91,9 +97,12 @@ extension Home {
                         .font(.system(size: 12, weight: .bold)).foregroundColor(.loopGray)
                         .padding(.leading, 8)
                 } else if let tempRate = viewModel.tempRate {
-                    Text((numberFormatter.string(from: tempRate as NSNumber) ?? "0") + " U/hr")
-                        .font(.system(size: 12, weight: .bold)).foregroundColor(.insulin)
-                        .padding(.leading, 8)
+                    Text(
+                        (numberFormatter.string(from: tempRate as NSNumber) ?? "0") +
+                            NSLocalizedString(" U/hr", comment: "Unit per hour with space")
+                    )
+                    .font(.system(size: 12, weight: .bold)).foregroundColor(.insulin)
+                    .padding(.leading, 8)
                 }
 
                 if let tempTarget = viewModel.tempTarget {

+ 9 - 1
FreeAPS/Sources/Modules/PreferencesEditor/PreferencesEditorDataFlow.swift

@@ -6,6 +6,7 @@ enum PreferencesEditor {
     class Field<T>: Identifiable {
         var displayName: String
         var keypath: WritableKeyPath<Preferences, T>
+        var infoText: String
         var value: T {
             didSet {
                 settable?.onSet(keypath, value: value)
@@ -14,10 +15,17 @@ enum PreferencesEditor {
 
         weak var settable: PreferencesSettable?
 
-        init(displayName: String, keypath: WritableKeyPath<Preferences, T>, value: T, settable: PreferencesSettable? = nil) {
+        init(
+            displayName: String,
+            keypath: WritableKeyPath<Preferences, T>,
+            value: T,
+            infoText: String,
+            settable: PreferencesSettable? = nil
+        ) {
             self.displayName = displayName
             self.keypath = keypath
             self.value = value
+            self.infoText = infoText
             self.settable = settable
         }
 

File diff suppressed because it is too large
+ 148 - 8
FreeAPS/Sources/Modules/PreferencesEditor/PreferencesEditorViewModel.swift


+ 24 - 2
FreeAPS/Sources/Modules/PreferencesEditor/View/PreferencesEditorRootView.swift

@@ -1,5 +1,11 @@
 import SwiftUI
 
+struct InfoText: Identifiable {
+    var id: String { description }
+    let description: String
+    let oref0Variable: String
+}
+
 extension PreferencesEditor {
     struct RootView: BaseView {
         @EnvironmentObject var viewModel: ViewModel<Provider>
@@ -10,6 +16,8 @@ extension PreferencesEditor {
             return formatter
         }
 
+        @State private var infoButtonPressed: InfoText?
+
         var body: some View {
             Form {
                 Section(header: Text("FreeAPS X")) {
@@ -36,17 +44,24 @@ extension PreferencesEditor {
                     }
 
                     ForEach(viewModel.boolFields.indexed(), id: \.1.id) { index, field in
-                        Toggle(field.displayName, isOn: self.$viewModel.boolFields[index].value)
+                        HStack {
+                            Button("", action: {
+                                infoButtonPressed = InfoText(description: field.infoText, oref0Variable: field.displayName)
+                            })
+                            Toggle(field.displayName, isOn: self.$viewModel.boolFields[index].value)
+                        }
                     }
 
                     ForEach(viewModel.decimalFields.indexed(), id: \.1.id) { index, field in
                         HStack {
+                            Button("", action: {
+                                infoButtonPressed = InfoText(description: field.infoText, oref0Variable: field.displayName)
+                            })
                             Text(field.displayName)
                             DecimalTextField("0", value: self.$viewModel.decimalFields[index].value, formatter: formatter)
                         }
                     }
                 }
-
                 Section {
                     Text("Edit settings json").chevronCell()
                         .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.settings), from: self)
@@ -54,6 +69,13 @@ extension PreferencesEditor {
             }
             .navigationTitle("Preferences")
             .navigationBarTitleDisplayMode(.automatic)
+            .alert(item: $infoButtonPressed) { infoButton in
+                Alert(
+                    title: Text("\(infoButton.oref0Variable)"),
+                    message: Text("\(infoButton.description)"),
+                    dismissButton: .default(Text("OK"))
+                )
+            }
         }
     }
 }

+ 2 - 2
FreeAPS/Sources/Views/DecimalTextField.swift

@@ -36,13 +36,13 @@ struct DecimalTextField: UIViewRepresentable {
             height: 44
         ))
         let clearButton = UIBarButtonItem(
-            title: "Clear",
+            title: NSLocalizedString("Clear", comment: "Clear button"),
             style: .plain,
             target: self,
             action: #selector(textfield.clearButtonTapped(button:))
         )
         let doneButton = UIBarButtonItem(
-            title: "Done",
+            title: NSLocalizedString("Done", comment: "Done button"),
             style: .done,
             target: self,
             action: #selector(textfield.doneButtonTapped(button:))

+ 1 - 1
README.md

@@ -47,7 +47,7 @@ Beta versions are the first to introduce new functionality. They are designed to
 
 **Beta versions are not recommended for daily use for blood glucose control!**
 
-Beta numbers end with a number greater than 0, and the code can be found in the [dev brunch](https://github.com/ivalkou/freeaps/tree/dev).
+Beta numbers end with a number greater than 0, and the code can be found in the [dev branch](https://github.com/ivalkou/freeaps/tree/dev).
 
 Pull requests are accepted on the dev branch.