Bladeren bron

Merge branch 'dev' into Crowdin

Jon B.M 2 jaren geleden
bovenliggende
commit
9697dd35b1
58 gewijzigde bestanden met toevoegingen van 299 en 149 verwijderingen
  1. 1 1
      .github/FUNDING.yml
  2. 2 1
      Config.xcconfig
  3. 2 2
      FreeAPS.xcodeproj/project.pbxproj
  4. 1 0
      FreeAPS/Resources/Info.plist
  5. 1 1
      FreeAPS/Resources/javascript/bundle/determine-basal.js
  6. 1 1
      FreeAPS/Resources/javascript/bundle/profile.js
  7. 2 2
      FreeAPS/Resources/javascript/prepare/autotune-prep.js
  8. 1 1
      FreeAPS/Resources/javascript/prepare/meal.js
  9. 44 40
      FreeAPS/Resources/json/defaults/freeaps/freeaps_settings.json
  10. 53 0
      FreeAPS/Resources/json/defaults/preferences.json
  11. 1 1
      FreeAPS/Resources/json/defaults/settings/bg_targets.json
  12. 28 18
      FreeAPS/Sources/APS/CGM/DexcomSourceG6.swift
  13. 3 2
      FreeAPS/Sources/APS/Storage/PumpHistoryStorage.swift
  14. 1 1
      FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings
  15. 1 1
      FreeAPS/Sources/Localizations/Main/ca.lproj/Localizable.strings
  16. 1 1
      FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings
  17. 1 1
      FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings
  18. 4 1
      FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings
  19. 1 1
      FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings
  20. 1 1
      FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings
  21. 1 1
      FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings
  22. 1 1
      FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings
  23. 1 1
      FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings
  24. 1 1
      FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings
  25. 1 1
      FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings
  26. 1 1
      FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings
  27. 1 1
      FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings
  28. 1 1
      FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings
  29. 1 1
      FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings
  30. 1 1
      FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings
  31. 2 2
      FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings
  32. 1 1
      FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings
  33. 1 1
      FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings
  34. 1 1
      FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings
  35. 1 1
      FreeAPS/Sources/Models/AlertEntry.swift
  36. 1 1
      FreeAPS/Sources/Models/Announcement.swift
  37. 1 1
      FreeAPS/Sources/Models/CarbsEntry.swift
  38. 10 0
      FreeAPS/Sources/Models/FreeAPSSettings.swift
  39. 1 1
      FreeAPS/Sources/Models/NightscoutTreatment.swift
  40. 3 3
      FreeAPS/Sources/Models/Preferences.swift
  41. 6 1
      FreeAPS/Sources/Models/PumpHistoryEvent.swift
  42. 1 1
      FreeAPS/Sources/Models/TempTarget.swift
  43. 4 0
      FreeAPS/Sources/Modules/CGM/CGMStateModel.swift
  44. 3 1
      FreeAPS/Sources/Modules/CGM/View/CGMRootView.swift
  45. 1 1
      FreeAPS/Sources/Modules/CREditor/CREditorStateModel.swift
  46. 19 10
      FreeAPS/Sources/Modules/DataTable/DataTableDataFlow.swift
  47. 8 1
      FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift
  48. 2 1
      FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift
  49. 1 2
      FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift
  50. 1 0
      FreeAPS/Sources/Modules/Snooze/View/SnoozeRootView.swift
  51. 2 2
      FreeAPS/Sources/Modules/Stat/View/ChartsView.swift
  52. 43 2
      FreeAPS/Sources/Services/Calendar/CalendarManager.swift
  53. 1 1
      FreeAPS/Sources/Services/Network/NightscoutAPI.swift
  54. 15 18
      FreeAPS/Sources/Services/UserNotifiactions/UserNotificationsManager.swift
  55. 2 1
      FreeAPS/Sources/Views/TagCloudView.swift
  56. 2 2
      FreeAPSWatch WatchKit Extension/Views/BolusConfirmationView.swift
  57. 1 1
      README.md
  58. 5 5
      fastlane/testflight.md

+ 1 - 1
.github/FUNDING.yml

@@ -1,3 +1,3 @@
 # These are supported funding model platforms
 
-custom: ["https://paypal.me/jonbm78?country.x=SE&locale.x=sv_SE"]
+custom: ["https://paypal.me/jonbm78", "https://www.paypal.com/paypalme/jonbm78"]

+ 2 - 1
Config.xcconfig

@@ -1,11 +1,12 @@
 APP_DISPLAY_NAME = iAPS
-APP_VERSION = 2.2.2
+APP_VERSION = 2.2.5
 APP_BUILD_NUMBER = 1
 COPYRIGHT_NOTICE =
 DEVELOPER_TEAM = ##TEAM_ID##
 BUNDLE_IDENTIFIER = ru.artpancreas.$(DEVELOPMENT_TEAM).FreeAPS
 APP_GROUP_ID = group.com.$(DEVELOPMENT_TEAM).loopkit.LoopGroup
 APP_ICON = pod_colorful
+APP_URL_SCHEME = freeaps-x
 
 #include? "ConfigOverride.xcconfig"
 //#include? "../../ConfigOverride.xcconfig"

+ 2 - 2
FreeAPS.xcodeproj/project.pbxproj

@@ -2254,11 +2254,11 @@
 			buildPhases = (
 				3811DEF525CA169200A708ED /* Swiftformat */,
 				388E595425AD948C0019842D /* Sources */,
-				B99D8B8E295F34DB00420AB8 /* Run Script */,
 				388E595525AD948C0019842D /* Frameworks */,
 				388E595625AD948C0019842D /* Resources */,
 				3821ECD025DC703C00BC42AD /* Embed Frameworks */,
 				38E8753D27554D5900975559 /* Embed Watch Content */,
+				B99D8B8E295F34DB00420AB8 /* Run Script */,
 			);
 			buildRules = (
 			);
