From e4c92c1863a582be9407d58b36ac89bacc75113d Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 31 Jul 2019 22:42:20 +0200 Subject: [PATCH 01/44] Bump 2.4-alpha2 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3335387f40..14e14bc8be 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,7 +111,7 @@ android { targetSdkVersion 28 multiDexEnabled true versionCode 1500 - version "2.4-dev" + version "2.4-alpha2" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' From d827c10161c621664f5041b3ee586b8fe76a7707 Mon Sep 17 00:00:00 2001 From: Paulus Date: Thu, 1 Aug 2019 00:47:57 +0200 Subject: [PATCH 02/44] CR #1903 initial commit --- .../activities/HistoryBrowseActivity.java | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java index a076608ed2..38e89a0f9b 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java @@ -2,9 +2,6 @@ package info.nightscout.androidaps.activities; import android.os.Bundle; import android.os.SystemClock; -import androidx.core.content.res.ResourcesCompat; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.PopupMenu; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.view.Menu; @@ -15,6 +12,10 @@ import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.TextView; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.PopupMenu; +import androidx.core.content.res.ResourcesCompat; + import com.jjoe64.graphview.GraphView; import com.squareup.otto.Subscribe; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; @@ -36,13 +37,14 @@ import info.nightscout.androidaps.events.EventCustomCalculationFinished; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress; import info.nightscout.androidaps.plugins.general.overview.OverviewFragment; import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin; import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress; import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.T; public class HistoryBrowseActivity extends AppCompatActivity { @@ -248,6 +250,15 @@ public class HistoryBrowseActivity extends AppCompatActivity { final boolean showPrediction = false; + showBasal = SP.getBoolean("hist_showbasals", true); + showIob = SP.getBoolean("hist_showiob", true); + showCob = SP.getBoolean("hist_showcob", true); + showDev = SP.getBoolean("hist_showdeviations", false); + showRat = SP.getBoolean("hist_showratios", false); + showActPrim = SP.getBoolean("hist_showactivityprimary", false); + showActSec = SP.getBoolean("hist_showactivitysecondary", false); + showDevslope = SP.getBoolean("hist_showdevslope", false); + int hoursToFetch; final long toTime; final long fromTime; @@ -453,21 +464,21 @@ public class HistoryBrowseActivity extends AppCompatActivity { popup.setOnMenuItemClickListener(item1 -> { if (item1.getItemId() == OverviewFragment.CHARTTYPE.BAS.ordinal()) { - showBasal = !item1.isChecked(); + SP.putBoolean("hist_showbasals", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.IOB.ordinal()) { - showIob = !item1.isChecked(); + SP.putBoolean("hist_showiob", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.COB.ordinal()) { - showCob = !item1.isChecked(); + SP.putBoolean("hist_showcob", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEV.ordinal()) { - showDev = !item1.isChecked(); + SP.putBoolean("hist_showdeviations", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) { - showRat = !item1.isChecked(); + SP.putBoolean("hist_showratios", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTPRIM.ordinal()) { - showActPrim = !item1.isChecked(); + SP.putBoolean("hist_showactivityprimary", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTSEC.ordinal()) { - showActSec = !item1.isChecked(); + SP.putBoolean("hist_showactivitysecondary", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) { - showDevslope = !item1.isChecked(); + SP.putBoolean("hist_showdevslope", !item1.isChecked()); } updateGUI("onGraphCheckboxesCheckedChanged"); return true; From 2f3a2116fb264776eaafe32e674457301b4da312 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 21 Aug 2019 11:08:23 +0200 Subject: [PATCH 03/44] gradle update to 3.5.0 --- app/build.gradle | 10 +++++----- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0db2e1f986..316c7cf77d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -54,7 +54,7 @@ def generateGitBuild = { -> } def generateGitRemote = { -> - StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder = new StringBuilder() try { def stdout = new ByteArrayOutputStream() exec { @@ -70,7 +70,7 @@ def generateGitRemote = { -> } def generateDate = { -> - StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder = new StringBuilder() stringBuilder.append((new Date()).format('yyyy.MM.dd-HH:mm')) return stringBuilder.toString() } @@ -80,7 +80,7 @@ def isMaster = { -> } def allCommited = { -> - StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder = new StringBuilder() try { def stdout = new ByteArrayOutputStream() exec { @@ -90,7 +90,7 @@ def allCommited = { -> String commitObject = stdout.toString().trim() stringBuilder.append(commitObject) } catch (ignored) { - return false; // NoGitSystemAvailable + return false // NoGitSystemAvailable } return stringBuilder.toString().isEmpty() @@ -225,7 +225,7 @@ dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.google.android.gms:play-services-wearable:17.0.0' - implementation 'com.google.firebase:firebase-core:17.0.1' + implementation 'com.google.firebase:firebase-core:17.1.0' implementation("com.crashlytics.sdk.android:crashlytics:2.9.9@aar") { transitive = true; } diff --git a/build.gradle b/build.gradle index 3e31750d82..6513ece66e 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { maven { url 'https://maven.fabric.io/public' } } dependencies { - classpath 'com.android.tools.build:gradle:3.4.2' + classpath 'com.android.tools.build:gradle:3.5.0' classpath 'com.google.gms:google-services:4.3.0' classpath 'io.fabric.tools:gradle:1.31.0' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 219a2e077c..008330001c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Apr 02 11:30:12 CEST 2018 +#Wed Aug 21 10:14:00 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip From e0421b509c81a33f4a8a33741e8efafd7651eb07 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 21 Aug 2019 17:41:54 +0200 Subject: [PATCH 04/44] LocationService: invoke startForeground in onCreate(). --- .../info/nightscout/androidaps/services/LocationService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/info/nightscout/androidaps/services/LocationService.java b/app/src/main/java/info/nightscout/androidaps/services/LocationService.java index feec4dcab8..485ad1823a 100644 --- a/app/src/main/java/info/nightscout/androidaps/services/LocationService.java +++ b/app/src/main/java/info/nightscout/androidaps/services/LocationService.java @@ -86,6 +86,8 @@ public class LocationService extends Service { @Override public void onCreate() { + super.onCreate(); + startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().updateNotification()); if (L.isEnabled(L.LOCATION)) log.debug("onCreate"); From 450a25c3b847c3eea1a2c607efe17b52b891643d Mon Sep 17 00:00:00 2001 From: Brian Quinion Date: Wed, 21 Aug 2019 17:38:01 +0100 Subject: [PATCH 05/44] Allow for Battery Optimization failing on some platforms --- .../setupwizard/SetupWizardActivity.java | 2 +- .../androidaps/utils/AndroidPermission.java | 36 +++++++++++++++---- app/src/main/res/values/strings.xml | 2 ++ 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java index 3064228fd3..f998b343a2 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java @@ -226,7 +226,7 @@ public class SetupWizardActivity extends NoSplashAppCompatActivity { } @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == AndroidPermission.CASE_BATTERY) updateButtons(); diff --git a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java index 7963ae0545..42f24dff69 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java @@ -3,7 +3,9 @@ package info.nightscout.androidaps.utils; import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; @@ -11,6 +13,7 @@ import android.os.Build; import android.os.PowerManager; import android.provider.Settings; +import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; @@ -45,10 +48,26 @@ public class AndroidPermission { ActivityCompat.requestPermissions(activity, permission, requestCode); } if (testBattery) { - Intent i = new Intent(); - i.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); - i.setData(Uri.parse("package:" + activity.getPackageName())); - activity.startActivityForResult(i, CASE_BATTERY); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + try { + Intent i = new Intent(); + i.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + i.setData(Uri.parse("package:" + activity.getPackageName())); + activity.startActivityForResult(i, CASE_BATTERY); + } catch (ActivityNotFoundException e) { + SP.putBoolean(R.string.key_permission_battery_optimization_failed, true); + + AlertDialog.Builder alert = new AlertDialog.Builder(activity); + alert.setMessage(R.string.alert_dialog_permission_battery_optimization_failed); + alert.setPositiveButton(R.string.ok, null); + alert.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + activity.recreate(); + } + }); + alert.show(); + } } } @@ -60,9 +79,12 @@ public class AndroidPermission { public static boolean permissionNotGranted(Context context, String permission) { boolean selfCheck = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; if (permission.equals(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) { - PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - String packageName = context.getPackageName(); - selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + && !SP.getBoolean(R.string.key_permission_battery_optimization_failed, false)) { + PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + String packageName = context.getPackageName(); + selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName); + } } return !selfCheck; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2029c7023d..6a77b5acf7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -38,6 +38,8 @@ DanaR Bluetooth device Always use basal absolute values Please reboot your phone or restart AndroidAPS from the System Settings \notherwise Android APS will not have logging (important to track and verify that the algorithms are working correctly)! + key_permission_battery_optimization_failed + This device does not appear to support battery optimization whitelisting - you may experience performance issues. Some buttons to quickly access common features Enter advanced log book entries. From d0335e56fa37ea3d7e4589d96840fedc30387df7 Mon Sep 17 00:00:00 2001 From: Brian Quinion Date: Wed, 21 Aug 2019 17:45:31 +0100 Subject: [PATCH 06/44] Allow for Battery Optimization failing on some platforms --- .../nightscout/androidaps/setupwizard/SetupWizardActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java index f998b343a2..3064228fd3 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java @@ -226,7 +226,7 @@ public class SetupWizardActivity extends NoSplashAppCompatActivity { } @Override - public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == AndroidPermission.CASE_BATTERY) updateButtons(); From 2384573831aa09dc39e360278fea656ce7a8ac2f Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 21 Aug 2019 20:41:29 +0100 Subject: [PATCH 07/44] Fix for fill canula double bolus --- .../androidaps/plugins/treatments/TreatmentsPlugin.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java index a9284dd366..1f1e03ec9f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java @@ -294,14 +294,19 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } + /** + * Returns all Treatments after specified timestamp. Also returns invalid entries (required to + * map "Fill Canulla" entries to history (and not to add double bolus for it) + * + * @param fromTimestamp + * @return + */ @Override public List getTreatmentsFromHistoryAfterTimestamp(long fromTimestamp) { List in5minback = new ArrayList<>(); long time = System.currentTimeMillis(); synchronized (treatments) { for (Treatment t : treatments) { - if (!t.isValid) - continue; if (t.date <= time && t.date >= fromTimestamp) in5minback.add(t); } From 86fa8199b6a2f4eb7c9edcebfb7bc83ffb929c28 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 22 Aug 2019 10:41:06 +0200 Subject: [PATCH 08/44] New Crowdin translations (#1973) * New translations strings.xml (French) * New translations strings.xml (Greek) --- app/src/main/res/values-el-rGR/strings.xml | 3 +-- app/src/main/res/values-fr-rFR/strings.xml | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index 68e5bf76ed..13e36d84ae 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -1175,7 +1175,7 @@ Γλυκόζη δεν είναι διαθέσιμη Γλυκόζη %1$s %2$.0f %3$s Γλυκόζη %1$s %2$.1f %3$s - Προφίλ % %1$s %2$d + Προφίλ %% %1$s %2$d ΙΟΒ %1$s %2$.1f Και ή @@ -1238,7 +1238,6 @@ παλιά έκδοση πολύ παλιά έκδοση Νέα έκδοση για τουλάχιστον %1$d ημέρες διαθέσιμη! Επιστροφή σε LGS μετά από 60 ημέρες, το κύκλωμα θα απενεργοποιηθεί μετά από 90 ημέρες - Γραφική κλίμακα δραστηριότητας ινσουλίνης [U/min] 2ώρες %1$.2fU Εφαρμογή Dexcom (τροποποιημένη) diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml index fa94aa359b..30ba290c97 100644 --- a/app/src/main/res/values-fr-rFR/strings.xml +++ b/app/src/main/res/values-fr-rFR/strings.xml @@ -1179,7 +1179,7 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S La glycémie n\'est pas disponible Glycémie %1$s %2$.0f %3$s Glycémie %1$s %2$.1f %3$s - Profil % %1$s %2$d + Profil %% %1$s %2$d IA %1$s %2$.1f Et Ou @@ -1250,7 +1250,6 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S ancienne version très ancienne version Une nouvelle version est disponible depuis au moins %1$d jours ! Retour au traitement par pompe assistée par capteur (Arrêt par Glycémie Basse (AGB), Low Glucose Suspend (LGS) ) après 60 jours et la Boucle sera désactivée après 90 jours - Courbe de l\'activité de l\'insuline [U/min] 2 h %1$.2fU App Dexcom (patchée) @@ -1415,6 +1414,7 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S Impossible d\'annuler le DBT (TBR) actuel. Arrêt de l\'opération. Le nouveau profil a échoué car le taux basal suivant est trop élevé : %1$s Le Bolus n\'a pas pu être délivré. + Le Bolus n\'a pas pu être délivré, car la quantité d\'insuline disponible (%1$.2f) est inférieure à celle requise (%2$.2f). DBT n\'a pas pu être défini. Impossible d\'annuler le DBT actuel. Le profil Basal n\'a pas pu être défini. From fb6bcfdccd42fb7991a7a0a226ab03b5607fdee6 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 22 Aug 2019 11:12:15 +0200 Subject: [PATCH 09/44] Log an uncaught exception before it crashes the app. --- app/src/main/java/info/nightscout/androidaps/MainApp.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index f539f2e33f..f2edd23882 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -139,6 +139,8 @@ public class MainApp extends Application { sConstraintsChecker = new ConstraintChecker(); sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class); + Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> log.error("Uncaught exception crashing app", ex)); + try { if (FabricPrivacy.fabricEnabled()) { Fabric.with(this, new Crashlytics()); From 91bd2c5b4f0debd9afa83ca4b3d39417ea18f192 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 22 Aug 2019 11:12:15 +0200 Subject: [PATCH 10/44] Log an uncaught exception before it crashes the app. According to https://fabric.io/kits/android/crashlytics/features (Step 3, 2nd paragraph), registering an UncaughtExceptionHandler before Fabric is set up does not interfere with Fabric. --- app/src/main/java/info/nightscout/androidaps/MainApp.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index f539f2e33f..f2edd23882 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -139,6 +139,8 @@ public class MainApp extends Application { sConstraintsChecker = new ConstraintChecker(); sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class); + Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> log.error("Uncaught exception crashing app", ex)); + try { if (FabricPrivacy.fabricEnabled()) { Fabric.with(this, new Crashlytics()); From 75be27485cf41aedf7a469a303dc07244fa3555d Mon Sep 17 00:00:00 2001 From: Brian Quinion Date: Thu, 22 Aug 2019 10:29:13 +0100 Subject: [PATCH 11/44] Typo in battery optimization code --- .../java/info/nightscout/androidaps/utils/AndroidPermission.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java index 42f24dff69..3a9d8909b3 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java @@ -67,6 +67,7 @@ public class AndroidPermission { } }); alert.show(); + } } } } From d414b9b6511bdf9f03ef73f68bbe103d7f8e10b6 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 22 Aug 2019 20:33:18 +0200 Subject: [PATCH 12/44] fixed TimeListEdit when time is localized, larger add/remove buttons --- .../androidaps/utils/TimeListEdit.java | 182 +++++++++--------- .../main/res/layout/timelistedit_element.xml | 8 +- 2 files changed, 94 insertions(+), 96 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java b/app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java index 6271ee95fa..436043fd36 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java @@ -1,9 +1,6 @@ package info.nightscout.androidaps.utils; import android.content.Context; -import android.os.Handler; -import androidx.core.content.ContextCompat; -import androidx.core.widget.TextViewCompat; import android.text.Editable; import android.text.TextWatcher; import android.view.Gravity; @@ -15,6 +12,10 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.core.widget.TextViewCompat; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -24,6 +25,7 @@ import org.slf4j.LoggerFactory; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -77,8 +79,7 @@ public class TimeListEdit { } private void buildView() { - layout = (LinearLayout) view.findViewById(resLayoutId); - layout.removeAllViews(); + layout = view.findViewById(resLayoutId); textlabel = new TextView(context); textlabel.setText(label); @@ -96,72 +97,63 @@ public class TimeListEdit { } // last "plus" to append new interval + float factor = layout.getContext().getResources().getDisplayMetrics().density; finalAdd = new ImageView(context); finalAdd.setImageResource(R.drawable.add); - LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); + LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams((int) (35d * factor), (int) (35 * factor)); illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom); illp.gravity = Gravity.CENTER; layout.addView(finalAdd); finalAdd.setLayoutParams(illp); - finalAdd.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - addItem(itemsCount(), itemsCount() > 0 ? secondFromMidnight(itemsCount() - 1) + ONEHOURINSECONDS : 0, 0, 0); - callSave(); - log(); - fillView(); - } + finalAdd.setOnClickListener(view -> { + addItem(itemsCount(), itemsCount() > 0 ? secondFromMidnight(itemsCount() - 1) + ONEHOURINSECONDS : 0, 0, 0); + callSave(); + log(); + fillView(); }); fillView(); } - private void inflateRow(int i) { + private void inflateRow(final int position) { LayoutInflater inflater = LayoutInflater.from(context); - View childview = intervals[i] = inflater.inflate(R.layout.timelistedit_element, layout, false); - spinners[i] = new SpinnerHelper(childview.findViewById(R.id.timelistedit_time)); - numberPickers1[i] = (NumberPicker) childview.findViewById(R.id.timelistedit_edit1); - numberPickers2[i] = (NumberPicker) childview.findViewById(R.id.timelistedit_edit2); - addButtons[i] = (ImageView) childview.findViewById(R.id.timelistedit_add); - removeButtons[i] = (ImageView) childview.findViewById(R.id.timelistedit_remove); + View childView = intervals[position] = inflater.inflate(R.layout.timelistedit_element, layout, false); + spinners[position] = new SpinnerHelper(childView.findViewById(R.id.timelistedit_time)); + numberPickers1[position] = childView.findViewById(R.id.timelistedit_edit1); + numberPickers2[position] = childView.findViewById(R.id.timelistedit_edit2); + addButtons[position] = childView.findViewById(R.id.timelistedit_add); + removeButtons[position] = childView.findViewById(R.id.timelistedit_remove); - final int fixedPos = i; - addButtons[i].setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - int seconds = secondFromMidnight(fixedPos); - addItem(fixedPos, seconds, 0, 0); - // for here for the rest of values - for (int i = fixedPos + 1; i < itemsCount(); i++) { - if (secondFromMidnight(i - 1) >= secondFromMidnight(i)) { - editItem(i, secondFromMidnight(i - 1) + ONEHOURINSECONDS, value1(i), value2(i)); - } + addButtons[position].setOnClickListener(view -> { + int seconds = secondFromMidnight(position); + addItem(position, seconds, 0, 0); + // for here for the rest of values + for (int i = position + 1; i < itemsCount(); i++) { + if (secondFromMidnight(i - 1) >= secondFromMidnight(i)) { + editItem(i, secondFromMidnight(i - 1) + ONEHOURINSECONDS, value1(i), value2(i)); } - while (itemsCount() > 24 || secondFromMidnight(itemsCount() - 1) > 23 * ONEHOURINSECONDS) - removeItem(itemsCount() - 1); - callSave(); - log(); - fillView(); } + while (itemsCount() > 24 || secondFromMidnight(itemsCount() - 1) > 23 * ONEHOURINSECONDS) + removeItem(itemsCount() - 1); + callSave(); + log(); + fillView(); }); - removeButtons[i].setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - removeItem(fixedPos); - callSave(); - log(); - fillView(); - } + removeButtons[position].setOnClickListener(view -> { + removeItem(position); + callSave(); + log(); + fillView(); }); - spinners[i].setOnItemSelectedListener( + spinners[position].setOnItemSelectedListener( new AdapterView.OnItemSelectedListener() { @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - int seconds = DateUtil.toSeconds(spinners[fixedPos].getSelectedItem().toString()); - editItem(fixedPos, seconds, value1(fixedPos), value2(fixedPos)); + public void onItemSelected(AdapterView parent, View view, int selected, long id) { + int seconds = ((SpinnerAdapter) spinners[position].getAdapter()).valueForPosition(selected); + editItem(position, seconds, value1(position), value2(position)); log(); callSave(); fillView(); @@ -173,30 +165,10 @@ public class TimeListEdit { } ); - numberPickers1[i].setTextWatcher(new TextWatcher() { - @Override - public void afterTextChanged(Editable s) { - editItem(fixedPos, secondFromMidnight(fixedPos), SafeParse.stringToDouble(numberPickers1[fixedPos].getText()), value2(fixedPos)); - callSave(); - log(); - } - - @Override - public void beforeTextChanged(CharSequence s, int start, - int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, - int before, int count) { - } - }); - - - numberPickers2[i].setTextWatcher(new TextWatcher() { + numberPickers1[position].setTextWatcher(new TextWatcher() { @Override public void afterTextChanged(Editable s) { - editItem(fixedPos, secondFromMidnight(fixedPos), value1(fixedPos), SafeParse.stringToDouble(numberPickers2[fixedPos].getText())); + editItem(position, secondFromMidnight(position), SafeParse.stringToDouble(numberPickers1[position].getText()), value2(position)); callSave(); log(); } @@ -212,7 +184,27 @@ public class TimeListEdit { } }); - layout.addView(childview); + + numberPickers2[position].setTextWatcher(new TextWatcher() { + @Override + public void afterTextChanged(Editable s) { + editItem(position, secondFromMidnight(position), value1(position), SafeParse.stringToDouble(numberPickers2[position].getText())); + callSave(); + log(); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, + int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, + int before, int count) { + } + }); + + layout.addView(childView); } private void fillView() { @@ -220,7 +212,7 @@ public class TimeListEdit { if (i < itemsCount()) { intervals[i].setVisibility(View.VISIBLE); buildInterval(i); - } else if (i <= inflatedUntil){ + } else if (i <= inflatedUntil) { intervals[i].setVisibility(View.GONE); } } @@ -232,9 +224,8 @@ public class TimeListEdit { } } - private View buildInterval(int i) { + private void buildInterval(int i) { SpinnerHelper timeSpinner = spinners[i]; - View childview = intervals[i]; final NumberPicker editText1 = numberPickers1[i]; final NumberPicker editText2 = numberPickers2[i]; @@ -263,29 +254,38 @@ public class TimeListEdit { addButtons[i].setVisibility(View.VISIBLE); } - return childview; + } + + class SpinnerAdapter extends ArrayAdapter { + List values; + + SpinnerAdapter(@NonNull Context context, int resource, final @NonNull List objects, final @NonNull List values) { + super(context, resource, objects); + this.values = values; + } + + int valueForPosition(int position) { + return values.get(position); + } } private void fillSpinner(final SpinnerHelper spinner, int secondsFromMidnight, int previous, int next) { int posInList = 0; ArrayList timeList = new ArrayList<>(); + ArrayList timeListValues = new ArrayList<>(); int pos = 0; for (int t = previous + ONEHOURINSECONDS; t < next; t += ONEHOURINSECONDS) { timeList.add(DateUtil.timeStringFromSeconds(t)); + timeListValues.add(t); if (secondsFromMidnight == t) posInList = pos; pos++; } - final ArrayAdapter adapter = new ArrayAdapter<>(context, - R.layout.spinner_centered, timeList); + final SpinnerAdapter adapter = new SpinnerAdapter(context, + R.layout.spinner_centered, timeList, timeListValues); spinner.setAdapter(adapter); - final int finalPosInList = posInList; - new Handler().postDelayed(new Runnable() { - public void run() { - spinner.setSelection(finalPosInList, false); - adapter.notifyDataSetChanged(); - } - }, 100); + spinner.setSelection(posInList, false); + adapter.notifyDataSetChanged(); } private int itemsCount() { @@ -362,7 +362,7 @@ public class TimeListEdit { } private void addItem(int index, int timeAsSeconds, double value1, double value2) { - if(itemsCount()>inflatedUntil) { + if (itemsCount() > inflatedUntil) { layout.removeView(finalAdd); inflateRow(++inflatedUntil); layout.addView(finalAdd); @@ -389,10 +389,8 @@ public class TimeListEdit { } private void log() { - if (log.isDebugEnabled()) { - for (int i = 0; i < data1.length(); i++) { - log.debug(i + ": @" + DateUtil.timeStringFromSeconds(secondFromMidnight(i)) + " " + value1(i) + (data2 != null ? " " + value2(i) : "")); - } + for (int i = 0; i < data1.length(); i++) { + log.debug(i + ": @" + DateUtil.timeStringFromSeconds(secondFromMidnight(i)) + " " + value1(i) + (data2 != null ? " " + value2(i) : "")); } } @@ -400,9 +398,9 @@ public class TimeListEdit { if (save != null) save.run(); } - public void updateLabel(String txt){ + public void updateLabel(String txt) { this.label = txt; - if(textlabel!=null) + if (textlabel != null) textlabel.setText(txt); } } diff --git a/app/src/main/res/layout/timelistedit_element.xml b/app/src/main/res/layout/timelistedit_element.xml index b9e473d34e..a57dc29998 100644 --- a/app/src/main/res/layout/timelistedit_element.xml +++ b/app/src/main/res/layout/timelistedit_element.xml @@ -33,16 +33,16 @@ From 6ed0f9b40ece9d0c6d7391a6b4ef3401466e0aa1 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 22 Aug 2019 20:55:58 +0200 Subject: [PATCH 13/44] more detailed message --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2029c7023d..18006eb0b3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1665,7 +1665,7 @@ No connection for %1$d day(s) %2$d hours %2$.1fg %3$.2fU]]> Bolus constraint applied: %2$.2fU to %3$.2fU]]> - !!!!! Slow carbs absorption detected: %2$d%% of time. Double check your calculation. COB can be really off !!!!!]]> + !!!!! Slow carbs absorption detected: %2$d%% of time. Double check your calculation. COB can be overestimated thus more insulin could be given !!!!!]]> %1$.0f / %2$d U From 40ffb6f19982d06249a126410ed380737e96ef36 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 22 Aug 2019 21:33:10 +0200 Subject: [PATCH 14/44] force use iob when cob is selected --- .../dialogs/EditQuickWizardDialog.java | 48 ++++++++++++++----- .../overview/dialogs/WizardDialog.java | 19 +++++++- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java index 248ab30d7c..f4a689e34e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java @@ -8,6 +8,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; +import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.Spinner; @@ -59,17 +60,17 @@ public class EditQuickWizardDialog extends DialogFragment implements View.OnClic getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); View view = inflater.inflate(R.layout.overview_editquickwizard_dialog, container, false); - buttonEdit = (EditText) view.findViewById(R.id.overview_editquickwizard_button_edit); - carbsEdit = (EditText) view.findViewById(R.id.overview_editquickwizard_carbs_edit); - fromSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_from_spinner); - toSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_to_spinner); - useBGSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebg_spinner); - useCOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usecob_spinner); - useBolusIOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebolusiob_spinner); - useBasalIOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebasaliob_spinner); - useTrendSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usetrend_spinner); - useSuperBolusSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usesuperbolus_spinner); - useTempTargetSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usetemptarget_spinner); + buttonEdit = view.findViewById(R.id.overview_editquickwizard_button_edit); + carbsEdit = view.findViewById(R.id.overview_editquickwizard_carbs_edit); + fromSpinner = view.findViewById(R.id.overview_editquickwizard_from_spinner); + toSpinner = view.findViewById(R.id.overview_editquickwizard_to_spinner); + useBGSpinner = view.findViewById(R.id.overview_editquickwizard_usebg_spinner); + useCOBSpinner = view.findViewById(R.id.overview_editquickwizard_usecob_spinner); + useBolusIOBSpinner = view.findViewById(R.id.overview_editquickwizard_usebolusiob_spinner); + useBasalIOBSpinner = view.findViewById(R.id.overview_editquickwizard_usebasaliob_spinner); + useTrendSpinner = view.findViewById(R.id.overview_editquickwizard_usetrend_spinner); + useSuperBolusSpinner = view.findViewById(R.id.overview_editquickwizard_usesuperbolus_spinner); + useTempTargetSpinner = view.findViewById(R.id.overview_editquickwizard_usetemptarget_spinner); view.findViewById(R.id.ok).setOnClickListener(this); view.findViewById(R.id.cancel).setOnClickListener(this); @@ -104,6 +105,19 @@ public class EditQuickWizardDialog extends DialogFragment implements View.OnClic setSelection(useSuperBolusSpinner, entry.useSuperBolus()); setSelection(useTempTargetSpinner, entry.useTempTarget()); + useCOBSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + processCob(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + }); + processCob(); + return view; } @@ -147,6 +161,18 @@ public class EditQuickWizardDialog extends DialogFragment implements View.OnClic } } + private void processCob() { + if (getSelection(useCOBSpinner) == QuickWizardEntry.YES) { + useBolusIOBSpinner.setEnabled(false); + useBasalIOBSpinner.setEnabled(false); + setSelection(useBolusIOBSpinner, QuickWizardEntry.YES); + setSelection(useBasalIOBSpinner, QuickWizardEntry.YES); + } else { + useBolusIOBSpinner.setEnabled(true); + useBasalIOBSpinner.setEnabled(true); + } + } + int getSelection(Spinner spinner) { String value = spinner.getSelectedItem().toString(); if (value.equals(MainApp.gs(R.string.yes))) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java index fb903f3bae..6fb3768051 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java @@ -3,8 +3,6 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs; import android.app.Activity; import android.content.Context; import android.os.Bundle; -import androidx.fragment.app.DialogFragment; -import androidx.appcompat.app.AlertDialog; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; @@ -23,6 +21,8 @@ import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; +import androidx.fragment.app.DialogFragment; + import com.squareup.otto.Subscribe; import org.slf4j.Logger; @@ -254,6 +254,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com editCarbTime.setValue(savedInstanceState.getDouble("editCarbTime")); editCorr.setValue(savedInstanceState.getDouble("editCorr")); } + processCobCheckBox(); return view; } @@ -261,9 +262,23 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { saveCheckedStates(); ttCheckbox.setEnabled(bgCheckbox.isChecked() && TreatmentsPlugin.getPlugin().getTempTargetFromHistory() != null); + if (buttonView.getId() == cobCheckbox.getId()) + processCobCheckBox(); calculateInsulin(); } + private void processCobCheckBox() { + if (cobCheckbox.isChecked()) { + bolusIobCheckbox.setEnabled(false); + basalIobCheckbox.setEnabled(false); + bolusIobCheckbox.setChecked(true); + basalIobCheckbox.setChecked(true); + } else { + bolusIobCheckbox.setEnabled(true); + basalIobCheckbox.setEnabled(true); + } + } + private void saveCheckedStates() { SP.putBoolean(MainApp.gs(R.string.key_wizard_include_cob), cobCheckbox.isChecked()); SP.putBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), bgtrendCheckbox.isChecked()); From 0a77fb9bcbd56509c06f916fe003f98620c60642 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 23 Aug 2019 16:31:30 +0200 Subject: [PATCH 15/44] implement percentage in wizard, refactoring to kotlin --- .../activities/HistoryBrowseActivity.java | 2 +- .../plugins/aps/loop/LoopPlugin.java | 2 +- .../overview/dialogs/WizardDialog.java | 465 ------------------ .../general/overview/dialogs/WizardDialog.kt | 344 +++++++++++++ .../iob/iobCobCalculator/IobCobThread.java | 2 + .../EventAutosensCalculationFinished.java | 16 - .../EventAutosensCalculationFinished.kt | 6 + .../treatments/dialogs/WizardInfoDialog.java | 86 ---- .../treatments/dialogs/WizardInfoDialog.kt | 70 +++ .../androidaps/utils/BolusWizard.kt | 1 + .../androidaps/utils/JsonHelper.java | 13 + .../res/layout/overview_wizard_dialog.xml | 14 +- .../layout/treatments_wizardinfo_dialog.xml | 37 +- app/src/main/res/values/strings.xml | 3 + app/src/main/res/xml/pref_overview.xml | 13 + 15 files changed, 503 insertions(+), 571 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/events/EventAutosensCalculationFinished.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/events/EventAutosensCalculationFinished.kt delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.kt diff --git a/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java index 75767ec974..e5639d2ba4 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java @@ -194,7 +194,7 @@ public class HistoryBrowseActivity extends NoSplashActivity { @Subscribe public void onStatusEvent(final EventAutosensCalculationFinished e) { - if (e.cause == eventCustomCalculationFinished) { + if (e.getCause() == eventCustomCalculationFinished) { log.debug("EventAutosensCalculationFinished"); runOnUiThread(() -> { synchronized (HistoryBrowseActivity.this) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index e68bf9c30d..47a477f382 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -155,7 +155,7 @@ public class LoopPlugin extends PluginBase { */ @Subscribe public void onStatusEvent(final EventAutosensCalculationFinished ev) { - if (!(ev.cause instanceof EventNewBG)) { + if (!(ev.getCause() instanceof EventNewBG)) { // Autosens calculation not triggered by a new BG return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java deleted file mode 100644 index 6fb3768051..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java +++ /dev/null @@ -1,465 +0,0 @@ -package info.nightscout.androidaps.plugins.general.overview.dialogs; - -import android.app.Activity; -import android.content.Context; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.Spinner; -import android.widget.TextView; - -import androidx.fragment.app.DialogFragment; - -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.DecimalFormat; -import java.util.ArrayList; - -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.events.EventFeatureRunning; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.utils.BolusWizard; -import info.nightscout.androidaps.utils.DecimalFormatter; -import info.nightscout.androidaps.utils.NumberPicker; -import info.nightscout.androidaps.utils.SP; -import info.nightscout.androidaps.utils.SafeParse; -import info.nightscout.androidaps.utils.StringUtils; -import info.nightscout.androidaps.utils.ToastUtils; - -public class WizardDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener, Spinner.OnItemSelectedListener { - private static Logger log = LoggerFactory.getLogger(WizardDialog.class); - - Button okButton; - TextView bg; - TextView bgInsulin; - TextView bgUnits; - CheckBox bgCheckbox; - CheckBox ttCheckbox; - TextView carbs; - TextView carbsInsulin; - TextView bolusIobInsulin; - TextView basalIobInsulin; - CheckBox bolusIobCheckbox; - CheckBox basalIobCheckbox; - TextView correctionInsulin; - TextView total; - Spinner profileSpinner; - CheckBox superbolusCheckbox; - TextView superbolus; - TextView superbolusInsulin; - CheckBox bgtrendCheckbox; - TextView bgTrend; - TextView bgTrendInsulin; - LinearLayout cobLayout; - CheckBox cobCheckbox; - TextView cob; - TextView cobInsulin; - - NumberPicker editBg; - NumberPicker editCarbs; - NumberPicker editCorr; - NumberPicker editCarbTime; - - LinearLayout notesLayout; - EditText notesEdit; - - Integer calculatedCarbs = 0; - BolusWizard wizard; - - Context context; - - //one shot guards - private boolean accepted; - private boolean okClicked; - - public WizardDialog() { - super(); - } - - @Override - public void onAttach(Context context) { - super.onAttach(context); - this.context = context; - } - - @Override - public void onDetach() { - super.onDetach(); - this.context = null; - } - - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); - MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.WIZARD)); - } - - @Override - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onSaveInstanceState(Bundle savedInstanceState) { - savedInstanceState.putBoolean("bgCheckbox", bgCheckbox.isChecked()); - savedInstanceState.putBoolean("ttCheckbox", ttCheckbox.isChecked()); - savedInstanceState.putBoolean("bolusIobCheckbox", bolusIobCheckbox.isChecked()); - savedInstanceState.putBoolean("basalIobCheckbox", basalIobCheckbox.isChecked()); - savedInstanceState.putBoolean("bgtrendCheckbox", bgtrendCheckbox.isChecked()); - savedInstanceState.putBoolean("cobCheckbox", cobCheckbox.isChecked()); - savedInstanceState.putDouble("editBg", editBg.getValue()); - savedInstanceState.putDouble("editCarbs", editCarbs.getValue()); - savedInstanceState.putDouble("editCorr", editCorr.getValue()); - savedInstanceState.putDouble("editCarbTime", editCarbTime.getValue()); - super.onSaveInstanceState(savedInstanceState); - } - - - @Subscribe - public void onStatusEvent(final EventAutosensCalculationFinished e) { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - calculateInsulin(); - } - }); - } - - final private TextWatcher textWatcher = new TextWatcher() { - @Override - public void afterTextChanged(Editable s) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - calculateInsulin(); - } - }; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.overview_wizard_dialog, container, false); - - getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); - getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - - okButton = (Button) view.findViewById(R.id.ok); - okButton.setOnClickListener(this); - view.findViewById(R.id.cancel).setOnClickListener(this); - - bg = (TextView) view.findViewById(R.id.treatments_wizard_bg); - bgInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bginsulin); - bgUnits = (TextView) view.findViewById(R.id.treatments_wizard_bgunits); - carbs = (TextView) view.findViewById(R.id.treatments_wizard_carbs); - carbsInsulin = (TextView) view.findViewById(R.id.treatments_wizard_carbsinsulin); - bolusIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bolusiobinsulin); - basalIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_basaliobinsulin); - correctionInsulin = (TextView) view.findViewById(R.id.treatments_wizard_correctioninsulin); - total = (TextView) view.findViewById(R.id.treatments_wizard_total); - superbolus = (TextView) view.findViewById(R.id.treatments_wizard_sb); - superbolusInsulin = (TextView) view.findViewById(R.id.treatments_wizard_sbinsulin); - - notesLayout = view.findViewById(R.id.treatments_wizard_notes_layout); - notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE); - notesEdit = (EditText) view.findViewById(R.id.treatment_wizard_notes); - - bgTrend = (TextView) view.findViewById(R.id.treatments_wizard_bgtrend); - bgTrendInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bgtrendinsulin); - cobLayout = (LinearLayout) view.findViewById(R.id.treatments_wizard_cob_layout); - cob = (TextView) view.findViewById(R.id.treatments_wizard_cob); - cobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_cobinsulin); - - bgCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgcheckbox); - ttCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_ttcheckbox); - bgtrendCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgtrendcheckbox); - cobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_cobcheckbox); - bolusIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bolusiobcheckbox); - basalIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_basaliobcheckbox); - superbolusCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_sbcheckbox); - loadCheckedStates(); - - bgCheckbox.setOnCheckedChangeListener(this); - ttCheckbox.setOnCheckedChangeListener(this); - bgtrendCheckbox.setOnCheckedChangeListener(this); - cobCheckbox.setOnCheckedChangeListener(this); - basalIobCheckbox.setOnCheckedChangeListener(this); - bolusIobCheckbox.setOnCheckedChangeListener(this); - superbolusCheckbox.setOnCheckedChangeListener(this); - - profileSpinner = (Spinner) view.findViewById(R.id.treatments_wizard_profile); - profileSpinner.setOnItemSelectedListener(this); - - editCarbTime = (NumberPicker) view.findViewById(R.id.treatments_wizard_carbtimeinput); - editCorr = (NumberPicker) view.findViewById(R.id.treatments_wizard_correctioninput); - editCarbs = (NumberPicker) view.findViewById(R.id.treatments_wizard_carbsinput); - editBg = (NumberPicker) view.findViewById(R.id.treatments_wizard_bginput); - - superbolusCheckbox.setVisibility(SP.getBoolean(R.string.key_usesuperbolus, false) ? View.VISIBLE : View.GONE); - - Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); - Double maxCorrection = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); - - editBg.setParams(0d, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok), textWatcher); - editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher); - double bolusstep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep; - editCorr.setParams(0d, -maxCorrection, maxCorrection, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, view.findViewById(R.id.ok), textWatcher); - editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher); - initDialog(); - - setCancelable(true); - getDialog().setCanceledOnTouchOutside(false); - //recovering state if there is something - if (savedInstanceState != null) { - editCarbs.setValue(savedInstanceState.getDouble("editCarbs")); - editBg.setValue(savedInstanceState.getDouble("editBg")); - editCarbTime.setValue(savedInstanceState.getDouble("editCarbTime")); - editCorr.setValue(savedInstanceState.getDouble("editCorr")); - } - processCobCheckBox(); - return view; - } - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - saveCheckedStates(); - ttCheckbox.setEnabled(bgCheckbox.isChecked() && TreatmentsPlugin.getPlugin().getTempTargetFromHistory() != null); - if (buttonView.getId() == cobCheckbox.getId()) - processCobCheckBox(); - calculateInsulin(); - } - - private void processCobCheckBox() { - if (cobCheckbox.isChecked()) { - bolusIobCheckbox.setEnabled(false); - basalIobCheckbox.setEnabled(false); - bolusIobCheckbox.setChecked(true); - basalIobCheckbox.setChecked(true); - } else { - bolusIobCheckbox.setEnabled(true); - basalIobCheckbox.setEnabled(true); - } - } - - private void saveCheckedStates() { - SP.putBoolean(MainApp.gs(R.string.key_wizard_include_cob), cobCheckbox.isChecked()); - SP.putBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), bgtrendCheckbox.isChecked()); - } - - private void loadCheckedStates() { - bgtrendCheckbox.setChecked(SP.getBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), false)); - cobCheckbox.setChecked(SP.getBoolean(MainApp.gs(R.string.key_wizard_include_cob), false)); - } - - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - calculateInsulin(); - okButton.setVisibility(View.VISIBLE); - } - - @Override - public void onNothingSelected(AdapterView parent) { - ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.noprofileselected)); - okButton.setVisibility(View.GONE); - } - - @Override - public synchronized void onClick(View view) { - switch (view.getId()) { - case R.id.ok: - if (okClicked) { - log.debug("guarding: ok already clicked"); - dismiss(); - return; - } - okClicked = true; - wizard.confirmAndExecute(context); - dismiss(); - break; - case R.id.cancel: - dismiss(); - break; - } - } - - private void initDialog() { - Profile profile = ProfileFunctions.getInstance().getProfile(); - ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null ? ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() : null; - - if (profile == null || profileStore == null) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.noprofile)); - dismiss(); - return; - } - - ArrayList profileList; - profileList = profileStore.getProfileList(); - profileList.add(0, MainApp.gs(R.string.active)); - ArrayAdapter adapter = new ArrayAdapter<>(getContext(), - R.layout.spinner_centered, profileList); - - profileSpinner.setAdapter(adapter); - - String units = profile.getUnits(); - bgUnits.setText(units); - if (units.equals(Constants.MGDL)) editBg.setStep(1d); - else editBg.setStep(0.1d); - - // Set BG if not old - BgReading lastBg = DatabaseHelper.actualBg(); - - if (lastBg != null) { - editBg.setValue(lastBg.valueToUnits(units)); - } else { - editBg.setValue(0d); - } - ttCheckbox.setEnabled(TreatmentsPlugin.getPlugin().getTempTargetFromHistory() != null); - - // IOB calculation - TreatmentsPlugin.getPlugin().updateTotalIOBTreatments(); - IobTotal bolusIob = TreatmentsPlugin.getPlugin().getLastCalculationTreatments().round(); - TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals(); - IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round(); - - bolusIobInsulin.setText(StringUtils.formatInsulin(-bolusIob.iob)); - basalIobInsulin.setText(StringUtils.formatInsulin(-basalIob.basaliob)); - - calculateInsulin(); - } - - private void calculateInsulin() { - ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile(); - if (profileSpinner == null || profileSpinner.getSelectedItem() == null || profileStore == null) - return; // not initialized yet - String profileName = profileSpinner.getSelectedItem().toString(); - Profile specificProfile; - if (profileName.equals(MainApp.gs(R.string.active))) { - specificProfile = ProfileFunctions.getInstance().getProfile(); - profileName = ProfileFunctions.getInstance().getProfileName(); - } else - specificProfile = profileStore.getSpecificProfile(profileName); - - // Entered values - Double c_bg = SafeParse.stringToDouble(editBg.getText()); - Integer c_carbs = SafeParse.stringToInt(editCarbs.getText()); - Double c_correction = SafeParse.stringToDouble(editCorr.getText()); - Double corrAfterConstraint = c_correction; - if (c_correction > 0) - c_correction = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(c_correction)).value(); - if (Math.abs(c_correction - corrAfterConstraint) > 0.01d) { // c_correction != corrAfterConstraint doesn't work - editCorr.setValue(0d); - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.bolusconstraintapplied)); - return; - } - Integer carbsAfterConstraint = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(c_carbs)).value(); - if (Math.abs(c_carbs - carbsAfterConstraint) > 0.01d) { - editCarbs.setValue(0d); - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied)); - return; - } - - c_bg = bgCheckbox.isChecked() ? c_bg : 0d; - TempTarget tempTarget = ttCheckbox.isChecked() ? TreatmentsPlugin.getPlugin().getTempTargetFromHistory() : null; - - // COB - Double c_cob = 0d; - if (cobCheckbox.isChecked()) { - CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard COB"); - if (cobInfo.displayCob != null) - c_cob = cobInfo.displayCob; - } - - int carbTime = SafeParse.stringToInt(editCarbTime.getText()); - - wizard = new BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, 100d, bgCheckbox.isChecked(), cobCheckbox.isChecked(), bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked(), superbolusCheckbox.isChecked(), ttCheckbox.isChecked(), bgtrendCheckbox.isChecked(), notesEdit.getText().toString(), carbTime); - - bg.setText(c_bg + " ISF: " + DecimalFormatter.to1Decimal(wizard.getSens())); - bgInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBG())); - - carbs.setText(DecimalFormatter.to0Decimal(c_carbs) + "g IC: " + DecimalFormatter.to1Decimal(wizard.getIc())); - carbsInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCarbs())); - - bolusIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBolusIOB())); - basalIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBasalsIOB())); - - correctionInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCorrection())); - - calculatedCarbs = carbsAfterConstraint; - - // Superbolus - superbolus.setText(superbolusCheckbox.isChecked() ? MainApp.gs(R.string.twohours) : ""); - superbolusInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromSuperBolus())); - - // Trend - if (bgtrendCheckbox.isChecked() && wizard.getGlucoseStatus() != null) { - bgTrend.setText( - (wizard.getTrend() > 0 ? "+" : "") - + Profile.toUnitsString(wizard.getTrend() * 3, wizard.getTrend() * 3 / Constants.MMOLL_TO_MGDL, specificProfile.getUnits()) - + " " + specificProfile.getUnits()); - } else { - bgTrend.setText(""); - } - bgTrendInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromTrend())); - - // COB - if (cobCheckbox.isChecked()) { - cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.getIc())); - cobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCOB())); - } else { - cob.setText(""); - cobInsulin.setText(""); - } - - if (wizard.getCalculatedTotalInsulin() > 0d || calculatedCarbs > 0d) { - String insulinText = wizard.getCalculatedTotalInsulin() > 0d ? (DecimalFormatter.toPumpSupportedBolus(wizard.getCalculatedTotalInsulin()) + "U") : ""; - String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : ""; - total.setText(MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText); - okButton.setVisibility(View.VISIBLE); - } else { - // TODO this should also be run when loading the dialog as the OK button is initially visible - // but does nothing if neither carbs nor insulin is > 0 - total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.getCarbsEquivalent()) + "g"); - okButton.setVisibility(View.INVISIBLE); - } - - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt new file mode 100644 index 0000000000..1b54b0c69c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt @@ -0,0 +1,344 @@ +package info.nightscout.androidaps.plugins.general.overview.dialogs + +import android.content.Context +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.view.* +import android.widget.AdapterView +import android.widget.AdapterView.* +import android.widget.ArrayAdapter +import android.widget.CompoundButton +import androidx.fragment.app.DialogFragment +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.db.DatabaseHelper +import info.nightscout.androidaps.events.EventFeatureRunning +import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.utils.* +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.okcancel.* +import kotlinx.android.synthetic.main.overview_wizard_dialog.* +import org.slf4j.LoggerFactory +import java.text.DecimalFormat +import java.util.* + +class WizardDialog : DialogFragment() { + private val log = LoggerFactory.getLogger(WizardDialog::class.java) + + private var wizard: BolusWizard? = null + private var parentContext: Context? = null + + //one shot guards + private var okClicked: Boolean = false + + private val textWatcher = object : TextWatcher { + override fun afterTextChanged(s: Editable) {} + + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + calculateInsulin() + } + } + + private var disposable: CompositeDisposable = CompositeDisposable() + + override fun onAttach(context: Context?) { + super.onAttach(context) + this.parentContext = context + } + + override fun onDetach() { + super.onDetach() + this.parentContext = null + } + + override fun onResume() { + super.onResume() + MainApp.bus().post(EventFeatureRunning(EventFeatureRunning.Feature.WIZARD)) + } + + override fun onSaveInstanceState(savedInstanceState: Bundle) { + super.onSaveInstanceState(savedInstanceState) + savedInstanceState.putDouble("treatments_wizard_bginput", treatments_wizard_bginput.value) + savedInstanceState.putDouble("treatments_wizard_carbsinput", treatments_wizard_carbsinput.value) + savedInstanceState.putDouble("treatments_wizard_correctioninput", treatments_wizard_correctioninput.value) + savedInstanceState.putDouble("treatments_wizard_carbtimeinput", treatments_wizard_carbtimeinput.value) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + dialog.window?.requestFeature(Window.FEATURE_NO_TITLE) + dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) + isCancelable = true + dialog.setCanceledOnTouchOutside(false) + + return inflater.inflate(R.layout.overview_wizard_dialog, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + loadCheckedStates() + processCobCheckBox() + treatments_wizard_sbcheckbox.visibility = if (SP.getBoolean(R.string.key_usesuperbolus, false)) View.VISIBLE else View.GONE + treatments_wizard_notes_layout.visibility = if (SP.getBoolean(R.string.key_show_notes_entry_dialogs, false)) View.VISIBLE else View.GONE + + val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value() + val maxCorrection = MainApp.getConstraintChecker().maxBolusAllowed.value() + + treatments_wizard_bginput.setParams(savedInstanceState?.getDouble("treatments_wizard_bginput") + ?: 0.0, 0.0, 500.0, 0.1, DecimalFormat("0.0"), false, ok, textWatcher) + treatments_wizard_carbsinput.setParams(savedInstanceState?.getDouble("treatments_wizard_carbsinput") + ?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, ok, textWatcher) + val bolusstep = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription?.bolusStep + ?: 0.1 + treatments_wizard_correctioninput.setParams(savedInstanceState?.getDouble("treatments_wizard_correctioninput") + ?: 0.0, -maxCorrection, maxCorrection, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher) + treatments_wizard_carbtimeinput.setParams(savedInstanceState?.getDouble("treatments_wizard_carbtimeinput") + ?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher) + initDialog() + + // ok button + ok.setOnClickListener { + if (okClicked) { + log.debug("guarding: ok already clicked") + } else { + okClicked = true + parentContext?.let { context -> + wizard?.confirmAndExecute(context) + } + } + dismiss() + } + // cancel button + cancel.setOnClickListener { dismiss() } + // checkboxes + treatments_wizard_bgcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } + treatments_wizard_ttcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } + treatments_wizard_cobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } + treatments_wizard_basaliobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } + treatments_wizard_bolusiobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } + treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } + // profile spinner + treatments_wizard_profile.onItemSelectedListener = object : OnItemSelectedListener { + override fun onNothingSelected(parent: AdapterView<*>?) { + ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.noprofileselected)) + ok.visibility = View.GONE + } + + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + calculateInsulin() + ok.visibility = View.VISIBLE + } + } + // bus + disposable.add(RxBus + .toObservable(EventAutosensCalculationFinished::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + activity?.runOnUiThread { calculateInsulin() } + }, { + FabricPrivacy.logException(it) + }) + ) + + } + + override fun onDestroyView() { + super.onDestroyView() + disposable.clear() + } + + fun onCheckedChanged(buttonView: CompoundButton) { + saveCheckedStates() + treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && TreatmentsPlugin.getPlugin().tempTargetFromHistory != null + if (buttonView.id == treatments_wizard_cobcheckbox.id) + processCobCheckBox() + calculateInsulin() + } + + private fun processCobCheckBox() { + if (treatments_wizard_cobcheckbox.isChecked) { + treatments_wizard_bolusiobcheckbox.isEnabled = false + treatments_wizard_basaliobcheckbox.isEnabled = false + treatments_wizard_bolusiobcheckbox.isChecked = true + treatments_wizard_basaliobcheckbox.isChecked = true + } else { + treatments_wizard_bolusiobcheckbox.isEnabled = true + treatments_wizard_basaliobcheckbox.isEnabled = true + } + } + + private fun saveCheckedStates() { + SP.putBoolean(MainApp.gs(R.string.key_wizard_include_cob), treatments_wizard_cobcheckbox.isChecked) + SP.putBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), treatments_wizard_bgtrendcheckbox.isChecked) + } + + private fun loadCheckedStates() { + treatments_wizard_bgtrendcheckbox.isChecked = SP.getBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), false) + treatments_wizard_cobcheckbox.isChecked = SP.getBoolean(MainApp.gs(R.string.key_wizard_include_cob), false) + } + + private fun initDialog() { + val profile = ProfileFunctions.getInstance().profile + val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile + + if (profile == null || profileStore == null) { + ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.noprofile)) + dismiss() + return + } + + val profileList: ArrayList + profileList = profileStore.profileList + profileList.add(0, MainApp.gs(R.string.active)) + context?.let { context -> + val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList) + treatments_wizard_profile.adapter = adapter + } ?: return + + + val units = profile.units + treatments_wizard_bgunits.text = units + if (units == Constants.MGDL) + treatments_wizard_bginput.setStep(1.0) + else + treatments_wizard_bginput.setStep(0.1) + + // Set BG if not old + val lastBg = DatabaseHelper.actualBg() + + if (lastBg != null) { + treatments_wizard_bginput.value = lastBg.valueToUnits(units) + } else { + treatments_wizard_bginput.value = 0.0 + } + treatments_wizard_ttcheckbox.isEnabled = TreatmentsPlugin.getPlugin().tempTargetFromHistory != null + + // IOB calculation + TreatmentsPlugin.getPlugin().updateTotalIOBTreatments() + val bolusIob = TreatmentsPlugin.getPlugin().lastCalculationTreatments.round() + TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals() + val basalIob = TreatmentsPlugin.getPlugin().lastCalculationTempBasals.round() + + treatments_wizard_bolusiobinsulin.text = StringUtils.formatInsulin(-bolusIob.iob) + treatments_wizard_basaliobinsulin.text = StringUtils.formatInsulin(-basalIob.basaliob) + + calculateInsulin() + + treatments_wizard_percent_used.visibility = if (SP.getInt(R.string.key_boluswizard_percentage, 100) != 100) View.VISIBLE else View.GONE + } + + private fun calculateInsulin() { + val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile + if (treatments_wizard_profile.selectedItem == null || profileStore == null) + return // not initialized yet + var profileName = treatments_wizard_profile.selectedItem.toString() + val specificProfile: Profile? + if (profileName == MainApp.gs(R.string.active)) { + specificProfile = ProfileFunctions.getInstance().profile + profileName = ProfileFunctions.getInstance().profileName + } else + specificProfile = profileStore.getSpecificProfile(profileName) + + if (specificProfile == null) return + + // Entered values + var c_bg = SafeParse.stringToDouble(treatments_wizard_bginput.text) + val c_carbs = SafeParse.stringToInt(treatments_wizard_carbsinput.text) + var c_correction = SafeParse.stringToDouble(treatments_wizard_correctioninput.text) + val corrAfterConstraint = c_correction + if (c_correction > 0) + c_correction = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(c_correction)).value() + if (Math.abs(c_correction - corrAfterConstraint) > 0.01) { // c_correction != corrAfterConstraint doesn't work + treatments_wizard_correctioninput.value = 0.0 + ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.bolusconstraintapplied)) + return + } + val carbsAfterConstraint = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(c_carbs)).value() + if (Math.abs(c_carbs - carbsAfterConstraint) > 0.01) { + treatments_wizard_carbsinput.value = 0.0 + ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied)) + return + } + + c_bg = if (treatments_wizard_bgcheckbox.isChecked) c_bg else 0.0 + val tempTarget = if (treatments_wizard_ttcheckbox.isChecked) TreatmentsPlugin.getPlugin().tempTargetFromHistory else null + + // COB + var c_cob = 0.0 + if (treatments_wizard_cobcheckbox.isChecked) { + val cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard COB") + cobInfo.displayCob?.let { c_cob = it } + } + + val carbTime = SafeParse.stringToInt(treatments_wizard_carbtimeinput.text) + + wizard = BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, + SP.getInt(R.string.key_boluswizard_percentage, 100).toDouble(), + treatments_wizard_bgcheckbox.isChecked, + treatments_wizard_cobcheckbox.isChecked, + treatments_wizard_bolusiobcheckbox.isChecked, + treatments_wizard_basaliobcheckbox.isChecked, + treatments_wizard_sbcheckbox.isChecked, + treatments_wizard_ttcheckbox.isChecked, + treatments_wizard_bgtrendcheckbox.isChecked, + treatment_wizard_notes.text.toString(), carbTime) + + wizard?.let { wizard -> + treatments_wizard_bg.text = c_bg.toString() + " ISF: " + DecimalFormatter.to1Decimal(wizard.sens) + treatments_wizard_bginsulin.text = StringUtils.formatInsulin(wizard.insulinFromBG) + + treatments_wizard_carbs.text = DecimalFormatter.to0Decimal(c_carbs.toDouble()) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic) + treatments_wizard_carbsinsulin.text = StringUtils.formatInsulin(wizard.insulinFromCarbs) + + treatments_wizard_bolusiobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromBolusIOB) + treatments_wizard_basaliobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromBasalsIOB) + + treatments_wizard_correctioninsulin.text = StringUtils.formatInsulin(wizard.insulinFromCorrection) + + // Superbolus + treatments_wizard_sb.text = if (treatments_wizard_sbcheckbox.isChecked) MainApp.gs(R.string.twohours) else "" + treatments_wizard_sbinsulin.text = StringUtils.formatInsulin(wizard.insulinFromSuperBolus) + + // Trend + if (treatments_wizard_bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) { + treatments_wizard_bgtrend.text = ((if (wizard.trend > 0) "+" else "") + + Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, specificProfile.units) + + " " + specificProfile.units) + } else { + treatments_wizard_bgtrend.text = "" + } + treatments_wizard_bgtrendinsulin.text = StringUtils.formatInsulin(wizard.insulinFromTrend) + + // COB + if (treatments_wizard_cobcheckbox.isChecked) { + treatments_wizard_cob.text = DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic) + treatments_wizard_cobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromCOB) + } else { + treatments_wizard_cob.text = "" + treatments_wizard_cobinsulin.text = "" + } + + if (wizard.calculatedTotalInsulin > 0.0 || carbsAfterConstraint > 0.0) { + val insulinText = if (wizard.calculatedTotalInsulin > 0.0) DecimalFormatter.toPumpSupportedBolus(wizard.calculatedTotalInsulin) + "U" else "" + val carbsText = if (carbsAfterConstraint > 0.0) DecimalFormatter.to0Decimal(carbsAfterConstraint.toDouble()) + "g" else "" + treatments_wizard_total.text = MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText + ok.visibility = View.VISIBLE + } else { + treatments_wizard_total.text = MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g" + ok.visibility = View.INVISIBLE + } + } + + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java index 943637fd4e..4694685ea6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java @@ -22,6 +22,7 @@ import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults; +import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; @@ -312,6 +313,7 @@ public class IobCobThread extends Thread { new Thread(() -> { SystemClock.sleep(1000); MainApp.bus().post(new EventAutosensCalculationFinished(cause)); + RxBus.INSTANCE.send(new EventAutosensCalculationFinished(cause)); }).start(); } finally { if (mWakeLock != null) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/events/EventAutosensCalculationFinished.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/events/EventAutosensCalculationFinished.java deleted file mode 100644 index 25622843e7..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/events/EventAutosensCalculationFinished.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.plugins.iob.iobCobCalculator.events; - -import info.nightscout.androidaps.events.Event; -import info.nightscout.androidaps.events.EventLoop; - -/** - * Created by mike on 30.04.2017. - */ - -public class EventAutosensCalculationFinished extends EventLoop { - public Event cause; - - public EventAutosensCalculationFinished(Event cause) { - this.cause = cause; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/events/EventAutosensCalculationFinished.kt b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/events/EventAutosensCalculationFinished.kt new file mode 100644 index 0000000000..aa96aaf0b0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/events/EventAutosensCalculationFinished.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.iob.iobCobCalculator.events + +import info.nightscout.androidaps.events.Event +import info.nightscout.androidaps.events.EventLoop + +class EventAutosensCalculationFinished(var cause: Event) : EventLoop() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.java deleted file mode 100644 index e068e094f1..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.java +++ /dev/null @@ -1,86 +0,0 @@ -package info.nightscout.androidaps.plugins.treatments.dialogs; - -import android.os.Bundle; -import androidx.fragment.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.widget.CheckBox; -import android.widget.TextView; - -import org.json.JSONObject; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.utils.DecimalFormatter; -import info.nightscout.androidaps.utils.JsonHelper; - -public class WizardInfoDialog extends DialogFragment implements OnClickListener { - JSONObject json; - - public WizardInfoDialog() { - super(); - } - - public void setData(JSONObject json) { - this.json = json; - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.treatments_wizardinfo_dialog, container, false); - - getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - - view.findViewById(R.id.ok).setOnClickListener(this); - - // BG - ((TextView) view.findViewById(R.id.treatments_wizard_bg)).setText(DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "bg")) + " ISF: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "isf"))); - ((TextView) view.findViewById(R.id.treatments_wizard_bginsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulinbg")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_bgcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "insulinbgused")); - ((CheckBox) view.findViewById(R.id.treatments_wizard_ttcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "ttused")); - // Trend - ((TextView) view.findViewById(R.id.treatments_wizard_bgtrend)).setText(JsonHelper.safeGetString(json, "trend")); - ((TextView) view.findViewById(R.id.treatments_wizard_bgtrendinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulintrend")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_bgtrendcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "trendused")); - // COB - ((TextView) view.findViewById(R.id.treatments_wizard_cob)).setText(DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "cob")) + "g IC: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "ic"))); - ((TextView) view.findViewById(R.id.treatments_wizard_cobinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulincob")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_cobcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "cobused")); - // Bolus IOB - ((TextView) view.findViewById(R.id.treatments_wizard_bolusiobinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "bolusiob")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_bolusiobcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "bolusiobused")); - // Basal IOB - ((TextView) view.findViewById(R.id.treatments_wizard_basaliobinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "basaliob")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_basaliobcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "basaliobused")); - // Superbolus - ((TextView) view.findViewById(R.id.treatments_wizard_sbinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulinsuperbolus")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_sbcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "superbolusused")); - // Carbs - ((TextView) view.findViewById(R.id.treatments_wizard_carbs)).setText(DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "carbs")) + "g IC: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "ic"))); - ((TextView) view.findViewById(R.id.treatments_wizard_carbsinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulincarbs")) + "U"); - // Correction - ((TextView) view.findViewById(R.id.treatments_wizard_correctioninsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "othercorrection")) + "U"); - // Profile - ((TextView) view.findViewById(R.id.treatments_wizard_profile)).setText(JsonHelper.safeGetString(json, "profile")); - // Notes - ((TextView) view.findViewById(R.id.treatments_wizard_notes)).setText(JsonHelper.safeGetString(json, "notes")); - // Total - ((TextView) view.findViewById(R.id.treatments_wizard_totalinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulin")) + "U"); - - setCancelable(true); - return view; - } - - @Override - public synchronized void onClick(View view) { - switch (view.getId()) { - case R.id.ok: - dismiss(); - break; - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.kt new file mode 100644 index 0000000000..4e77a8f758 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.kt @@ -0,0 +1,70 @@ +package info.nightscout.androidaps.plugins.treatments.dialogs + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import androidx.fragment.app.DialogFragment +import info.nightscout.androidaps.R +import info.nightscout.androidaps.utils.DecimalFormatter +import info.nightscout.androidaps.utils.JsonHelper +import kotlinx.android.synthetic.main.treatments_wizardinfo_dialog.* +import org.json.JSONObject + +class WizardInfoDialog : DialogFragment() { + private var json: JSONObject? = null + + fun setData(json: JSONObject) { + this.json = json + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) + isCancelable = true + return inflater.inflate(R.layout.treatments_wizardinfo_dialog, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + close.setOnClickListener { dismiss() } + + // BG + treatments_wizard_bg.text = DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "bg")) + " ISF: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "isf")) + treatments_wizard_bginsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulinbg")) + "U" + treatments_wizard_bgcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "insulinbgused") + treatments_wizard_ttcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "ttused") + // Trend + treatments_wizard_bgtrend.text = JsonHelper.safeGetString(json, "trend") + treatments_wizard_bgtrendinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulintrend")) + "U" + treatments_wizard_bgtrendcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "trendused") + // COB + treatments_wizard_cob.text = DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "cob")) + "g IC: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "ic")) + treatments_wizard_cobinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulincob")) + "U" + treatments_wizard_cobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "cobused") + // Bolus IOB + treatments_wizard_bolusiobinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "bolusiob")) + "U" + treatments_wizard_bolusiobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "bolusiobused") + // Basal IOB + treatments_wizard_basaliobinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "basaliob")) + "U" + treatments_wizard_basaliobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "basaliobused") + // Superbolus + treatments_wizard_sbinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulinsuperbolus")) + "U" + treatments_wizard_sbcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "superbolusused") + // Carbs + treatments_wizard_carbs.text = DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "carbs")) + "g IC: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "ic")) + treatments_wizard_carbsinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulincarbs")) + "U" + // Correction + treatments_wizard_correctioninsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "othercorrection")) + "U" + // Profile + treatments_wizard_profile.text = JsonHelper.safeGetString(json, "profile") + // Notes + treatments_wizard_notes.text = JsonHelper.safeGetString(json, "notes") + // Percentage + treatments_wizard_percent_used.text = DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "percentageCorrection", 100.0)) + "%" + // Total + treatments_wizard_totalinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulin")) + "U" + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt index b741e4656c..598616f1bf 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt @@ -231,6 +231,7 @@ class BolusWizard @JvmOverloads constructor(val profile: Profile, boluscalcJSON.put("insulintrend", insulinFromTrend) boluscalcJSON.put("trend", trend) boluscalcJSON.put("ttused", useTT) + boluscalcJSON.put("percentageCorrection", percentageCorrection) } catch (e: JSONException) { log.error("Unhandled exception", e) } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java b/app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java index 8f715a0448..5308c62420 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java @@ -72,6 +72,19 @@ public class JsonHelper { return result; } + public static double safeGetDouble(JSONObject json, String fieldName, double defaultValue) { + double result = defaultValue; + + if (json != null && json.has(fieldName)) { + try { + result = json.getDouble(fieldName); + } catch (JSONException ignored) { + } + } + + return result; + } + public static int safeGetInt(JSONObject json, String fieldName) { int result = 0; diff --git a/app/src/main/res/layout/overview_wizard_dialog.xml b/app/src/main/res/layout/overview_wizard_dialog.xml index 7fc3c32f3a..a6a278a89d 100644 --- a/app/src/main/res/layout/overview_wizard_dialog.xml +++ b/app/src/main/res/layout/overview_wizard_dialog.xml @@ -197,6 +197,18 @@ android:text="2.35U 28g" android:textAppearance="?android:attr/textAppearanceLarge" /> + + - + + + + + + + + + + + +