Bläddra i källkod

Merge branch 'UI' of github.com:polscm32/iAPS into UI

dnzxy 2 år sedan
förälder
incheckning
35e2c8e0f5
30 ändrade filer med 333 tillägg och 307 borttagningar
  1. 4 0
      Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents
  2. 3 3
      FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings
  3. 3 3
      FreeAPS/Sources/Localizations/Main/ca.lproj/Localizable.strings
  4. 3 3
      FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings
  5. 3 3
      FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings
  6. 24 3
      FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings
  7. 3 3
      FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings
  8. 3 3
      FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings
  9. 3 3
      FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings
  10. 3 3
      FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings
  11. 3 3
      FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings
  12. 3 3
      FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings
  13. 3 3
      FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings
  14. 3 3
      FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings
  15. 3 3
      FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings
  16. 3 3
      FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings
  17. 3 3
      FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings
  18. 3 3
      FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings
  19. 18 3
      FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings
  20. 3 3
      FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings
  21. 3 3
      FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings
  22. 3 3
      FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings
  23. 6 4
      FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift
  24. 107 92
      FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift
  25. 11 4
      FreeAPS/Sources/Modules/Home/HomeStateModel.swift
  26. 20 29
      FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift
  27. 9 6
      FreeAPS/Sources/Modules/Home/View/Header/PumpView.swift
  28. 76 95
      FreeAPS/Sources/Modules/Home/View/HomeRootView.swift
  29. 0 8
      FreeAPS/Sources/Modules/StatConfig/StatConfigStateModel.swift
  30. 1 6
      FreeAPS/Sources/Modules/StatConfig/View/StatConfigRootView.swift

+ 4 - 0
Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents

@@ -163,4 +163,8 @@
         <attribute name="id" optional="YES" attributeType="String" defaultValueString="empy"/>
         <attribute name="isPreset" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
     </entity>
+    <entity name="UXSettings" representedClassName="UXSettings" syncable="YES" codeGenerationType="class">
+        <attribute name="date" optional="YES" attributeType="Date" defaultDateTimeInterval="722095800" usesScalarValueType="NO"/>
+        <attribute name="hours" optional="YES" attributeType="Integer 16" defaultValueString="6" usesScalarValueType="YES"/>
+    </entity>
 </model>

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Temp Targets";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Delete carbs?";
+"Delete Carbs?" = "Delete Carbs?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Treatments";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -490,10 +490,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Temp Targets";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Delete carbs?";
+"Delete Carbs?" = "Delete Carbs?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Treatments";
@@ -1250,7 +1250,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Midlertidige Mål";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Slet kulhydrater?";
+"Delete Carbs?" = "Slet kulhydrater?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Slet insulin?";
+"Delete Insulin?" = "Slet insulin?";
 
 /* Treatments list */
 "Treatments" = "Behandlinger";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Temporäre Ziele";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Kohlenhydrate löschen?";
+"Delete Carbs?" = "Kohlenhydrate löschen?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Insulin löschen?";
+"Delete Insulin?" = "Insulin löschen?";
 
 /* Treatments list */
 "Treatments" = "Behandlungen";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistiken und Home-Ansicht";
 
 /* Alert text */
-"Delete carb equivalents?" = "Kohlenhydratäquivalente löschen?";
+"Delete Carb Equivalents?" = "Kohlenhydratäquivalente löschen?";
 
 /* */
 "Meal Presets" = "Mahlzeit Voreinstellungen";

+ 24 - 3
FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Temp Targets";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Delete carbs?";
+"Delete Carbs?" = "Delete Carbs?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Treatments";
@@ -1369,7 +1369,13 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
+
+/* */
+"All FPUs of the meal will be deleted." = "All FPUs of the meal will be deleted.";
+
+/* */
+"Delete Glucose?" = "Delete Glucose?";
 
 /* */
 "Meal Presets" = "Meal Presets";
@@ -1655,6 +1661,21 @@ Enact a temp Basal or a temp target */
 /* */
 "Hours X-Axis (6 default)" = "Hours X-Axis (6 default)";
 
+/* */
+"2 hours" = "2 hours";
+
+/* */
+"4 hours" = "4 hours";
+
+/* */
+"6 hours" = "6 hours";
+
+/* */
+"12 hours" = "12 hours";
+
+/* */
+"24 hours" = "24 hours";
+
 /* Average BG = */
 "Average" = "Average";
 

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Temp Targets";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "¿Eliminar carbohidratos?";
+"Delete Carbs?" = "¿Eliminar carbohidratos?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Tratamientos";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Temp Targets";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Delete carbs?";
+"Delete Carbs?" = "Delete Carbs?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Treatments";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Cibles temporaires";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Supprimer les glucides ?";
+"Delete Carbs?" = "Supprimer les glucides ?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Traitements";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Temp Targets";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Delete carbs?";
+"Delete Carbs?" = "Delete Carbs?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Treatments";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Obiettivi Temporanei";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Cancella carboidrati?";
+"Delete Carbs?" = "Cancella carboidrati?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Cancella l'insulina?";
+"Delete Insulin?" = "Cancella l'insulina?";
 
 /* Treatments list */
 "Treatments" = "Trattamenti";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistiche e Vista Iniziale";
 
 /* Alert text */