@@ -2484,7 +2484,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "git_version=$(git log -1 --format=\"%h\")\ngit_branch=$(git symbolic-ref --short -q HEAD)\ngit_tag=$(git describe --tags --exact-match 2>/dev/null)\n\ngit_branch_or_tag=\"${git_branch:-${git_tag}}\"\ngit_branch_or_tag_version=\"${git_branch:-${git_tag}} ${git_version}\"\n\ninfo_plist=\"${SRCROOT}/FreeAPS/Resources/Info.plist\"\n\n/usr/libexec/PlistBuddy -c \"Set :BuildBranch '${git_branch_or_tag_version}'\" \"${info_plist}\"\n";
+			shellScript = "#!/bin/sh\n\ngit_version=$(git log -1 --format=\"%h\")\ngit_branch=$(git symbolic-ref --short -q HEAD)\ngit_tag=$(git describe --tags --exact-match 2>/dev/null)\n\ngit_branch_or_tag=\"${git_branch:-${git_tag}}\"\ngit_branch_or_tag_version=\"${git_branch:-${git_tag}} ${git_version}\"\n\ninfo_plist=\"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}\"\n\n/usr/libexec/PlistBuddy -c \"Set :BuildBranch '${git_branch_or_tag_version}'\" \"${info_plist}\"\n";
 		};
 /* End PBXShellScriptBuildPhase section */
 

+ 1 - 0
FreeAPS/Resources/Info.plist

@@ -37,6 +37,7 @@
 			<string>com.artificial-pancreas-iaps</string>
 			<key>CFBundleURLSchemes</key>
 			<array>
+				<string>$(APP_URL_SCHEME)</string>
 				<string>freeaps-x</string>
 			</array>
 		</dict>

File diff suppressed because it is too large
+ 1 - 1
FreeAPS/Resources/javascript/bundle/determine-basal.js


File diff suppressed because it is too large
+ 1 - 1
FreeAPS/Resources/javascript/bundle/profile.js


+ 2 - 2
FreeAPS/Resources/javascript/prepare/autotune-prep.js