-"Delete carb equivalents?" = "Cancella i carb equivalenti?";
+"Delete Carb Equivalents?" = "Cancella i carb equivalenti?";
 
 /* */
 "Meal Presets" = "Pasto Predefinito";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Midlertidige mål";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Slette karbohydrater?";
+"Delete Carbs?" = "Slette karbohydrater?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Slette insulin?";
+"Delete Insulin?" = "Slette insulin?";
 
 /* Treatments list */
 "Treatments" = "Behandlinger";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistikk og startskjerm";
 
 /* Alert text */
-"Delete carb equivalents?" = "Slette karboekvivalenter?";
+"Delete Carb Equivalents?" = "Slette karboekvivalenter?";
 
 /* */
 "Meal Presets" = "Forvalg av måltid";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Tijdelijk streefdoel";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Koolhydraten verwijderen?";
+"Delete Carbs?" = "Koolhydraten verwijderen?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Insuline verwijderen?";
+"Delete Insulin?" = "Insuline verwijderen?";
 
 /* Treatments list */
 "Treatments" = "Behandelingen";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistieken en Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Verwijder koolhydraten?";
+"Delete Carb Equivalents?" = "Verwijder koolhydraten?";
 
 /* */
 "Meal Presets" = "Maaltijd voorinstellingen";

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

@@ -578,10 +578,10 @@ Połączono z Nightscout!";
 "Temp Targets" = "Temp Targets";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Delete carbs?";
+"Delete Carbs?" = "Delete Carbs?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Treatments";
@@ -1370,7 +1370,7 @@ Połączono z Nightscout!";
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Alvos Temporários";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Deletar carboidratos?";
+"Delete Carbs?" = "Deletar carboidratos?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Tratamentos";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Temp Targets";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Delete carbs?";
+"Delete Carbs?" = "Delete Carbs?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Treatments";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Временные цели";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Удалить углеводы?";
+"Delete Carbs?" = "Удалить углеводы?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Удалить инсулин?";
+"Delete Insulin?" = "Удалить инсулин?";
 
 /* Treatments list */
 "Treatments" = "События";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Статистика и экран";
 
 /* Alert text */
-"Delete carb equivalents?" = "Удалить эквиваленты углеводов?";
+"Delete Carb Equivalents?" = "Удалить эквиваленты углеводов?";
 
 /* */
 "Meal Presets" = "Шаблоны";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Temp Targets";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Delete carbs?";
+"Delete Carbs?" = "Delete Carbs?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "Treatments";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Målvärden";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Ta bort kolhydrater?";
+"Delete Carbs?" = "Ta bort kolhydrater?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Ta bort insulin?";
+"Delete Insulin?" = "Ta bort insulin?";
 
 /* Treatments list */
 "Treatments" = "Behandlingar";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistik och Diagram";
 
 /* Alert text */
-"Delete carb equivalents?" = "Radera dessa poster?";
+"Delete Carb Equivalents?" = "Radera dessa poster?";
 
 /* */
 "Meal Presets" = "Förval";
@@ -1652,6 +1652,21 @@ Enact a temp Basal or a temp target */
 /* */
 "Hours X-Axis (6 default)" = "Antal timmar att visa för X-axel (6 standard)";
 
+/* */
+"2 hours" = "2 timmar";
+
+/* */
+"4 hours" = "4 timmar";
+
+/* */
+"6 hours" = "6 timmar";
+
+/* */
+"12 hours" = "12 timmar";
+
+/* */
+"24 hours" = "24 timmar";
+
 /* Average BG = */
 "Average" = "Medelvärde";
 

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Geçici Hedefler";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Karbonhidratları sil?";
+"Delete Carbs?" = "Karbonhidratları sil?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "İnsülin silinsin mi?";
+"Delete Insulin?" = "İnsülin silinsin mi?";
 
 /* Treatments list */
 "Treatments" = "Tedaviler";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "Тимчасові цілі";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "Видалити вуглеводи?";
+"Delete Carbs?" = "Видалити вуглеводи?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Видалити інсулін?";
+"Delete Insulin?" = "Видалити інсулін?";
 
 /* Treatments list */
 "Treatments" = "Події";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Статистика та Домашня сторінка";
 
 /* Alert text */
-"Delete carb equivalents?" = "Видалити вуглеводні еквіваленти?";
+"Delete Carb Equivalents?" = "Видалити вуглеводні еквіваленти?";
 
 /* */
 "Meal Presets" = "Попередні Налаштування Їжі";

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

@@ -576,10 +576,10 @@ Enact a temp Basal or a temp target */
 "Temp Targets" = "临时目标";
 
 /* Delete carbs from data table and Nightscout */
-"Delete carbs?" = "删除碳水?";
+"Delete Carbs?" = "删除碳水?";
 
 /* Delete insulin from pump history and Nightscout */