@@ -1,6 +1,6 @@
 function generate(pumphistory_data, profile_data, glucose_data, pumpprofile_data, carb_data = {} , categorize_uam_as_basal = false, tune_insulin_curve = false) {
-    if (typeof(profile_data.carb_ratio) === 'undefined' || profile_data.carb_ratio < 1) {
-        if (typeof(pumpprofile_data.carb_ratio) === 'undefined' || pumpprofile_data.carb_ratio < 1) {
+    if (typeof(profile_data.carb_ratio) === 'undefined' || profile_data.carb_ratio < 0.1) {
+        if (typeof(pumpprofile_data.carb_ratio) === 'undefined' || pumpprofile_data.carb_ratio < 0.1) {
             console.log('{ "carbs": 0, "mealCOB": 0, "reason": "carb_ratios ' + profile_data.carb_ratio + ' and ' + pumpprofile_data.carb_ratio + ' out of bounds" }');
             return console.error("Error: carb_ratios " + profile_data.carb_ratio + ' and ' + pumpprofile_data.carb_ratio + " out of bounds");
         } else {

+ 1 - 1
FreeAPS/Resources/javascript/prepare/meal.js

@@ -1,7 +1,7 @@
 //для monitor/meal.json параметры: monitor/pumphistory-24h-zoned.json settings/profile.json monitor/clock-zoned.json monitor/glucose.json settings/basal_profile.json monitor/carbhistory.json
 
 function generate(pumphistory_data, profile_data, clock_data, glucose_data, basalprofile_data, carbhistory = false) {
-    if (typeof(profile_data.carb_ratio) === 'undefined' || profile_data.carb_ratio < 1) {
+    if (typeof(profile_data.carb_ratio) === 'undefined' || profile_data.carb_ratio < 0.1) {
         return {"error":"Error: carb_ratio " + profile_data.carb_ratio + " out of bounds"};
     }
 

+ 44 - 40
FreeAPS/Resources/json/defaults/freeaps/freeaps_settings.json

@@ -1,42 +1,46 @@
 {
-    "useAlarmSound" : false,
-      "uploadStats" : false,
-      "useCalendar" : false,
-      "rulerMarks" : false,
-      "individualAdjustmentFactor" : 0.5,
-      "low" : 70,
-      "displayHR" : true,
-      "localGlucosePort" : 8080,
-      "uploadGlucose" : true,
-      "allowAnnouncements" : false,
-      "debugOptions" : false,
-      "useAppleHealth" : false,
-      "high" : 170,
-      "yGridLines" : true,
-      "useLocalGlucoseSource" : false,
-      "closedLoop" : false,
-      "units" : "mmol/L",
-      "xGridLines" : true,
-      "lowGlucose" : 70,
-      "oneDimensionalGraph" : false,
-      "glucoseNotificationsAlways" : false,
-      "addSourceInfoToGlucoseNotifications" : false,
-      "cgm" : "nightscout",
-      "glucoseBadge" : true,
-      "overrideHbA1cUnit" : false,
-      "delay" : 80,
-      "smoothGlucose" : false,
-      "skipBolusScreenAfterCarbs" : false,
-      "highGlucose" : 220,
-      "timeCap" : 8,
-      "minuteInterval" : 20,
-      "isUploadEnabled" : true,
-      "useAutotune" : false,
-      "hours" : 6,
-      "carbsRequiredThreshold" : 50,
-      "insulinReqPercentage" : 80,
-      "useFPUconversion" : false,
-      "displayOnWatch" : "HR",
-      "animatedBackground" : false
-      "maxCarbs": 1000
+  "units" : "mmol/L",
+  "closedLoop" : false,
+  "allowAnnouncements" : false,
+  "useAutotune" : false,
+  "onlyAutotuneBasals" : false,
+  "isUploadEnabled" : false,
+  "useLocalGlucoseSource" : false,
+  "localGlucosePort" : 8080,
+  "debugOptions" : false,
+  "insulinReqPercentage" : 70,
+  "skipBolusScreenAfterCarbs" : false,
+  "displayHR" : false,
+  "cgm" : "nightscout",
+  "uploadGlucose" : true,
+  "useCalendar" : false,
+  "displayCalendarEmojis" : false,
+  "displayCalendarIOBandCOB" : false,
+  "glucoseBadge" : false,
+  "glucoseNotificationsAlways" : false,
+  "useAlarmSound" : false,
+  "addSourceInfoToGlucoseNotifications" : false,
+  "lowGlucose" : 72,
+  "highGlucose" : 270,
+  "carbsRequiredThreshold" : 10,
+  "animatedBackground" : false,
+  "useFPUconversion" : true,
+  "individualAdjustmentFactor" : 0.5,
+  "timeCap" : 8,
+  "minuteInterval" : 30,
+  "delay" : 60,
+  "useAppleHealth" : false,
+  "smoothGlucose" : false,
+  "displayOnWatch" : "BGTarget",
+  "overrideHbA1cUnit" : false,
+  "high" : 145,
+  "low" : 70,
+  "uploadStats" : true,
+  "hours" : 6,
+  "xGridLines" : true,
+  "yGridLines" : true,
+  "oneDimensionalGraph" : false,
+  "rulerMarks" : false,
+  "maxCarbs": 1000,
+  "displayFatAndProteinOnWatch": false
 }

+ 53 - 0
FreeAPS/Resources/json/defaults/preferences.json

@@ -0,0 +1,53 @@
+{
+  "max_iob" : 0,
+  "max_daily_safety_multiplier" : 3,
+  "current_basal_safety_multiplier" : 4,
+  "autosens_max" : 1.2,
+  "autosens_min" : 0.7,
+  "smb_delivery_ratio" : 0.5,
+  "rewind_resets_autosens" : true,
+  "high_temptarget_raises_sensitivity" : false,
+  "low_temptarget_lowers_sensitivity" : false,
+  "sensitivity_raises_target" : true,
+  "resistanceLowersTarget" : false,
+  "adv_target_adjustments" : false,
+  "exercise_mode" : false,
+  "half_basal_exercise_target" : 160,
+  "maxCOB" : 120,
+  "wide_bg_target_range" : false,
+  "skip_neutral_temps" : false,
+  "unsuspend_if_no_temp" : false,
+  "min_5m_carbimpact" : 8,
+  "autotune_isf_adjustmentFraction" : 1,
+  "remainingCarbsFraction" : 1,
+  "remainingCarbsCap" : 90,
+  "enableUAM" : false,
+  "A52_risk_enable" : false,
+  "enableSMB_with_COB" : false,
+  "enableSMB_with_temptarget" : false,
+  "enableSMB_always" : false,
+  "enableSMB_after_carbs" : false,
+  "allowSMB_with_high_temptarget" : false,
+  "maxSMBBasalMinutes" : 30,
+  "maxUAMSMBBasalMinutes" : 30,
+  "SMBInterval" : 3,
+  "bolus_increment" : 0.1,
+  "curve" : "rapid-acting",
+  "useCustomPeakTime" : false,
+  "insulinPeakTime" : 75,
+  "carbsReqThreshold" : 1,
+  "noisyCGMTargetMultiplier" : 1.3,
+  "suspend_zeros_iob" : false,
+  "maxDelta_bg_threshold" : 0.2,
+  "adjustmentFactor" : 0.5,
+  "sigmoid" : false,
+  "enableDynamicCR" : false,
+  "useNewFormula" : false,
+  "useWeightedAverage" : false,
+  "weightPercentage" : 0.65,
+  "tddAdjBasal" : false,
+  "enableSMB_high_bg" : false,
+  "enableSMB_high_bg_target" : 110,
+  "threshold_setting" : 65,
+  "updateInterval" : 20
+}

+ 1 - 1
FreeAPS/Resources/json/defaults/settings/bg_targets.json

@@ -4,7 +4,7 @@
     "targets": [
         {
             "low": 5.5,
-            "high": 6.0,
+            "high": 5.5,
             "start": "00:00:00",
             "offset": 0
         }

+ 28 - 18
FreeAPS/Sources/APS/CGM/DexcomSourceG6.swift

@@ -145,25 +145,35 @@ extension DexcomSourceG6: CGMManagerDelegate {
         debug(.deviceManager, "DEXCOM - Process CGM Reading Result launched with \(readingResult)")
         switch readingResult {
         case let .newData(values):
-            let bloodGlucose = values.compactMap { newGlucoseSample -> BloodGlucose? in
-                let quantity = newGlucoseSample.quantity
-                let value = Int(quantity.doubleValue(for: .milligramsPerDeciliter))
-                return BloodGlucose(
-                    _id: newGlucoseSample.syncIdentifier,
-                    sgv: value,
-                    direction: .init(trendType: newGlucoseSample.trend),
-                    date: Decimal(Int(newGlucoseSample.date.timeIntervalSince1970 * 1000)),
-                    dateString: newGlucoseSample.date,
-                    unfiltered: Decimal(value),
-                    filtered: nil,
-                    noise: nil,
-                    glucose: value,
-                    type: "sgv",
-                    transmitterID: self.transmitterID
-                )
+            if let cgmG6Manager = cgmManager as? G6CGMManager,
+               let activationDate = cgmG6Manager.latestReading?.activationDate,
+               let sessionStartDate = cgmG6Manager.latestReading?.sessionStartDate
+            {
+                let bloodGlucose = values.compactMap { newGlucoseSample -> BloodGlucose? in
+                    let quantity = newGlucoseSample.quantity
+                    let value = Int(quantity.doubleValue(for: .milligramsPerDeciliter))
+                    return BloodGlucose(
+                        _id: newGlucoseSample.syncIdentifier,
+                        sgv: value,
+                        direction: .init(trendType: newGlucoseSample.trend),
+                        date: Decimal(Int(newGlucoseSample.date.timeIntervalSince1970 * 1000)),
+                        dateString: newGlucoseSample.date,
+                        unfiltered: Decimal(value),
+                        filtered: nil,
+                        noise: nil,
+                        glucose: value,
+                        type: "sgv",
+                        activationDate: activationDate,
+                        sessionStartDate: sessionStartDate,
+                        transmitterID: self.transmitterID
+                    )
+                }
+                promise?(.success(bloodGlucose))
+                completion()
+            } else {
+                // Handle the case where activationDate or sessionStartDate is nil
+                completion()
             }
-            promise?(.success(bloodGlucose))
-            completion()
         case .unreliableData:
             // loopManager.receivedUnreliableCGMReading()
             promise?(.failure(GlucoseDataError.unreliableData))

+ 3 - 2
FreeAPS/Sources/APS/Storage/PumpHistoryStorage.swift

@@ -44,7 +44,8 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable {
                         durationMin: nil,
                         rate: nil,
                         temp: nil,
-                        carbInput: nil
+                        carbInput: nil,
+                        isSMB: dose.automatic
                     )]
                 case .tempBasal:
                     guard let dose = event.dose else { return [] }
@@ -255,7 +256,7 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable {
                     rawRate: nil,
                     absolute: nil,
                     rate: nil,
-                    eventType: .bolus,
+                    eventType: (event.isSMB ?? false) ? .smb : .bolus,
                     createdAt: event.timestamp,
                     enteredBy: NigtscoutTreatment.local,
                     bolus: event,

+ 1 - 1
FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibrations";
 
 /* */
-"Create events in calendar" = "Create events in calendar";
+"Create Events in Calendar" = "Create Events in Calendar";
 
 /* */
 "Calendar" = "Calendar";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/ca.lproj/Localizable.strings

@@ -514,7 +514,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibrations";
 
 /* */
-"Create events in calendar" = "Create events in calendar";
+"Create Events in Calendar" = "Create Events in Calendar";
 
 /* */
 "Calendar" = "Calendar";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibrations";
 
 /* */
-"Create events in calendar" = "Create events in calendar";
+"Create Events in Calendar" = "Create Events in Calendar";
 
 /* */
 "Calendar" = "Calendar";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Kalibrierungen";
 
 /* */
-"Create events in calendar" = "Kalendereintrag erstellen";
+"Create Events in Calendar" = "Kalendereintrag erstellen";
 
 /* */
 "Calendar" = "Kalender";

+ 4 - 1
FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibrations";
 
 /* */
-"Create events in calendar" = "Create events in calendar";
+"Create Events in Calendar" = "Create Events in Calendar";
 
 /* */
 "Calendar" = "Calendar";
@@ -1115,6 +1115,9 @@ Enact a temp Basal or a temp target */
 /* Manual temp basal mode */
 "Manual" = "Manual";
 
+/* An Automatic delivered bolus (SMB) */
+"SMB" = "SMB";
+
 /* Status highlight when manual temp basal is running. */
 "Manual Basal" = "Manual Basal";
 

+ 1 - 1
FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibraciones";
 
 /* */
-"Create events in calendar" = "Crear eventos en el calendario";
+"Create Events in Calendar" = "Crear eventos en el calendario";
 
 /* */
 "Calendar" = "Calendario";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibrations";
 
 /* */
-"Create events in calendar" = "Create events in calendar";
+"Create Events in Calendar" = "Create Events in Calendar";
 
 /* */
 "Calendar" = "Calendar";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Étalonnages";
 
 /* */
-"Create events in calendar" = "Créer des événements dans le calendrier";
+"Create Events in Calendar" = "Créer des événements dans le calendrier";
 
 /* */
 "Calendar" = "Calendrier";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibrations";
 
 /* */
-"Create events in calendar" = "Create events in calendar";
+"Create Events in Calendar" = "Create Events in Calendar";
 
 /* */
 "Calendar" = "Calendar";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibrazioni";
 
 /* */
-"Create events in calendar" = "Crea eventi nel calendario";
+"Create Events in Calendar" = "Crea eventi nel calendario";
 
 /* */
 "Calendar" = "Calendario";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Kalibreringer";
 
 /* */
-"Create events in calendar" = "Opprett hendelser i kalenderen";
+"Create Events in Calendar" = "Opprett hendelser i kalenderen";
 
 /* */
 "Calendar" = "Kalender";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Kalibraties";
 
 /* */
-"Create events in calendar" = "Voeg gebeurtenissen toe aan de kalender";
+"Create Events in Calendar" = "Voeg gebeurtenissen toe aan de kalender";
 
 /* */
 "Calendar" = "Agenda";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings

@@ -521,7 +521,7 @@ Połączono z Nightscout!";
 "Calibrations" = "Calibrations";
 
 /* */
-"Create events in calendar" = "Create events in calendar";
+"Create Events in Calendar" = "Create Events in Calendar";
 
 /* */
 "Calendar" = "Calendar";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibragens";
 
 /* */
-"Create events in calendar" = "Criar eventos no calendário";
+"Create Events in Calendar" = "Criar eventos no calendário";
 
 /* */
 "Calendar" = "Calendário";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibrations";
 
 /* */
-"Create events in calendar" = "Create events in calendar";
+"Create Events in Calendar" = "Create Events in Calendar";
 
 /* */
 "Calendar" = "Calendar";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Калибровки";
 
 /* */
-"Create events in calendar" = "Создавать событий в календаре";
+"Create Events in Calendar" = "Создавать событий в календаре";
 
 /* */
 "Calendar" = "Календарь";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Calibrations";
 
 /* */
-"Create events in calendar" = "Create events in calendar";
+"Create Events in Calendar" = "Create Events in Calendar";
 
 /* */
 "Calendar" = "Calendar";

+ 2 - 2
FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Kalibreringar";
 
 /* */
-"Create events in calendar" = "Skapa kalenderhändelser";
+"Create Events in Calendar" = "Skapa kalenderhändelser";
 
 /* */
 "Calendar" = "Kalender";
@@ -1112,7 +1112,7 @@ Enact a temp Basal or a temp target */
 "Error" = "Fel";
 
 /* Manual temp basal mode */
-"Manual" = "Manuellt";
+"Manual" = "Manuell";
 
 /* Status highlight when manual temp basal is running. */
 "Manual Basal" = "Manuell temporär basal";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Kalibrasyonlar";
 
 /* */
-"Create events in calendar" = "Takvimde etkinlikler oluşturun";
+"Create Events in Calendar" = "Takvimde etkinlikler oluşturun";
 
 /* */
 "Calendar" = "Takvim";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "Калібрування";
 
 /* */
-"Create events in calendar" = "Створити подію в календарі";
+"Create Events in Calendar" = "Створити подію в календарі";
 
 /* */
 "Calendar" = "Календар";

+ 1 - 1
FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings

@@ -519,7 +519,7 @@ Enact a temp Basal or a temp target */
 "Calibrations" = "校准";
 
 /* */
-"Create events in calendar" = "在日历中创建事件";
+"Create Events in Calendar" = "在日历中创建事件";
 
 /* */
 "Calendar" = "日历";

+ 1 - 1
FreeAPS/Sources/Models/AlertEntry.swift

@@ -15,7 +15,7 @@ struct AlertEntry: JSON, Codable, Hashable {
     let contentBody: String?
     var errorMessage: String?
 
-    static let manual = "freeaps-x"
+    static let manual = "iAPS"
 
     static func == (lhs: AlertEntry, rhs: AlertEntry) -> Bool {
         lhs.issuedDate == rhs.issuedDate

+ 1 - 1
FreeAPS/Sources/Models/Announcement.swift

@@ -5,7 +5,7 @@ struct Announcement: JSON {
     let enteredBy: String
     let notes: String
 
-    static let remote = "freeaps-x-remote"
+    static let remote = "remote"
 
     var action: AnnouncementAction? {
         let components = notes.replacingOccurrences(of: " ", with: "").split(separator: ":")

+ 1 - 1
FreeAPS/Sources/Models/CarbsEntry.swift

@@ -11,7 +11,7 @@ struct CarbsEntry: JSON, Equatable, Hashable {
     let isFPU: Bool?
     let fpuID: String?
 
-    static let manual = "freeaps-x"
+    static let manual = "iAPS"
     static let appleHealth = "applehealth"
 
     static func == (lhs: CarbsEntry, rhs: CarbsEntry) -> Bool {

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

@@ -15,6 +15,8 @@ struct FreeAPSSettings: JSON, Equatable {
     var cgm: CGMType = .nightscout
     var uploadGlucose: Bool = true
     var useCalendar: Bool = false
+    var displayCalendarIOBandCOB: Bool = false
+    var displayCalendarEmojis: Bool = false
     var glucoseBadge: Bool = false
     var glucoseNotificationsAlways: Bool = false
     var useAlarmSound: Bool = false
@@ -113,6 +115,14 @@ extension FreeAPSSettings: Decodable {
             settings.useCalendar = useCalendar
         }
 
+        if let displayCalendarIOBandCOB = try? container.decode(Bool.self, forKey: .displayCalendarIOBandCOB) {
+            settings.displayCalendarIOBandCOB = displayCalendarIOBandCOB
+        }
+
+        if let displayCalendarEmojis = try? container.decode(Bool.self, forKey: .displayCalendarEmojis) {
+            settings.displayCalendarEmojis = displayCalendarEmojis
+        }
+
         if let useAppleHealth = try? container.decode(Bool.self, forKey: .useAppleHealth) {
             settings.useAppleHealth = useAppleHealth
         }

+ 1 - 1
FreeAPS/Sources/Models/NightscoutTreatment.swift

@@ -19,7 +19,7 @@ struct NigtscoutTreatment: JSON, Hashable, Equatable {
     let targetTop: Decimal?
     let targetBottom: Decimal?
 
-    static let local = "freeaps-x"
+    static let local = "iAPS"
 
     static let empty = NigtscoutTreatment(from: "{}")!
 

+ 3 - 3
FreeAPS/Sources/Models/Preferences.swift

@@ -8,8 +8,8 @@ struct Preferences: JSON {
     var autosensMin: Decimal = 0.7
     var smbDeliveryRatio: Decimal = 0.5
     var rewindResetsAutosens: Bool = true
-    var highTemptargetRaisesSensitivity: Bool = true
-    var lowTemptargetLowersSensitivity: Bool = true
+    var highTemptargetRaisesSensitivity: Bool = false
+    var lowTemptargetLowersSensitivity: Bool = false
     var sensitivityRaisesTarget: Bool = true
     var resistanceLowersTarget: Bool = false
     var advTargetAdjustments: Bool = false
@@ -39,7 +39,7 @@ struct Preferences: JSON {
     var insulinPeakTime: Decimal = 75
     var carbsReqThreshold: Decimal = 1.0
     var noisyCGMTargetMultiplier: Decimal = 1.3
-    var suspendZerosIOB: Bool = true
+    var suspendZerosIOB: Bool = false
     var timestamp: Date?
     var maxDeltaBGthreshold: Decimal = 0.2
     var adjustmentFactor: Decimal = 0.5

+ 6 - 1
FreeAPS/Sources/Models/PumpHistoryEvent.swift

@@ -11,6 +11,7 @@ struct PumpHistoryEvent: JSON, Equatable {
     let temp: TempType?
     let carbInput: Int?
     let note: String?
+    let isSMB: Bool?
 
     init(
         id: String,
@@ -22,7 +23,8 @@ struct PumpHistoryEvent: JSON, Equatable {
         rate: Decimal? = nil,
         temp: TempType? = nil,
         carbInput: Int? = nil,
-        note: String? = nil
+        note: String? = nil,
+        isSMB: Bool? = nil
     ) {
         self.id = id
         self.type = type
@@ -34,11 +36,13 @@ struct PumpHistoryEvent: JSON, Equatable {
         self.temp = temp
         self.carbInput = carbInput
         self.note = note
+        self.isSMB = isSMB
     }
 }
 
 enum EventType: String, JSON {
     case bolus = "Bolus"
+    case smb = "SMB"
     case mealBulus = "Meal Bolus"
     case correctionBolus = "Correction Bolus"
     case snackBolus = "Snack Bolus"
@@ -80,5 +84,6 @@ extension PumpHistoryEvent {
         case temp
         case carbInput = "carb_input"
         case note
+        case isSMB
     }
 }

+ 1 - 1
FreeAPS/Sources/Models/TempTarget.swift

@@ -10,7 +10,7 @@ struct TempTarget: JSON, Identifiable, Equatable, Hashable {
     let enteredBy: String?
     let reason: String?
 
-    static let manual = "freeaps-x"
+    static let manual = "iAPS"
     static let custom = "Temp target"
     static let cancel = "Cancel"
 

+ 4 - 0
FreeAPS/Sources/Modules/CGM/CGMStateModel.swift

@@ -16,6 +16,8 @@ extension CGM {
         @Published var uploadGlucose = true
         @Published var smoothGlucose = false
         @Published var createCalendarEvents = false
+        @Published var displayCalendarIOBandCOB = false
+        @Published var displayCalendarEmojis = false
         @Published var calendarIDs: [String] = []
         @Published var currentCalendarID: String = ""
         @Persisted(key: "CalendarManager.currentCalendarID") var storedCalendarID: String? = nil
@@ -28,6 +30,8 @@ extension CGM {
             cgmTransmitterDeviceAddress = UserDefaults.standard.cgmTransmitterDeviceAddress
 
             subscribeSetting(\.useCalendar, on: $createCalendarEvents) { createCalendarEvents = $0 }
+            subscribeSetting(\.displayCalendarIOBandCOB, on: $displayCalendarIOBandCOB) { displayCalendarIOBandCOB = $0 }
+            subscribeSetting(\.displayCalendarEmojis, on: $displayCalendarEmojis) { displayCalendarEmojis = $0 }
             subscribeSetting(\.smoothGlucose, on: $smoothGlucose, initial: { smoothGlucose = $0 })
 
             $cgm

+ 3 - 1
FreeAPS/Sources/Modules/CGM/View/CGMRootView.swift

@@ -54,13 +54,15 @@ extension CGM {
                         Text("Calibrations").navigationLink(to: .calibrations, from: self)
                     }
                     Section(header: Text("Calendar")) {
-                        Toggle("Create events in calendar", isOn: $state.createCalendarEvents)
+                        Toggle("Create Events in Calendar", isOn: $state.createCalendarEvents)
                         if state.calendarIDs.isNotEmpty {
                             Picker("Calendar", selection: $state.currentCalendarID) {
                                 ForEach(state.calendarIDs, id: \.self) {
                                     Text($0).tag($0)
                                 }
                             }
+                            Toggle("Display Emojis as Labels", isOn: $state.displayCalendarEmojis)
+                            Toggle("Display IOB and COB", isOn: $state.displayCalendarIOBandCOB)
                         }
                     }
 

+ 1 - 1
FreeAPS/Sources/Modules/CREditor/CREditorStateModel.swift

@@ -7,7 +7,7 @@ extension CREditor {
 
         let timeValues = stride(from: 0.0, to: 1.days.timeInterval, by: 30.minutes.timeInterval).map { $0 }
 
-        let rateValues = stride(from: 15.0, to: 501.0, by: 1.0).map { ($0.decimal ?? .zero) / 10 }
+        let rateValues = stride(from: 1.0, to: 501.0, by: 1.0).map { ($0.decimal ?? .zero) / 10 }
 
         var canAdd: Bool {
             guard let lastItem = items.last else { return true }

+ 19 - 10
FreeAPS/Sources/Modules/DataTable/DataTableDataFlow.swift

@@ -66,8 +66,9 @@ enum DataTable {
         let isFPU: Bool?
         let fpuID: String?
         let note: String?
+        let isSMB: Bool?
 
-        private var numberFormater: NumberFormatter {
+        private var numberFormatter: NumberFormatter {
             let formatter = NumberFormatter()
             formatter.numberStyle = .decimal
             formatter.maximumFractionDigits = 2
@@ -90,9 +91,10 @@ enum DataTable {
             duration: Decimal? = nil,
             id: String? = nil,
             idPumpEvent: String? = nil,
-            isFPU: Bool? = false,
+            isFPU: Bool? = nil,
             fpuID: String? = nil,
-            note: String? = nil
+            note: String? = nil,
+            isSMB: Bool? = nil
         ) {
             self.units = units
             self.type = type
@@ -105,6 +107,7 @@ enum DataTable {
             self.isFPU = isFPU
             self.fpuID = fpuID
             self.note = note
+            self.isSMB = isSMB
         }
 
         static func == (lhs: Treatment, rhs: Treatment) -> Bool {
@@ -126,14 +129,20 @@ enum DataTable {
 
             switch type {
             case .carbs:
-                return numberFormater.string(from: amount as NSNumber)! + NSLocalizedString(" g", comment: "gram of carbs")
+                return numberFormatter
+                    .string(from: amount as NSNumber)! + NSLocalizedString(" g", comment: "gram of carbs")
             case .fpus:
-                return numberFormater
+                return numberFormatter
                     .string(from: amount as NSNumber)! + NSLocalizedString(" g", comment: "gram of carb equilvalents")
             case .bolus:
-                return numberFormater.string(from: amount as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit")
+                return numberFormatter
+                    .string(from: amount as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit") +
+                    (
+                        (isSMB ?? false) ? " " + NSLocalizedString("Auto", comment: "Automatic delivered bolus (SMB)") : " " +
+                            NSLocalizedString("Manual", comment: "Manual Bolus")
+                    )
             case .tempBasal:
-                return numberFormater
+                return numberFormatter
                     .string(from: amount as NSNumber)! + NSLocalizedString(" U/hr", comment: "Unit insulin per hour")
             case .tempTarget:
                 var converted = amount
@@ -142,7 +151,7 @@ enum DataTable {
                 }
 
                 guard var secondAmount = secondAmount else {
-                    return numberFormater.string(from: converted as NSNumber)! + " \(units.rawValue)"
+                    return numberFormatter.string(from: converted as NSNumber)! + " \(units.rawValue)"
                 }
                 if units == .mmolL {
                     secondAmount = secondAmount.asMmolL
@@ -161,7 +170,7 @@ enum DataTable {
             case .carbs:
                 return .loopYellow
             case .fpus:
-                return .red
+                return .loopRed
             case .bolus:
                 return .insulin
             case .tempBasal:
@@ -177,7 +186,7 @@ enum DataTable {
             guard let duration = duration, duration > 0 else {
                 return nil
             }
-            return numberFormater.string(from: duration as NSNumber)! + " min"
+            return numberFormatter.string(from: duration as NSNumber)! + " min"
         }
     }
 

+ 8 - 1
FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift

@@ -66,7 +66,14 @@ extension DataTable {
                 let boluses = self.provider.pumpHistory()
                     .filter { $0.type == .bolus }
                     .map {
-                        Treatment(units: units, type: .bolus, date: $0.timestamp, amount: $0.amount, idPumpEvent: $0.id)
+                        Treatment(
+                            units: units,
+                            type: .bolus,
+                            date: $0.timestamp,
+                            amount: $0.amount,
+                            idPumpEvent: $0.id,
+                            isSMB: $0.isSMB
+                        )
                     }
 
                 let tempBasals = self.provider.pumpHistory()

+ 2 - 1
FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift

@@ -113,8 +113,9 @@ extension DataTable {
                 Image(systemName: "circle.fill").foregroundColor(item.color)
                 Text(dateFormatter.string(from: item.date))
                     .moveDisabled(true)
-                Text(item.type.name)
+                Text((item.isSMB ?? false) ? "SMB" : item.type.name)
                 Text(item.amountText).foregroundColor(.secondary)
+
                 if let duration = item.durationText {
                     Text(duration).foregroundColor(.secondary)
                 }

+ 1 - 2
FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift

@@ -292,10 +292,9 @@ extension OverrideProfilesConfig {
             let durationString = perpetual ? "" : "\(formatter.string(from: duration as NSNumber)!)"
             let scheduledSMBstring = (preset.smbIsOff && preset.smbIsAlwaysOff) ? "Scheduled SMBs" : ""
             let smbString = (preset.smbIsOff && scheduledSMBstring == "") ? "SMBs are off" : ""
-            let targetString = target != 0 ? "\(formatter.string(from: target as NSNumber)!)" : ""
+            let targetString = target != 0 ? "\(glucoseFormatter.string(from: target as NSNumber)!)" : ""
             let maxMinutesSMB = (preset.smbMinutes as Decimal?) != nil ? (preset.smbMinutes ?? 0) as Decimal : 0
             let maxMinutesUAM = (preset.uamMinutes as Decimal?) != nil ? (preset.uamMinutes ?? 0) as Decimal : 0
-
             let isfString = preset.isf ? "ISF" : ""
             let crString = preset.cr ? "CR" : ""
             let dash = crString != "" ? "/" : ""

+ 1 - 0
FreeAPS/Sources/Modules/Snooze/View/SnoozeRootView.swift

@@ -88,6 +88,7 @@ extension Snooze {
                     debug(.default, "will snooze for \(snoozeFor) until \(dateFormatter.string(from: untilDate))")
                     snoozeDescription = getSnoozeDescription()
                     BaseUserNotificationsManager.stopSound()
+                    state.hideModal()
                 } label: {
                     Text("Click to Snooze Alerts")
                         .padding()

+ 2 - 2
FreeAPS/Sources/Modules/Stat/View/ChartsView.swift

@@ -215,7 +215,7 @@ struct ChartsView: View {
                 let mapGlucoseNormal = mapGlucose.filter({ $0 > Int16(3.8 / 0.0555) && $0 < Int16(7.9 / 0.0555) })
                 HStack {
                     let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count)
-                    Text(units == .mmolL ? ">  11  " : ">  200 ").foregroundColor(.secondary)
+                    Text(units == .mmolL ? ">  11  " : ">  198 ").foregroundColor(.secondary)
                     Text(value.formatted()).foregroundColor(.orange)
                     Text("%").foregroundColor(.secondary)
                 }.font(.caption)
@@ -259,7 +259,7 @@ struct ChartsView: View {
                 Spacer()
                 HStack {
                     let value = Double(mapGlucoseAcuteHigh.count * 100 / mapGlucose.count)
-                    Text(units == .mmolL ? "> 11.0" : "> 216").font(.caption).foregroundColor(.secondary)
+                    Text(units == .mmolL ? "> 11.0" : "> 198").font(.caption).foregroundColor(.secondary)
                     Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange)
                     Text("%").font(.caption)
                 }

+ 43 - 2
FreeAPS/Sources/Services/Calendar/CalendarManager.swift

@@ -16,6 +16,7 @@ final class BaseCalendarManager: CalendarManager, Injectable {
     @Injected() private var settingsManager: SettingsManager!
     @Injected() private var broadcaster: Broadcaster!
     @Injected() private var glucoseStorage: GlucoseStorage!
+    @Injected() private var storage: FileStorage!
 
     init(resolver: Resolver) {
         injectServices(resolver)
@@ -62,6 +63,10 @@ final class BaseCalendarManager: CalendarManager, Injectable {
         // create an event now
         let event = EKEvent(eventStore: eventStore)
 
+        var glucoseIcon = "🟢"
+        glucoseIcon = Double(glucoseValue) <= Double(settingsManager.settings.low) ? "🔴" : glucoseIcon
+        glucoseIcon = Double(glucoseValue) >= Double(settingsManager.settings.high) ? "🟠" : glucoseIcon
+
         let glucoseText = glucoseFormatter
             .string(from: Double(
                 settingsManager.settings.units == .mmolL ?glucoseValue
@@ -74,9 +79,31 @@ final class BaseCalendarManager: CalendarManager, Injectable {
                     .string(from: Double(settingsManager.settings.units == .mmolL ? $0.asMmolL : Decimal($0)) as NSNumber)!
             } ?? "--"
 
-        let title = glucoseText + " " + directionText + " " + deltaText
+        let fetchedSuggestion = storage.retrieve(OpenAPS.Enact.enacted, as: Suggestion.self)
+        let iobText = iobFormatter.string(from: (fetchedSuggestion?.iob ?? 0) as NSNumber) ?? ""
+        let cobText = cobFormatter.string(from: (fetchedSuggestion?.cob ?? 0) as NSNumber) ?? ""
+
+        var glucoseDisplayText = settingsManager.settings.displayCalendarEmojis ? glucoseIcon + " " : ""
+        glucoseDisplayText += glucoseText + " " + directionText + " " + deltaText
+
+        var iobDisplayText = ""
+        var cobDisplayText = ""
+
+        if settingsManager.settings.displayCalendarIOBandCOB {
+            if settingsManager.settings.displayCalendarEmojis {
+                iobDisplayText += "💉"
+                cobDisplayText += "🥨"
+            } else {
+                iobDisplayText += "IOB:"
+                cobDisplayText += "COB:"
+            }
+            iobDisplayText += " " + iobText
+            cobDisplayText += " " + cobText
+
+            event.location = iobDisplayText + " " + cobDisplayText
+        }
 
-        event.title = title
+        event.title = glucoseDisplayText
         event.notes = "iAPS"
         event.startDate = Date()
         event.endDate = Date(timeIntervalSinceNow: 60 * 10)
@@ -133,6 +160,20 @@ final class BaseCalendarManager: CalendarManager, Injectable {
         return formatter
     }
 
+    private var iobFormatter: NumberFormatter {
+        let formatter = NumberFormatter()
+        formatter.numberStyle = .decimal
+        formatter.maximumFractionDigits = 1
+        return formatter
+    }
+
+    private var cobFormatter: NumberFormatter {
+        let formatter = NumberFormatter()
+        formatter.numberStyle = .decimal
+        formatter.maximumFractionDigits = 0
+        return formatter
+    }
+
     func setupGlucose() {
         let glucose = glucoseStorage.recent()
         let recentGlucose = glucose.last

+ 1 - 1
FreeAPS/Sources/Services/Network/NightscoutAPI.swift

@@ -33,7 +33,7 @@ extension NightscoutAPI {
     func checkConnection() -> AnyPublisher<Void, Swift.Error> {
         struct Check: Codable, Equatable {
             var eventType = "Note"
-            var enteredBy = "freeaps-x"
+            var enteredBy = "iAPS"
             var notes = "iAPS connected"
         }
         let check = Check()

+ 15 - 18
FreeAPS/Sources/Services/UserNotifiactions/UserNotificationsManager.swift

@@ -196,7 +196,6 @@ final class BaseUserNotificationsManager: NSObject, UserNotificationsManager, In
 
         ensureCanSendNotification {
             var titles: [String] = []
-
             var notificationAlarm = false
 
             switch self.glucoseStorage.alarm {
@@ -210,29 +209,27 @@ final class BaseUserNotificationsManager: NSObject, UserNotificationsManager, In
                 notificationAlarm = true
             }
 
-            if self.snoozeUntilDate > Date() {
-                titles.append(NSLocalizedString("(Snoozed)", comment: "(Snoozed)"))
-                notificationAlarm = false
-            }
-
             let delta = glucose.count >= 2 ? glucoseValue - (glucose[glucose.count - 2].glucose ?? 0) : nil
-
             let body = self.glucoseText(glucoseValue: glucoseValue, delta: delta, direction: lastGlucose.direction) + self
                 .infoBody()
 
-            titles.append(body)
-
-            let content = UNMutableNotificationContent()
-            content.title = titles.joined(separator: " ")
-            content.body = body
+            if self.snoozeUntilDate > Date() {
+                titles.append(NSLocalizedString("(Snoozed)", comment: "(Snoozed)"))
+                notificationAlarm = false
+            } else {
+                titles.append(body)
+                let content = UNMutableNotificationContent()
+                content.title = titles.joined(separator: " ")
+                content.body = body
+
+                if notificationAlarm {
+                    self.playSoundIfNeeded()
+                    content.sound = .default
+                    content.userInfo[NotificationAction.key] = NotificationAction.snooze.rawValue
+                }
 
-            if notificationAlarm {
-                self.playSoundIfNeeded()
-                content.sound = .default
-                content.userInfo[NotificationAction.key] = NotificationAction.snooze.rawValue
+                self.addRequest(identifier: .glucocoseNotification, content: content, deleteOld: true)
             }
-
-            self.addRequest(identifier: .glucocoseNotification, content: content, deleteOld: true)
         }
     }
 

+ 2 - 1
FreeAPS/Sources/Views/TagCloudView.swift

@@ -66,7 +66,8 @@ struct TagCloudView: View {
                  textTag where textTag.contains("AF:"),
                  textTag where textTag.contains("Autosens/Dynamic Limit:"),
                  textTag where textTag.contains("Dynamic ISF/CR"),
-                 textTag where textTag.contains("Basal ratio"):
+                 textTag where textTag.contains("Basal ratio"),
+                 textTag where textTag.contains("SMB Ratio:"):
                 return .zt
             default:
                 return .insulin

+ 2 - 2
FreeAPSWatch WatchKit Extension/Views/BolusConfirmationView.swift

@@ -40,7 +40,7 @@ struct BolusConfirmationView: View {
                     if isCrownLeftOriented {
                         Spacer().frame(width: elementSize / 2)
                     } else {
-                        Image(systemName: "arrow.down")
+                        Image(systemName: "digitalcrown.arrow.counterclockwise.fill")
                             .resizable()
                             .frame(width: elementSize / 2, height: elementSize / 2)
                             .foregroundColor(.primary)
@@ -51,7 +51,7 @@ struct BolusConfirmationView: View {
             .padding()
             HStack(spacing: 16) {
                 if isCrownLeftOriented {
-                    Image(systemName: "arrow.down")
+                    Image(systemName: "digitalcrown.arrow.counterclockwise.fill")
                         .resizable()
                         .frame(width: elementSize / 2, height: elementSize / 2)
                         .foregroundColor(.primary)

+ 1 - 1
README.md

@@ -56,7 +56,7 @@ iAPS app runs on iPhone or iPod. An iPhone 8 or newer is required.
 
 # Documentation
 
-[Discord iAPS - Server ](https://discord.gg/3eGsdykA6)
+[Discord iAPS - Server ](https://discord.gg/2gBpxRT2g)
 
 [iAPS documentation (under development)](https://iaps.readthedocs.io/en/latest/)
 

+ 5 - 5
fastlane/testflight.md

@@ -20,7 +20,7 @@ There are more detailed instructions in LoopDocs for doing Browser Builds of Loo
 
 ## Generate App Store Connect API Key
 
-This step is common for all "Browser Builds", and should be done ony once. Please save the API key somewhere safe, so it can be re-used for other builds, or if needing to start from scratch.
+This step is common for all "Browser Builds", and should be done only once. Please save the API key somewhere safe, so it can be re-used for other builds, or if needing to start from scratch.
 
 1. Sign in to the [Apple developer portal page](https://developer.apple.com/account/resources/certificates/list).
 1. Copy the team id from the upper right of the screen. Record this as your `TEAMID`.
@@ -71,18 +71,18 @@ If you have previously built Loop or another app using the "browser build" metho
 ## Create App Group
 
 If you have already built iAPS via Xcode using this Apple ID, you can skip on to [Create iAPS App in App Store Connect](#create-FreeAPS-X-app-in-app-store-connect).
-_Please note that in default builds of iAPS, the app group is actually identical to the one used with Loop, so please enter these details exactly as described below. This is to ease the setup of apps such as Xdrip4iOS. It may require some caution if transfering between FreAPS X and Loop._
+_Please note that in default builds of iAPS, the app group is actually identical to the one used with Loop, so please enter these details exactly as described below. This is to ease the setup of apps such as Xdrip4iOS. It may require some caution if transfering between iAPS and Loop._
 
 1. Go to [Register an App Group](https://developer.apple.com/account/resources/identifiers/applicationGroup/add/) on the apple developer site.
 1. For Description, use "Loop App Group".
-1. For Identifier, enter "group.com.TEAMID.loopkit.LoopGroup", subsituting your team id for `TEAMID`.
+1. For Identifier, enter "group.com.TEAMID.loopkit.LoopGroup", substituting your team id for `TEAMID`.
 1. Click "Continue" and then "Register".
 
 ## Add App Group to Bundle Identifiers
 
-1. Go to [Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources/identifiers/list) on the apple developer site.
+1. Go to [Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources/identifiers/list) on the Apple developer site.
 1. For each of the following identifier names:
-    * FreeeAPS
+    * FreeAPS
     * FreeAPS watchkitapp
     * FreeAPS watchkitapp watchkitextension
 1. Click on the identifier's name.