-"Delete insulin?" = "Delete insulin?";
+"Delete Insulin?" = "Delete Insulin?";
 
 /* Treatments list */
 "Treatments" = "治疗";
@@ -1368,7 +1368,7 @@ Enact a temp Basal or a temp target */
 "Statistics and Home View" = "Statistics and Home View";
 
 /* Alert text */
-"Delete carb equivalents?" = "Delete carb equivalents?";
+"Delete Carb Equivalents?" = "Delete Carb Equivalents?";
 
 /* */
 "Meal Presets" = "Meal Presets";

+ 6 - 4
FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift

@@ -152,9 +152,10 @@ extension DataTable {
                 .store(in: &lifetime)
         }
 
-        func deleteGlucose(at index: Int) {
-            let id = glucose[index].id
+        func deleteGlucose(_ glucose: Glucose) {
+            let id = glucose.id
             provider.deleteGlucose(id: id)
+
             let fetchRequest: NSFetchRequest<NSFetchRequestResult>
             fetchRequest = NSFetchRequest(entityName: "Readings")
             fetchRequest.predicate = NSPredicate(format: "id == %@", id)
@@ -171,9 +172,10 @@ extension DataTable {
                     )
                 }
             } catch { /* To do: handle any thrown errors. */ }
+
             // Deletes Manual Glucose
-            if (glucose[index].glucose.type ?? "") == GlucoseType.manual.rawValue {
-                provider.deleteManualGlucose(date: glucose[index].glucose.dateString)
+            if (glucose.glucose.type ?? "") == GlucoseType.manual.rawValue {
+                provider.deleteManualGlucose(date: glucose.glucose.dateString)
             }
         }
 

+ 107 - 92
FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift

@@ -6,11 +6,12 @@ extension DataTable {
     struct RootView: BaseView {
         let resolver: Resolver
         @StateObject var state = StateModel()
+        @State private var isRemoveHistoryItemAlertPresented: Bool = false
+        @State private var alertTitle: String = ""
+        @State private var alertMessage: String = ""
+        @State private var alertTreatmentToDelete: Treatment?
+        @State private var alertGlucoseToDelete: Glucose?
 
-        @State private var isRemoveCarbsAlertPresented = false
-        @State private var removeCarbsAlert: Alert?
-        @State private var isRemoveInsulinAlertPresented = false
-        @State private var removeInsulinAlert: Alert?
         @State private var showExternalInsulin: Bool = false
         @State private var showFutureEntries: Bool = false // default to hide future entries
         @State private var showManualGlucose: Bool = false
@@ -133,7 +134,6 @@ extension DataTable {
                     ForEach(state.glucose) { item in
                         glucoseView(item, isManual: item.glucose)
                     }
-                    .onDelete(perform: deleteGlucose)
                 } else {
                     HStack {
                         Text("No data.")
@@ -185,87 +185,70 @@ extension DataTable {
 
         @ViewBuilder private func treatmentView(_ item: Treatment) -> some View {
             HStack {
-                Image(systemName: "circle.fill").foregroundColor(item.color)
+                if item.type == .bolus || item.type == .carbs {
+                    Image(systemName: "circle.fill").foregroundColor(item.color).padding(.vertical)
+                } else {
+                    Image(systemName: "circle.fill").foregroundColor(item.color)
+                }
                 Text((item.isSMB ?? false) ? "SMB" : item.type.name)
                 Text(item.amountText).foregroundColor(.secondary)
 
                 if let duration = item.durationText {
                     Text(duration).foregroundColor(.secondary)
                 }
+                Spacer()
+                Text(dateFormatter.string(from: item.date))
+                    .moveDisabled(true)
+            }
+            .swipeActions {
+                Button(
+                    "Delete",
+                    systemImage: "trash.fill",
+                    role: .none,
+                    action: {
+                        alertTreatmentToDelete = item
 
-                if item.type == .carbs {
-                    if item.note != "" {
-                        Spacer()
-                        Text(item.note ?? "").foregroundColor(.brown)
-                    }
-                    Spacer()
-                    Image(systemName: "xmark.circle").foregroundColor(.secondary)
-                        .contentShape(Rectangle())
-                        .padding(.vertical)
-                        .onTapGesture {
-                            removeCarbsAlert = Alert(
-                                title: Text("Delete carbs?"),
-                                message: Text(item.amountText),
-                                primaryButton: .destructive(
-                                    Text("Delete"),
-                                    action: {
-                                        state.deleteCarbs(item) }
-                                ),
-                                secondaryButton: .cancel()
-                            )
-                            isRemoveCarbsAlertPresented = true
-                        }
-                        .alert(isPresented: $isRemoveCarbsAlertPresented) {
-                            removeCarbsAlert!
-                        }
-                }
+                        if item.type == .carbs {
+                            alertTitle = "Delete Carbs?"
+                            alertMessage = dateFormatter.string(from: item.date) + ", " + item.amountText
+                        } else if item.type == .fpus {
+                            alertTitle = "Delete Carb Equivalents?"
+                            alertMessage = "All FPUs of the meal will be deleted."
+                        } else {
+                            // item is insulin treatment; item.type == .bolus
+                            alertTitle = "Delete Insulin?"
+                            alertMessage = dateFormatter.string(from: item.date) + ", " + item.amountText
 
-                if item.type == .fpus {
-                    Spacer()
-                    Image(systemName: "xmark.circle").foregroundColor(.secondary)
-                        .contentShape(Rectangle())
-                        .padding(.vertical)
-                        .onTapGesture {
-                            removeCarbsAlert = Alert(
-                                title: Text("Delete carb equivalents?"),
-                                message: Text(""), // Temporary fix. New to fix real amount of carb equivalents later
-                                primaryButton: .destructive(
-                                    Text("Delete"),
-                                    action: { state.deleteCarbs(item) }
-                                ),
-                                secondaryButton: .cancel()
-                            )
-                            isRemoveCarbsAlertPresented = true
-                        }
-                        .alert(isPresented: $isRemoveCarbsAlertPresented) {
-                            removeCarbsAlert!
+                            if item.isSMB ?? false {
+                                // Add text snippet, so that alert message is more descriptive for SMBs
+                                alertMessage += "SMB"
+                            }
                         }
-                }
 
-                if item.type == .bolus {
-                    Spacer()
-                    Image(systemName: "xmark.circle").foregroundColor(.secondary)
-                        .contentShape(Rectangle())
-                        .padding(.vertical)
-                        .onTapGesture {
-                            removeInsulinAlert = Alert(
-                                title: Text("Delete insulin?"),
-                                message: Text(item.amountText),
-                                primaryButton: .destructive(
-                                    Text("Delete"),
-                                    action: { state.deleteInsulin(item) }
-                                ),
-                                secondaryButton: .cancel()
-                            )
-                            isRemoveInsulinAlertPresented = true
-                        }
-                        .alert(isPresented: $isRemoveInsulinAlertPresented) {
-                            removeInsulinAlert!
-                        }
+                        isRemoveHistoryItemAlertPresented = true
+                    }
+                ).tint(.red)
+            }
+            .disabled(item.type == .tempBasal || item.type == .tempTarget || item.type == .resume || item.type == .suspend)
+            .alert(
+                Text(NSLocalizedString(alertTitle, comment: "")),
+                isPresented: $isRemoveHistoryItemAlertPresented
+            ) {
+                Button("Cancel", role: .cancel) {}
+                Button("Delete", role: .destructive) {
+                    guard let treatmentToDelete = alertTreatmentToDelete else {
+                        debug(.default, "Cannot gracefully unwrap alertTreatmentToDelete!")
+                        return
+                    }
+
+                    if treatmentToDelete.type == .carbs || treatmentToDelete.type == .fpus {
+                        state.deleteCarbs(treatmentToDelete)
+                    } else {
+                        state.deleteInsulin(treatmentToDelete)
+                    }
                 }
-                Spacer()
-                Text(dateFormatter.string(from: item.date))
-                    .moveDisabled(true)
+            } message: {
+                Text("\n" + NSLocalizedString(alertMessage, comment: ""))
             }
         }
 
@@ -332,27 +315,59 @@ extension DataTable {
         }
 
         @ViewBuilder private func glucoseView(_ item: Glucose, isManual: BloodGlucose) -> some View {
-            VStack(alignment: .leading, spacing: 4) {
-                HStack {
-                    Text(item.glucose.glucose.map {
-                        glucoseFormatter.string(from: Double(
-                            state.units == .mmolL ? $0.asMmolL : Decimal($0)
-                        ) as NSNumber)!
-                    } ?? "--")
-                    if isManual.type == GlucoseType.manual.rawValue {
-                        Image(systemName: "drop.fill").symbolRenderingMode(.monochrome).foregroundStyle(.red)
-                    } else {
-                        Text(item.glucose.direction?.symbol ?? "--")
+            HStack {
+                Text(item.glucose.glucose.map {
+                    glucoseFormatter.string(from: Double(
+                        state.units == .mmolL ? $0.asMmolL : Decimal($0)
+                    ) as NSNumber)!
+                } ?? "--")
+                if isManual.type == GlucoseType.manual.rawValue {
+                    Image(systemName: "drop.fill").symbolRenderingMode(.monochrome).foregroundStyle(.red)
+                } else {
+                    Text(item.glucose.direction?.symbol ?? "--")
+                }
+                Spacer()
+
+                Text(dateFormatter.string(from: item.glucose.dateString))
+            }
+            .swipeActions {
+                Button(
+                    "Delete",
+                    systemImage: "trash.fill",
+                    role: .none,
+                    action: {
+                        alertGlucoseToDelete = item
+
+                        let valueText = glucoseFormatter.string(from: Double(
+                            state.units == .mmolL ? Double(item.glucose.value.asMmolL) : item.glucose.value
+                        ) as NSNumber)! + " " + state.units.rawValue
+
+                        alertTitle = "Delete Glucose?"
+                        alertMessage = dateFormatter.string(from: item.glucose.dateString) + ", " + valueText
+
+                        isRemoveHistoryItemAlertPresented = true
+                    }
+                ).tint(.red)
+            }
+            .alert(
+                Text(NSLocalizedString(alertTitle, comment: "")),
+                isPresented: $isRemoveHistoryItemAlertPresented
+            ) {
+                Button("Cancel", role: .cancel) {}
+                Button("Delete", role: .destructive) {
+                    // gracefully unwrap value here.
+                    // value cannot ever really be nil because it is an existing(!) table entry
+                    // but just to be sure.
+                    guard let glucoseToDelete = alertGlucoseToDelete else {
+                        print("Cannot gracefully unwrap alertTreatmentToDelete!")
+                        return
                     }
-                    Spacer()
 
-                    Text(dateFormatter.string(from: item.glucose.dateString))
+                    state.deleteGlucose(glucoseToDelete)
                 }
+            } message: {
+                Text("\n" + NSLocalizedString(alertMessage, comment: ""))
             }
         }
-
-        private func deleteGlucose(at offsets: IndexSet) {
-            state.deleteGlucose(at: offsets[offsets.startIndex])
-        }
     }
 }

+ 11 - 4
FreeAPS/Sources/Modules/Home/HomeStateModel.swift

@@ -56,11 +56,11 @@ extension Home {
         @Published var lowGlucose: Decimal = 4 / 0.0555
         @Published var highGlucose: Decimal = 10 / 0.0555
         @Published var overrideUnit: Bool = false
-        @Published var screenHours: Int = 6
         @Published var displayXgridLines: Bool = false
         @Published var displayYgridLines: Bool = false
         @Published var thresholdLines: Bool = false
         @Published var timeZone: TimeZone?
+        @Published var hours: Int16 = 6
 
         enum Scale: Int, CaseIterable, Identifiable {
             case one = 1
@@ -73,7 +73,7 @@ extension Home {
 
         @Published var scale: Scale = .six {
             didSet {
-                screenHours = calculateScreenHours(scale: scale)
+                hours = Int16(calculateScreenHours(scale: scale))
             }
         }
 
@@ -110,7 +110,6 @@ extension Home {
             lowGlucose = settingsManager.settings.low
             highGlucose = settingsManager.settings.high
             overrideUnit = settingsManager.settings.overrideHbA1cUnit
-            screenHours = settingsManager.settings.hours
             displayXgridLines = settingsManager.settings.xGridLines
             displayYgridLines = settingsManager.settings.yGridLines
             thresholdLines = settingsManager.settings.rulerMarks
@@ -248,6 +247,15 @@ extension Home {
             }
         }
 
+        func saveSettings() {
+            coredataContext.perform {
+                let settings = UXSettings(context: self.coredataContext)
+                settings.hours = self.hours
+                settings.date = Date.now
+                try? self.coredataContext.save()
+            }
+        }
+
         private func setupGlucose() {
             DispatchQueue.main.async { [weak self] in
                 guard let self = self else { return }
@@ -457,7 +465,6 @@ extension Home.StateModel:
         lowGlucose = settingsManager.settings.low
         highGlucose = settingsManager.settings.high
         overrideUnit = settingsManager.settings.overrideHbA1cUnit
-        screenHours = settingsManager.settings.hours
         displayXgridLines = settingsManager.settings.xGridLines
         displayYgridLines = settingsManager.settings.yGridLines
         thresholdLines = settingsManager.settings.rulerMarks

+ 20 - 29
FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

@@ -72,7 +72,7 @@ struct MainChartView: View {
     @Binding var smooth: Bool
     @Binding var highGlucose: Decimal
     @Binding var lowGlucose: Decimal
-    @Binding var screenHours: Int
+    @Binding var screenHours: Int16
     @Binding var displayXgridLines: Bool
     @Binding var displayYgridLines: Bool
     @Binding var thresholdLines: Bool
@@ -99,8 +99,6 @@ struct MainChartView: View {
     @State private var offset: CGFloat = 0
     @State private var cachedMaxBasalRate: Decimal?
 
-    @State var state: Home.StateModel
-
     private let calculationQueue = DispatchQueue(label: "MainChartView.calculationQueue")
 
     private var dateFormatter: DateFormatter {
@@ -197,9 +195,10 @@ struct MainChartView: View {
                         .onChange(of: tempBasals) { _ in
                             scroll.scrollTo(Config.endID, anchor: .trailing)
                         }
-                        .onChange(of: state.scale) { _ in
+                        .onChange(of: screenHours) { _ in
                             scroll.scrollTo(Config.endID, anchor: .trailing)
                         }
+
                         .onAppear {
                             // add trigger to the end of main queue
                             DispatchQueue.main.async {
@@ -274,7 +273,7 @@ struct MainChartView: View {
         .scaleEffect(x: 1, y: -1)
         .frame(width: fullGlucoseWidth(viewWidth: fullSize.width) + additionalWidth(viewWidth: fullSize.width))
         .frame(maxHeight: Config.basalHeight)
-        .background(colorScheme == .dark ? Color.black.opacity(0.8) : Color.clear)
+        .background(Color.secondary.opacity(0.1))
         .onChange(of: tempBasals) { _ in
             calculateBasalPoints(fullSize: fullSize)
         }
@@ -320,14 +319,11 @@ struct MainChartView: View {
         return ZStack {
             Path { path in
                 for hour in 0 ..< hours + hours {
-                    if screenHours < 12 || hour % 2 == 0 {
-                        // only show every second line if screenHours is too big
-                        let x = firstHourPosition(viewWidth: fullSize.width) +
-                            oneSecondStep(viewWidth: fullSize.width) *
-                            CGFloat(hour) * CGFloat(1.hours.timeInterval)
-                        path.move(to: CGPoint(x: x, y: 0))
-                        path.addLine(to: CGPoint(x: x, y: fullSize.height - 20))
-                    }
+                    let x = firstHourPosition(viewWidth: fullSize.width) +
+                        oneSecondStep(viewWidth: fullSize.width) *
+                        CGFloat(hour) * CGFloat(1.hours.timeInterval)
+                    path.move(to: CGPoint(x: x, y: 0))
+                    path.addLine(to: CGPoint(x: x, y: fullSize.height - 20))
                 }
             }
             .stroke(useColour, lineWidth: 0.15)
@@ -349,20 +345,15 @@ struct MainChartView: View {
         return ZStack {
             // X time labels
             ForEach(0 ..< hours + hours) { hour in
-                if screenHours >= 12 && hour % 2 == 1 {
-                    // only show every second time label if screenHours is too big
-                    EmptyView()
-                } else {
-                    Text(format.string(from: firstHourDate().addingTimeInterval(hour.hours.timeInterval)))
-                        .font(.caption)
-                        .position(
-                            x: firstHourPosition(viewWidth: fullSize.width) +
-                                oneSecondStep(viewWidth: fullSize.width) *
-                                CGFloat(hour) * CGFloat(1.hours.timeInterval),
-                            y: 10.0
-                        )
-                        .foregroundColor(.secondary)
-                }
+                Text(format.string(from: firstHourDate().addingTimeInterval(hour.hours.timeInterval)))
+                    .font(.caption)
+                    .position(
+                        x: firstHourPosition(viewWidth: fullSize.width) +
+                            oneSecondStep(viewWidth: fullSize.width) *
+                            CGFloat(hour) * CGFloat(1.hours.timeInterval),
+                        y: 10.0
+                    )
+                    .foregroundColor(.secondary)
             }
         }.frame(maxHeight: 20)
     }
@@ -832,8 +823,8 @@ extension MainChartView {
                 path.addLine(to: CGPoint(x: 0, y: Config.basalHeight))
             }
             let adjustForOptionalExtraHours = screenHours > 12 ? screenHours - 12 : 0
-            let endDateTime = dayAgoTime + min(max(screenHours - adjustForOptionalExtraHours, 12), 24).hours
-                .timeInterval + min(max(screenHours - adjustForOptionalExtraHours, 12), 24).hours
+            let endDateTime = dayAgoTime + min(max(Int(screenHours - adjustForOptionalExtraHours), 12), 24).hours
+                .timeInterval + min(max(Int(screenHours - adjustForOptionalExtraHours), 12), 24).hours
                 .timeInterval
             let autotunedBasalPoints = findRegularBasalPoints(
                 timeBegin: dayAgoTime,

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

@@ -7,6 +7,7 @@ struct PumpView: View {
     @Binding var expiresAtDate: Date?
     @Binding var timerDate: Date
     @Binding var boluses: [PumpHistoryEvent]
+    @Binding var screenHours: Int16
 
     @State var state: Home.StateModel
 
@@ -102,17 +103,19 @@ struct PumpView: View {
             }
         }
     }
-    
-    //MARK: WORKS....BUT MAYBE TIMEZONE PROBLEMS COULD OCCUR
-    //DEFINETELY SOMETHING FOR OUR TIMEZONE EXPERT.....
+
+    // MARK: WORKS....BUT MAYBE TIMEZONE PROBLEMS COULD OCCUR
+
+    // DEFINETELY SOMETHING FOR OUR TIMEZONE EXPERT.....
 
     func calculateTINS() -> String {
         let date = Date()
         let calendar = Calendar.current
-        let offset = state.scale
-        
+        let offset = screenHours
+
         var offsetComponents = DateComponents()
-        offsetComponents.hour = -offset.rawValue
+//        offsetComponents.hour = -offset.rawValue
+        offsetComponents.hour = -Int(offset)
 
         let startTime = calendar.date(byAdding: offsetComponents, to: date)!
         print("******************")

+ 76 - 95
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -12,6 +12,24 @@ extension Home {
         @State var isStatusPopupPresented = false
         @State var showCancelAlert = false
 
+        struct Buttons: Identifiable {
+            let label: String
+            let number: String
+            var active: Bool
+            let hours: Int16
+            var id: String { label }
+        }
+
+        @State var timeButtons: [Buttons] = [
+            Buttons(label: "2 hours", number: "2", active: false, hours: 2),
+            Buttons(label: "4 hours", number: "4", active: false, hours: 4),
+            Buttons(label: "6 hours", number: "6", active: true, hours: 6),
+            Buttons(label: "12 hours", number: "12", active: false, hours: 12),
+            Buttons(label: "24 hours", number: "24", active: false, hours: 24)
+        ]
+
+        let buttonFont = Font.custom("TimeButtonFont", size: 14)
+
         @Environment(\.managedObjectContext) var moc
         @Environment(\.colorScheme) var colorScheme
 
@@ -37,6 +55,11 @@ extension Home {
             sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)]
         ) var enactedSliderTT: FetchedResults<TempTargetsSlider>
 
+        @FetchRequest(
+            entity: UXSettings.entity(),
+            sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)]
+        ) var fetchedSettings: FetchedResults<UXSettings>
+
         private var numberFormatter: NumberFormatter {
             let formatter = NumberFormatter()
             formatter.numberStyle = .decimal
@@ -167,6 +190,7 @@ extension Home {
                 expiresAtDate: $state.pumpExpiresAtDate,
                 timerDate: $state.timerDate,
                 boluses: $state.boluses,
+                screenHours: $state.hours,
                 state: state
             )
             .onTapGesture {
@@ -388,6 +412,26 @@ extension Home {
             }
         }
 
+        var timeInterval: some View {
+            HStack(alignment: .center) {
+                let saveButton = UXSettings(context: moc)
+                ForEach(timeButtons) { button in
+                    Text(button.active ? NSLocalizedString(button.label, comment: "") : button.number).onTapGesture {
+                        let index = timeButtons.firstIndex(where: { $0.label == button.label }) ?? 0
+                        highlightButtons(index, onAppear: false)
+                        saveButton.hours = button.hours
+                        saveButton.date = Date.now
+                        try? moc.save()
+                        state.hours = button.hours
+                    }
+                    .foregroundStyle(button.active ? .primary : .secondary)
+                    .frame(maxHeight: 30).padding(.horizontal, 8)
+                    .background(button.active ? Color(.systemGray5) : .clear, in: .capsule(style: .circular))
+                }
+            }
+            .font(buttonFont)
+        }
+
         var mainChart: some View {
             ZStack {
                 if state.animatedBackground {
@@ -415,108 +459,16 @@ extension Home {
                     smooth: $state.smooth,
                     highGlucose: $state.highGlucose,
                     lowGlucose: $state.lowGlucose,
-                    screenHours: $state.screenHours,
+                    screenHours: $state.hours,
                     displayXgridLines: $state.displayXgridLines,
                     displayYgridLines: $state.displayYgridLines,
-                    thresholdLines: $state.thresholdLines,
-                    state: state
+                    thresholdLines: $state.thresholdLines
                 )
             }
             .padding(.bottom)
             .modal(for: .dataTable, from: self)
         }
 
-        // MARK: PICKER IN SEGEMENTED STYLE TO CHOOSE THE X AXIS SCALE OF THE GRAPH
-
-        @ViewBuilder private func pickerPanel(_: GeometryProxy) -> some View {
-//            HStack {
-//                Picker("Scale", selection: $state.scale) {
-//                    ForEach(Home.StateModel.Scale.allCases) { scale in
-//                        Text("\(scale.rawValue)h").tag(Optional(scale))
-//                    }
-//                }
-//                .pickerStyle(.segmented)
-//                .background(Color.clear)
-//                .frame(width: UIScreen.main.bounds.width / 1.5, height: 40, alignment: .center)
-//            }
-//            .padding(.vertical, 1)
-            HStack(spacing: 0) {
-                ForEach(Home.StateModel.Scale.allCases, id: \.self) { scale in
-                    Button(action: {
-                        state.scale = scale
-                    }) {
-                        Text(scale == state.scale ? "\(scale.rawValue) hours" : "\(scale.rawValue)")
-                            .font(.footnote)
-                            .foregroundColor(
-                                scale == state.scale ? (colorScheme == .dark ? Color.white : Color.black) : Color.secondary
-                            )
-                            .padding(.vertical, 6).padding(.horizontal, scale == state.scale ? 15 : 10)
-                            .background(
-                                scale == state
-                                    .scale ?
-                                    // RGB(10, 30, 50)
-                                    (colorScheme == .dark ? Color(red: 0.039, green: 0.117, blue: 0.196) : Color.white) :
-                                    Color
-                                    .clear
-                            )
-                            .cornerRadius(20)
-                    }
-                    .shadow(
-                        color: colorScheme == .dark ? Color(red: 0.02745098039, green: 0.1098039216, blue: 0.1411764706) : Color
-                            .black.opacity(0.33),
-                        radius: 3
-                    )
-                }
-            }
-            .padding()
-            .background(Color.clear)
-        }
-
-//        @ViewBuilder private func profiles(_: GeometryProxy) -> some View {
-//            let colour: Color = colorScheme == .dark ? .black : .white
-//            let colourRectangle: Color = colorScheme == .dark ? .gray.opacity(0.1) : .white
-//
-//            ZStack {
-//                Rectangle()
-        ////                    .fill(Color.gray.opacity(0.3))
-//                    .fill(colourRectangle)
-//                    .frame(maxHeight: 40)
-//                    .cornerRadius(15)
-//                    .padding([.leading, .trailing], 10)
-//                let cancel = fetchedPercent.first?.enabled ?? false
-//                HStack(spacing: cancel ? 25 : 15) {
-//                    Text(selectedProfile().name).foregroundColor(.secondary)
-//                    if cancel, selectedProfile().isOn {
-//                        Button { showCancelAlert.toggle() }
-//                        label: {
-//                            Image(systemName: "xmark")
-//                                .foregroundStyle(.secondary)
-//                        }
-//                    }
-//                    Button { state.showModal(for: .overrideProfilesConfig) }
-//                    label: {
-//                        Image(systemName: "person.3.sequence.fill")
-//                            .symbolRenderingMode(.palette)
-//                            .foregroundStyle(
-//                                !(fetchedPercent.first?.enabled ?? false) ? .green : .cyan,
-//                                !(fetchedPercent.first?.enabled ?? false) ? .cyan : .green,
-//                                .purple
-//                            )
-//                    }
-//                }
-//            }
-//            .alert(
-//                "Return to Normal?", isPresented: $showCancelAlert,
-//                actions: {
-//                    Button("No", role: .cancel) {}
-//                    Button("Yes", role: .destructive) {
-//                        state.cancelProfile()
-//                    }
-//                }, message: { Text("This will change settings back to your normal profile.") }
-//            )
-//            Rectangle().fill(colour).frame(maxHeight: 1)
-//        }
-
         private func selectedProfile() -> (name: String, isOn: Bool) {
             var profileString = ""
             var display: Bool = false
@@ -543,6 +495,31 @@ extension Home {
             return (name: profileString, isOn: display)
         }
 
+        func highlightButtons(_ int: Int?, onAppear: Bool) {
+            var index = 0
+            if let integer = int, !onAppear {
+                repeat {
+                    if index == integer {
+                        timeButtons[index].active = true
+                    } else {
+                        timeButtons[index].active = false
+                    }
+                    index += 1
+                } while index < timeButtons.count
+            } else if onAppear {
+                let i = timeButtons.firstIndex(where: { $0.hours == (fetchedSettings.first?.hours ?? 6) }) ?? 2
+                index = 0
+                repeat {
+                    if index == i {
+                        timeButtons[index].active = true
+                    } else {
+                        timeButtons[index].active = false
+                    }
+                    index += 1
+                } while index < timeButtons.count
+            }
+        }
+
         @ViewBuilder private func bottomPanel(_: GeometryProxy) -> some View {
             let colorRectangle: Color = colorScheme == .dark ? Color.black.opacity(0.8) : Color.white
             let colorIcon: Color = (colorScheme == .dark ? Color.white : Color.black).opacity(0.9)
@@ -716,7 +693,11 @@ extension Home {
                         .padding(.horizontal, 10)
                         .frame(maxHeight: UIScreen.main.bounds.height / 2.2)
 
-                    pickerPanel(geo)
+                    Spacer()
+
+                    timeInterval
+
+                    Spacer()
 
                     legendPanel
 

+ 0 - 8
FreeAPS/Sources/Modules/StatConfig/StatConfigStateModel.swift

@@ -5,7 +5,6 @@ extension StatConfig {
         @Published var overrideHbA1cUnit = false
         @Published var low: Decimal = 4 / 0.0555
         @Published var high: Decimal = 10 / 0.0555
-        @Published var hours: Decimal = 6
         @Published var xGridLines = false
         @Published var yGridLines: Bool = false
         @Published var oneDimensionalGraph = false
@@ -41,13 +40,6 @@ extension StatConfig {
                 guard units == .mmolL else { return $0 }
                 return $0.asMgdL
             })
-
-            subscribeSetting(\.hours, on: $hours.map(Int.init), initial: {
-                let value = max(min($0, 24), 2)
-                hours = Decimal(value)
-            }, map: {
-                $0
-            })
         }
     }
 }

+ 1 - 6
FreeAPS/Sources/Modules/StatConfig/View/StatConfigRootView.swift

@@ -31,12 +31,6 @@ extension StatConfig {
                     Toggle("Display Chart Y - Grid lines", isOn: $state.yGridLines)
                     Toggle("Display Chart Threshold lines for Low and High", isOn: $state.rulerMarks)
                     Toggle("Standing / Laying TIR Chart", isOn: $state.oneDimensionalGraph)
-                    HStack {
-                        Text("Hours X-Axis (6 default)")
-                        Spacer()
-                        DecimalTextField("6", value: $state.hours, formatter: carbsFormatter)
-                        Text("hours").foregroundColor(.secondary)
-                    }
                 } header: { Text("Home Chart settings ") }
 
                 Section {
@@ -64,6 +58,7 @@ extension StatConfig {
             .onAppear(perform: configureView)
             .navigationBarTitle("UI/UX")
             .navigationBarTitleDisplayMode(.automatic)
+            .navigationBarItems(trailing: Button("Close", action: state.hideModal))
         }
     }
 }