From 99c8bbc6c25c5e809b2a5691638ac864f89eaa49 Mon Sep 17 00:00:00 2001 From: "Markus M. May" Date: Mon, 9 Apr 2018 22:10:08 +0200 Subject: [PATCH 01/56] Adding notes to carbs and to wizard on overview --- .../androidaps/data/DetailedBolusInfo.java | 2 ++ .../Overview/Dialogs/NewCarbsDialog.java | 7 +++++ .../Overview/Dialogs/WizardDialog.java | 7 +++++ .../java/info/nightscout/utils/NSUpload.java | 4 +++ .../res/layout/overview_newcarbs_dialog.xml | 25 ++++++++++++++++++ .../res/layout/overview_wizard_dialog.xml | 26 +++++++++++++++++++ 6 files changed, 71 insertions(+) diff --git a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java index 3935b17b8a..c2f9d16dc3 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java +++ b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java @@ -30,6 +30,7 @@ public class DetailedBolusInfo { public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment) public boolean isSMB = false; // is a Super-MicroBolus public long deliverAt = 0; // SMB should be delivered within 1 min from this time + public String notes = null; public DetailedBolusInfo copy() { DetailedBolusInfo n = new DetailedBolusInfo(); @@ -47,6 +48,7 @@ public class DetailedBolusInfo { n.pumpId = pumpId; n.isSMB = isSMB; n.deliverAt = deliverAt; + n.notes = notes; return n; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 19119450df..c1ae798aa6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -18,6 +18,7 @@ import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.CompoundButton; +import android.widget.EditText; import android.widget.RadioButton; import android.widget.TextView; @@ -69,6 +70,8 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D private Button fav2Button; private Button fav3Button; + private EditText notesEdit; + private static final int FAV1_DEFAULT = 5; private static final int FAV2_DEFAULT = 10; private static final int FAV3_DEFAULT = 20; @@ -157,6 +160,8 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D fav3Button.setOnClickListener(this); fav3Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))); + notesEdit = (EditText) view.findViewById(R.id.newcarbs_notes); + setCancelable(true); getDialog().setCanceledOnTouchOutside(false); return view; @@ -358,6 +363,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D final int finalEatingSoonTTDuration = eatingSoonTTDuration; final double finalHypoTT = hypoTT; final int finalHypoTTDuration = hypoTTDuration; + final String finalNotes = notesEdit.getText().toString(); if (!initialEventTime.equals(eventTime)) { actions.add("Time: " + DateUtil.dateAndTimeString(eventTime)); @@ -416,6 +422,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D detailedBolusInfo.carbs = finalCarbsAfterConstraints; detailedBolusInfo.context = context; detailedBolusInfo.source = Source.USER; + detailedBolusInfo.notes = finalNotes; if (ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) { ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index f44e570774..7f8f16120e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -21,6 +21,7 @@ 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; @@ -103,6 +104,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com NumberPicker editCorr; NumberPicker editCarbTime; + EditText notesEdit; + Integer calculatedCarbs = 0; Double calculatedTotalInsulin = 0d; JSONObject boluscalcJSON; @@ -205,6 +208,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com superbolus = (TextView) view.findViewById(R.id.treatments_wizard_sb); superbolusInsulin = (TextView) view.findViewById(R.id.treatments_wizard_sbinsulin); + notesEdit = (EditText) view.findViewById(R.id.newcarbs_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); @@ -320,6 +325,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com final Double bg = SafeParse.stringToDouble(editBg.getText()); final int carbTime = SafeParse.stringToInt(editCarbTime.getText()); final boolean useSuperBolus = superbolusCheckbox.isChecked(); + final String finalNotes = notesEdit.getText().toString(); final AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); @@ -363,6 +369,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com detailedBolusInfo.carbTime = carbTime; detailedBolusInfo.boluscalc = boluscalcJSON; detailedBolusInfo.source = Source.USER; + detailedBolusInfo.notes = finalNotes; if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) { ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { @Override diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index 9b9b940ef9..1e24083ac2 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -8,6 +8,7 @@ import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; +import org.apache.commons.lang3.StringUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -275,6 +276,9 @@ public class NSUpload { data.put("boluscalc", detailedBolusInfo.boluscalc); if (detailedBolusInfo.carbTime != 0) data.put("preBolus", detailedBolusInfo.carbTime); + if (!StringUtils.isEmpty(detailedBolusInfo.notes)) { + data.put("notes", detailedBolusInfo.notes); + } } catch (JSONException e) { log.error("Unhandled exception", e); } diff --git a/app/src/main/res/layout/overview_newcarbs_dialog.xml b/app/src/main/res/layout/overview_newcarbs_dialog.xml index 25ca0d75d2..e75bf54dff 100644 --- a/app/src/main/res/layout/overview_newcarbs_dialog.xml +++ b/app/src/main/res/layout/overview_newcarbs_dialog.xml @@ -122,9 +122,34 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/overview_wizard_dialog.xml b/app/src/main/res/layout/overview_wizard_dialog.xml index 4fbdfd3614..d4609c931e 100644 --- a/app/src/main/res/layout/overview_wizard_dialog.xml +++ b/app/src/main/res/layout/overview_wizard_dialog.xml @@ -199,6 +199,32 @@ + + + + + + + + Date: Tue, 10 Apr 2018 12:06:26 +0200 Subject: [PATCH 02/56] Fix re-enabling the loop plugin from overview. Fixes #861. Note that enabling a loop plugin is hardcoded against the only impl currently available LoopPlugin. Support for multiple loop plugins is incomplete (and not needed at this point), since there's no LoopInterface, but immediately LoopPlugin (as compared to APSInterface with OpenAPS* impls). When adding support, the last activated loop plugin must be remembered so the correct one is re-enabled. --- .../ConfigBuilder/ConfigBuilderPlugin.java | 1 + .../plugins/Overview/OverviewFragment.java | 20 ++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java index c6b2e3ce96..4ffec6aef3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java @@ -264,6 +264,7 @@ public class ConfigBuilderPlugin extends PluginBase { return activeAPS; } + @Nullable public static LoopPlugin getActiveLoop() { return activeLoop; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index d6c9c70c4e..a05df99efd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -459,10 +459,12 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (v == apsModeView) { final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); final PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription(); - if (activeloop == null || !MainApp.getConfigBuilder().isProfileValid("ContexMenuCreation")) + if (!MainApp.getConfigBuilder().isProfileValid("ContexMenuCreation")) return; menu.setHeaderTitle(MainApp.gs(R.string.loop)); - if (activeloop.isEnabled(PluginType.LOOP)) { + if (activeloop == null) { + menu.add(MainApp.gs(R.string.enableloop)); + } else { menu.add(MainApp.gs(R.string.disableloop)); if (!activeloop.isSuspended()) { menu.add(MainApp.gs(R.string.suspendloopfor1h)); @@ -480,8 +482,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, menu.add(MainApp.gs(R.string.resume)); } } - if (!activeloop.isEnabled(PluginType.LOOP)) - menu.add(MainApp.gs(R.string.enableloop)); } else if (v == activeProfileView) { menu.setHeaderTitle(MainApp.gs(R.string.profile)); menu.add(MainApp.gs(R.string.danar_viewprofile)); @@ -496,13 +496,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) return true; - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); if (item.getTitle().equals(MainApp.gs(R.string.disableloop))) { + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); activeloop.setPluginEnabled(PluginType.LOOP, false); activeloop.setFragmentVisible(PluginType.LOOP, false); MainApp.getConfigBuilder().storeSettings("DisablingLoop"); updateGUI("suspendmenu"); - MainApp.getConfigBuilder().getCommandQueue().cancelTempBasal(true, new Callback() { + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { if (!result.success) { @@ -513,16 +513,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, NSUpload.uploadOpenAPSOffline(24 * 60); // upload 24h, we don't know real duration return true; } else if (item.getTitle().equals(MainApp.gs(R.string.enableloop))) { - activeloop.setPluginEnabled(PluginType.LOOP, true); - activeloop.setFragmentVisible(PluginType.LOOP, true); + final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); + loopPlugin.setPluginEnabled(PluginType.LOOP, true); + loopPlugin.setFragmentVisible(PluginType.LOOP, true); MainApp.getConfigBuilder().storeSettings("EnablingLoop"); updateGUI("suspendmenu"); NSUpload.uploadOpenAPSOffline(0); return true; } else if (item.getTitle().equals(MainApp.gs(R.string.resume))) { + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); activeloop.suspendTo(0L); updateGUI("suspendmenu"); - MainApp.getConfigBuilder().getCommandQueue().cancelTempBasal(true, new Callback() { + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { if (!result.success) { From d2491ca429e84ec361cda516ba3ff729afea2c6c Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 4 Apr 2018 19:59:16 +0200 Subject: [PATCH 03/56] NewCarbsDialog: add duration, help. --- .../Overview/Dialogs/NewCarbsDialog.java | 260 +++++++++--------- .../fragments/TreatmentsBolusFragment.java | 4 + .../TreatmentsTempTargetFragment.java | 12 +- .../res/layout/overview_newcarbs_dialog.xml | 158 +++++++++-- 4 files changed, 274 insertions(+), 160 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 19119450df..1725fed14f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.Overview.Dialogs; -import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.HandlerThread; @@ -9,7 +8,6 @@ import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.Html; import android.text.TextWatcher; -import android.text.format.DateFormat; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -18,20 +16,16 @@ import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.RadioButton; -import android.widget.TextView; import com.google.common.base.Joiner; -import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; -import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout; -import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.DecimalFormat; -import java.util.Calendar; -import java.util.Date; import java.util.LinkedList; import java.util.List; @@ -45,6 +39,8 @@ import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Loop.APSResult; +import info.nightscout.androidaps.plugins.OpenAPSSMB.DetermineBasalResultSMB; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DateUtil; @@ -54,16 +50,10 @@ import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; -public class NewCarbsDialog extends DialogFragment implements OnClickListener, DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener, CompoundButton.OnCheckedChangeListener { +public class NewCarbsDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener { private static Logger log = LoggerFactory.getLogger(NewCarbsDialog.class); - private NumberPicker editCarbs; - - private TextView dateButton; - private TextView timeButton; - - private Date initialEventTime; - private Date eventTime; + private ImageView helpView; private Button fav1Button; private Button fav2Button; @@ -77,6 +67,11 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D private RadioButton startHypoTTCheckbox; private boolean togglingTT; + private NumberPicker editTime; + private LinearLayout durationLayout; + private NumberPicker editDuration; + private NumberPicker editCarbs; + private Integer maxCarbs; //one shot guards @@ -104,6 +99,16 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D }; private void validateInputs() { + Integer time = SafeParse.stringToInt(editTime.getText()); + if (time > 12 * 60 || time < -12 * 60) { + editTime.setValue(0d); + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied)); + } + Integer duration = SafeParse.stringToInt(editDuration.getText()); + if (duration > 10) { + editDuration.setValue(0d); + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied)); + } Integer carbs = SafeParse.stringToInt(editCarbs.getText()); if (carbs > maxCarbs) { editCarbs.setValue(0d); @@ -122,10 +127,12 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); + helpView = view.findViewById(R.id.newcarbs_help); + helpView.setOnClickListener(this); + maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); editCarbs = view.findViewById(R.id.newcarb_carbsamount); - editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); startActivityTTCheckbox = view.findViewById(R.id.newcarbs_activity_tt); @@ -135,15 +142,13 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D startHypoTTCheckbox = view.findViewById(R.id.newcarbs_hypo_tt); startHypoTTCheckbox.setOnCheckedChangeListener(this); - dateButton = view.findViewById(R.id.newcarbs_eventdate); - timeButton = view.findViewById(R.id.newcarb_eventtime); + editTime = view.findViewById(R.id.newcarbs_time); + editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, textWatcher); - initialEventTime = new Date(); - eventTime = new Date(initialEventTime.getTime()); - dateButton.setText(DateUtil.dateString(eventTime)); - timeButton.setText(DateUtil.timeString(eventTime)); - dateButton.setOnClickListener(this); - timeButton.setOnClickListener(this); + durationLayout = view.findViewById(R.id.newcarbs_duration_layout); + durationLayout.setVisibility(MainApp.engineeringMode ? View.VISIBLE : View.GONE); + editDuration = view.findViewById(R.id.new_carbs_duration); + editDuration.setParams(0d, 0d, 10d, 1d, new DecimalFormat("0"), false, textWatcher); fav1Button = view.findViewById(R.id.newcarbs_plus1); fav1Button.setOnClickListener(this); @@ -168,8 +173,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D @Override public synchronized void onClick(View view) { - Calendar calendar = Calendar.getInstance(); - calendar.setTime(eventTime); switch (view.getId()) { case R.id.ok: submit(); @@ -177,27 +180,16 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D case R.id.cancel: dismiss(); break; - case R.id.newcarbs_eventdate: - DatePickerDialog dpd = DatePickerDialog.newInstance( - this, - calendar.get(Calendar.YEAR), - calendar.get(Calendar.MONTH), - calendar.get(Calendar.DAY_OF_MONTH) - ); - dpd.setThemeDark(true); - dpd.dismissOnPause(true); - dpd.show(getActivity().getFragmentManager(), "Datepickerdialog"); - break; - case R.id.newcarb_eventtime: - TimePickerDialog tpd = TimePickerDialog.newInstance( - this, - calendar.get(Calendar.HOUR_OF_DAY), - calendar.get(Calendar.MINUTE), - DateFormat.is24HourFormat(getActivity()) - ); - tpd.setThemeDark(true); - tpd.dismissOnPause(true); - tpd.show(getActivity().getFragmentManager(), "Timepickerdialog"); + case R.id.newcarbs_help: + AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext()); + builder.setTitle("Help"); + builder.setMessage(Html.fromHtml("Time: relative offset to now
" + + "Duration: splits carb up over entered time, one every 15m
" + + "
" + + "Did I ever tell you the story about the old tree and the wooden house? So " + + "anyway, there I was, in the middle of the forest with all my clothes gone.
" + + "
Also: blablabla")); + builder.show(); break; case R.id.newcarbs_plus1: editCarbs.setValue(Math.max(0, editCarbs.getValue() @@ -352,6 +344,11 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(hypoTT) + " mg/dl (" + hypoTTDuration + " min)"); } + int duration = SafeParse.stringToInt(editDuration.getText()); + if (duration > 0) { + actions.add("Duration: " + editDuration.getText() + "h"); + } + final double finalActivityTT = activityTT; final int finalActivityTTDuration = activityTTDuration; final double finalEatigSoonTT = eatingSoonTT; @@ -359,83 +356,74 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D final double finalHypoTT = hypoTT; final int finalHypoTTDuration = hypoTTDuration; - if (!initialEventTime.equals(eventTime)) { - actions.add("Time: " + DateUtil.dateAndTimeString(eventTime)); + long timeOffset = editTime.getValue().longValue(); + final long time = DateUtil.now() + timeOffset * 1000 * 60; + if (timeOffset != 0) { + actions.add("Time: " + DateUtil.dateAndTimeString(time)); } - final int finalCarbsAfterConstraints = carbsAfterConstraints; - - final Context context = getContext(); - final AlertDialog.Builder builder = new AlertDialog.Builder(context); - + final AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(MainApp.gs(R.string.confirmation)); - builder.setMessage(actions.isEmpty() - ? MainApp.gs(R.string.no_action_selected) - : Html.fromHtml(Joiner.on("
").join(actions))); - builder.setPositiveButton(MainApp.gs(R.string.ok), actions.isEmpty() ? null : (dialog, id) -> { - synchronized (builder) { - if (accepted) { - log.debug("guarding: already accepted"); - return; - } - accepted = true; + if (carbsAfterConstraints > 0 || startActivityTTCheckbox.isChecked() + || startEatingSoonTTCheckbox.isChecked() || startHypoTTCheckbox.isChecked()) { + builder.setMessage(Html.fromHtml(Joiner.on("
").join(actions))); + builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> { + synchronized (builder) { + if (accepted) { + log.debug("guarding: already accepted"); + return; + } + accepted = true; - if (startActivityTTCheckbox.isChecked()) { - TempTarget tempTarget = new TempTarget() - .date(System.currentTimeMillis()) - .duration(finalActivityTTDuration) - .reason(MainApp.gs(R.string.activity)) - .source(Source.USER) - .low(Profile.toMgdl(finalActivityTT, currentProfile.getUnits())) - .high(Profile.toMgdl(finalActivityTT, currentProfile.getUnits())); - MainApp.getDbHelper().createOrUpdate(tempTarget); - } else if (startEatingSoonTTCheckbox.isChecked()) { - TempTarget tempTarget = new TempTarget() - .date(System.currentTimeMillis()) - .duration(finalEatingSoonTTDuration) - .reason(MainApp.gs(R.string.eatingsoon)) - .source(Source.USER) - .low(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits())) - .high(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits())); - MainApp.getDbHelper().createOrUpdate(tempTarget); - } else if (startHypoTTCheckbox.isChecked()) { - TempTarget tempTarget = new TempTarget() - .date(System.currentTimeMillis()) - .duration(finalHypoTTDuration) - .reason(MainApp.gs(R.string.hypo)) - .source(Source.USER) - .low(Profile.toMgdl(finalHypoTT, currentProfile.getUnits())) - .high(Profile.toMgdl(finalHypoTT, currentProfile.getUnits())); - MainApp.getDbHelper().createOrUpdate(tempTarget); - } + if (startActivityTTCheckbox.isChecked()) { + TempTarget tempTarget = new TempTarget() + .date(System.currentTimeMillis()) + .duration(finalActivityTTDuration) + .reason(MainApp.gs(R.string.activity)) + .source(Source.USER) + .low(Profile.toMgdl(finalActivityTT, currentProfile.getUnits())) + .high(Profile.toMgdl(finalActivityTT, currentProfile.getUnits())); + MainApp.getDbHelper().createOrUpdate(tempTarget); + } else if (startEatingSoonTTCheckbox.isChecked()) { + TempTarget tempTarget = new TempTarget() + .date(System.currentTimeMillis()) + .duration(finalEatingSoonTTDuration) + .reason(MainApp.gs(R.string.eatingsoon)) + .source(Source.USER) + .low(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits())) + .high(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits())); + MainApp.getDbHelper().createOrUpdate(tempTarget); + } else if (startHypoTTCheckbox.isChecked()) { + TempTarget tempTarget = new TempTarget() + .date(System.currentTimeMillis()) + .duration(finalHypoTTDuration) + .reason(MainApp.gs(R.string.hypo)) + .source(Source.USER) + .low(Profile.toMgdl(finalHypoTT, currentProfile.getUnits())) + .high(Profile.toMgdl(finalHypoTT, currentProfile.getUnits())); + MainApp.getDbHelper().createOrUpdate(tempTarget); + } - if (finalCarbsAfterConstraints > 0) { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.date = eventTime.getTime(); - detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; - detailedBolusInfo.carbs = finalCarbsAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.source = Source.USER; - if (ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) { - ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } + if (carbsAfterConstraints > 0) { + if (duration == 0) { + createCarb(carbsAfterConstraints, time); + } else { + double remainingCarbs = carbsAfterConstraints; + long carbTime = time; + long smallCarbAmount = Math.round(remainingCarbs / (editDuration.getValue() * 4)); + if (smallCarbAmount == 0) smallCarbAmount = 1; + while (remainingCarbs > 0) { + createCarb(smallCarbAmount, carbTime); + remainingCarbs -= smallCarbAmount; + carbTime += 15 * 60 * 1000; } - }); - } else { - TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo); + } } } - } - }); + }); + } else { + builder.setMessage(MainApp.gs(R.string.no_action_selected)); + } builder.setNegativeButton(MainApp.gs(R.string.cancel), null); builder.show(); dismiss(); @@ -444,19 +432,29 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D } } - @Override - public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) { - eventTime.setYear(year - 1900); - eventTime.setMonth(monthOfYear); - eventTime.setDate(dayOfMonth); - dateButton.setText(DateUtil.dateString(eventTime)); - } - - @Override - public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) { - eventTime.setHours(hourOfDay); - eventTime.setMinutes(minute); - eventTime.setSeconds(second); - timeButton.setText(DateUtil.timeString(eventTime)); + private void createCarb(long carbs, long time) { + DetailedBolusInfo carbInfo = new DetailedBolusInfo(); + carbInfo.date = time; + carbInfo.eventType = CareportalEvent.CARBCORRECTION; + carbInfo.carbs = carbs; + carbInfo.context = getContext(); + carbInfo.source = Source.USER; + if (ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) { + ConfigBuilderPlugin.getCommandQueue().bolus(carbInfo, new Callback() { + @Override + public void run() { + if (!result.success) { + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } + } + }); + } else { + TreatmentsPlugin.getPlugin().addToHistoryTreatment(carbInfo); + } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java index 87626ed4cd..ae977d4024 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java @@ -89,6 +89,10 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); else holder.iob.setTextColor(holder.carbs.getCurrentTextColor()); + if (t.date > DateUtil.now()) + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorScheduled)); + else + holder.date.setTextColor(holder.carbs.getCurrentTextColor()); holder.remove.setTag(t); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java index d018efd97b..5ce79636b5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java @@ -84,14 +84,10 @@ public class TreatmentsTempTargetFragment extends SubscriberFragment implements holder.reasonLabel.setText(""); holder.reasonColon.setText(""); } - if (tempTarget.isInProgress()) { - if (tempTarget == currentlyActiveTarget) { - // active as newest - holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorInProgress)); - } else { - // other's that might become active again after the latest (overlapping) is over - holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); - } + if (tempTarget.isInProgress() && tempTarget == currentlyActiveTarget) { + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); + } else if (tempTarget.date > DateUtil.now()) { + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorScheduled)); } else { holder.date.setTextColor(holder.reasonColon.getCurrentTextColor()); } diff --git a/app/src/main/res/layout/overview_newcarbs_dialog.xml b/app/src/main/res/layout/overview_newcarbs_dialog.xml index 25ca0d75d2..944352af83 100644 --- a/app/src/main/res/layout/overview_newcarbs_dialog.xml +++ b/app/src/main/res/layout/overview_newcarbs_dialog.xml @@ -11,6 +11,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + - - + android:layout_height="wrap_content" + android:layout_gravity="center" + android:orientation="horizontal"> + + + + + + + + + android:paddingTop="5dp" + android:visibility="gone"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date: Wed, 11 Apr 2018 01:29:40 +0200 Subject: [PATCH 04/56] Color active/scheduled bolus/carbs and TT entries in treatment tab. --- app/src/main/res/values/colors.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 318e93d9d8..a0b229946e 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -49,7 +49,7 @@ #FFDD7792 #ca77dd - #c45026 + #de7550 #1b5e20 #47c8ff From f8d022ba87cb7ca90412195d3c2df17403b1f54b Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 11 Apr 2018 12:59:28 +0200 Subject: [PATCH 05/56] NewCarbsDialog: prefill with carbsReq. --- .../Overview/Dialogs/NewCarbsDialog.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 1725fed14f..93ba7c9d81 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -132,9 +132,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); - editCarbs = view.findViewById(R.id.newcarb_carbsamount); - editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); - startActivityTTCheckbox = view.findViewById(R.id.newcarbs_activity_tt); startActivityTTCheckbox.setOnCheckedChangeListener(this); startEatingSoonTTCheckbox = view.findViewById(R.id.newcarbs_eating_soon_tt); @@ -150,6 +147,22 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C editDuration = view.findViewById(R.id.new_carbs_duration); editDuration.setParams(0d, 0d, 10d, 1d, new DecimalFormat("0"), false, textWatcher); + editCarbs = view.findViewById(R.id.newcarb_carbsamount); + editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); + + if (MainApp.engineeringMode) { + // use SMB's carbs required as preset, check hypo TT if any + if (ConfigBuilderPlugin.getActiveAPS() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null) { + APSResult lastAPSResult = ConfigBuilderPlugin.getActiveAPS().getLastAPSResult(); + if (lastAPSResult != null && lastAPSResult instanceof DetermineBasalResultSMB && ((DetermineBasalResultSMB) lastAPSResult).carbsReq > 0) { + editCarbs.setValue(((DetermineBasalResultSMB) lastAPSResult).carbsReq); + startHypoTTCheckbox.setOnCheckedChangeListener(null); + startHypoTTCheckbox.setChecked(true); + startHypoTTCheckbox.setOnClickListener(this); + } + } + } + fav1Button = view.findViewById(R.id.newcarbs_plus1); fav1Button.setOnClickListener(this); fav1Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))); From 564e87d782af9515581d32207ee85b09ab578c25 Mon Sep 17 00:00:00 2001 From: Roumen Georgiev Date: Wed, 11 Apr 2018 15:44:53 +0300 Subject: [PATCH 06/56] added phone Manufacturer and model note to NS --- .../java/info/nightscout/utils/NSUpload.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index 9b9b940ef9..ad6cc45ab8 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -476,6 +476,32 @@ public class NSUpload { intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); context.sendBroadcast(intent); DbLogger.dbAdd(intent, data.toString()); + // now adding another note with the device running AndroidAPS + uploadDeviceNote(); + } + } + + public static void uploadDeviceNote(){ + if (SP.getBoolean(R.string.key_ns_logappstartedevent, true)) { + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + JSONObject data = new JSONObject(); + try { + data.put("eventType", "Note"); + data.put("created_at", DateUtil.toISOString(new Date())); + data.put("notes", "Started on "+ Build.MANUFACTURER + " "+ Build.MODEL); +// log.debug("Running on: "+Build.MANUFACTURER + " "+ Build.MODEL); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); } } From 61cce65947b980a1e2ca97f82a7f80e38889cb3a Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 11 Apr 2018 15:22:38 +0200 Subject: [PATCH 07/56] Revert "NewCarbsDialog: prefill with carbsReq." This reverts commit f8d022ba87cb7ca90412195d3c2df17403b1f54b. --- .../Overview/Dialogs/NewCarbsDialog.java | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 93ba7c9d81..1725fed14f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -132,6 +132,9 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); + editCarbs = view.findViewById(R.id.newcarb_carbsamount); + editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); + startActivityTTCheckbox = view.findViewById(R.id.newcarbs_activity_tt); startActivityTTCheckbox.setOnCheckedChangeListener(this); startEatingSoonTTCheckbox = view.findViewById(R.id.newcarbs_eating_soon_tt); @@ -147,22 +150,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C editDuration = view.findViewById(R.id.new_carbs_duration); editDuration.setParams(0d, 0d, 10d, 1d, new DecimalFormat("0"), false, textWatcher); - editCarbs = view.findViewById(R.id.newcarb_carbsamount); - editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); - - if (MainApp.engineeringMode) { - // use SMB's carbs required as preset, check hypo TT if any - if (ConfigBuilderPlugin.getActiveAPS() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null) { - APSResult lastAPSResult = ConfigBuilderPlugin.getActiveAPS().getLastAPSResult(); - if (lastAPSResult != null && lastAPSResult instanceof DetermineBasalResultSMB && ((DetermineBasalResultSMB) lastAPSResult).carbsReq > 0) { - editCarbs.setValue(((DetermineBasalResultSMB) lastAPSResult).carbsReq); - startHypoTTCheckbox.setOnCheckedChangeListener(null); - startHypoTTCheckbox.setChecked(true); - startHypoTTCheckbox.setOnClickListener(this); - } - } - } - fav1Button = view.findViewById(R.id.newcarbs_plus1); fav1Button.setOnClickListener(this); fav1Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))); From d0edd89b5b81c2f3ec0c3d1cc77c2f86715ea0f3 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 11 Apr 2018 15:42:51 +0200 Subject: [PATCH 08/56] Remove CB.getActiveLoop(), use LoopPlugin.getPlugin(). --- .../androidaps/data/QuickWizardEntry.java | 5 +- .../ConfigBuilder/ConfigBuilderPlugin.java | 9 +- .../androidaps/plugins/Loop/LoopPlugin.java | 2 + .../Overview/Dialogs/WizardDialog.java | 7 +- .../plugins/Overview/OverviewFragment.java | 158 +++++++++--------- .../SmsCommunicatorPlugin.java | 6 +- .../plugins/Wear/ActionStringHandler.java | 18 +- .../androidaps/plugins/Wear/WearPlugin.java | 6 +- .../wearintegration/WatchUpdaterService.java | 6 +- .../XDripStatusline/StatuslinePlugin.java | 13 +- .../nightscout/utils/LocalAlertUtils.java | 3 +- 11 files changed, 107 insertions(+), 126 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java index 4a94db0a44..e4cd50c490 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java @@ -11,7 +11,6 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; @@ -119,8 +118,8 @@ public class QuickWizardEntry { if (useSuperBolus() == YES && SP.getBoolean(R.string.key_usesuperbolus, false)) { superBolus = true; } - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus()) + final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); + if (loopPlugin.isEnabled(loopPlugin.getType()) && loopPlugin.isSuperBolus()) superBolus = false; // Trend diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java index 4ffec6aef3..06ddbef86f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java @@ -264,11 +264,6 @@ public class ConfigBuilderPlugin extends PluginBase { return activeAPS; } - @Nullable - public static LoopPlugin getActiveLoop() { - return activeLoop; - } - public static PumpInterface getActivePump() { return activePump; } @@ -622,7 +617,7 @@ public class ConfigBuilderPlugin extends PluginBase { } public void disconnectPump(int durationInMinutes, Profile profile) { - getActiveLoop().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L); + LoopPlugin.getPlugin().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L); getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() { @Override public void run() { @@ -645,7 +640,7 @@ public class ConfigBuilderPlugin extends PluginBase { } public void suspendLoop(int durationInMinutes) { - getActiveLoop().suspendTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000); + LoopPlugin.getPlugin().suspendTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000); getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java index e29eda04dc..e5510aae00 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java @@ -9,6 +9,7 @@ import android.app.TaskStackBuilder; import android.content.Context; import android.content.Intent; import android.os.Build; +import android.support.annotation.NonNull; import android.support.v4.app.NotificationCompat; import com.crashlytics.android.answers.CustomEvent; @@ -56,6 +57,7 @@ public class LoopPlugin extends PluginBase { protected static LoopPlugin loopPlugin; + @NonNull public static LoopPlugin getPlugin() { if (loopPlugin == null) { loopPlugin = new LoopPlugin(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index f44e570774..962254e503 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -53,6 +53,7 @@ import info.nightscout.androidaps.events.EventFeatureRunning; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; @@ -334,9 +335,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com accepted = true; if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { if (useSuperBolus) { - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - if (activeloop != null) { - activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); + final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); + if (loopPlugin.isEnabled(PluginType.LOOP)) { + loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); MainApp.bus().post(new EventRefreshOverview("WizardDialog")); } ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index a05df99efd..93d5b81724 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -457,16 +457,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); if (v == apsModeView) { - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); + final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); final PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription(); - if (!MainApp.getConfigBuilder().isProfileValid("ContexMenuCreation")) + if (loopPlugin == null || !MainApp.getConfigBuilder().isProfileValid("ContexMenuCreation")) return; menu.setHeaderTitle(MainApp.gs(R.string.loop)); - if (activeloop == null) { - menu.add(MainApp.gs(R.string.enableloop)); - } else { + if (loopPlugin.isEnabled(PluginType.LOOP)) { menu.add(MainApp.gs(R.string.disableloop)); - if (!activeloop.isSuspended()) { + if (!loopPlugin.isSuspended()) { menu.add(MainApp.gs(R.string.suspendloopfor1h)); menu.add(MainApp.gs(R.string.suspendloopfor2h)); menu.add(MainApp.gs(R.string.suspendloopfor3h)); @@ -482,6 +480,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, menu.add(MainApp.gs(R.string.resume)); } } + if (!loopPlugin.isEnabled(PluginType.LOOP)) + menu.add(MainApp.gs(R.string.enableloop)); } else if (v == activeProfileView) { menu.setHeaderTitle(MainApp.gs(R.string.profile)); menu.add(MainApp.gs(R.string.danar_viewprofile)); @@ -496,10 +496,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) return true; + final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); if (item.getTitle().equals(MainApp.gs(R.string.disableloop))) { - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - activeloop.setPluginEnabled(PluginType.LOOP, false); - activeloop.setFragmentVisible(PluginType.LOOP, false); + loopPlugin.setPluginEnabled(PluginType.LOOP, false); + loopPlugin.setFragmentVisible(PluginType.LOOP, false); MainApp.getConfigBuilder().storeSettings("DisablingLoop"); updateGUI("suspendmenu"); ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @@ -513,7 +513,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, NSUpload.uploadOpenAPSOffline(24 * 60); // upload 24h, we don't know real duration return true; } else if (item.getTitle().equals(MainApp.gs(R.string.enableloop))) { - final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); loopPlugin.setPluginEnabled(PluginType.LOOP, true); loopPlugin.setFragmentVisible(PluginType.LOOP, true); MainApp.getConfigBuilder().storeSettings("EnablingLoop"); @@ -521,8 +520,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, NSUpload.uploadOpenAPSOffline(0); return true; } else if (item.getTitle().equals(MainApp.gs(R.string.resume))) { - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - activeloop.suspendTo(0L); + loopPlugin.suspendTo(0L); updateGUI("suspendmenu"); ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override @@ -675,36 +673,34 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, private void onClickAcceptTemp() { Profile profile = MainApp.getConfigBuilder().getProfile(); - if (ConfigBuilderPlugin.getActiveLoop() != null && profile != null) { - ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false); + if (LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && profile != null) { + LoopPlugin.getPlugin().invoke("Accept temp button", false); final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.isChangeRequested()) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(getContext().getString(R.string.confirmation)); builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); - builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - hideTempRecommendation(); - clearNotification(); - MainApp.getConfigBuilder().applyTBRRequest(finalLastRun.constraintsProcessed, profile, new Callback() { - @Override - public void run() { - if (result.enacted) { - finalLastRun.tbrSetByPump = result; - finalLastRun.lastEnact = new Date(); - finalLastRun.lastOpenModeAccept = new Date(); - NSUpload.uploadDeviceStatus(); - ObjectivesPlugin objectivesPlugin = MainApp.getSpecificPlugin(ObjectivesPlugin.class); - if (objectivesPlugin != null) { - ObjectivesPlugin.manualEnacts++; - ObjectivesPlugin.saveProgress(); - } + builder.setPositiveButton(getContext().getString(R.string.ok), (dialog, id) -> { + hideTempRecommendation(); + clearNotification(); + MainApp.getConfigBuilder().applyTBRRequest(finalLastRun.constraintsProcessed, profile, new Callback() { + @Override + public void run() { + if (result.enacted) { + finalLastRun.tbrSetByPump = result; + finalLastRun.lastEnact = new Date(); + finalLastRun.lastOpenModeAccept = new Date(); + NSUpload.uploadDeviceStatus(); + ObjectivesPlugin objectivesPlugin = MainApp.getSpecificPlugin(ObjectivesPlugin.class); + if (objectivesPlugin != null) { + ObjectivesPlugin.manualEnacts++; + ObjectivesPlugin.saveProgress(); } - scheduleUpdateGUI("onClickAcceptTemp"); } - }); - FabricPrivacy.getInstance().logCustom(new CustomEvent("AcceptTemp")); - } + scheduleUpdateGUI("onClickAcceptTemp"); + } + }); + FabricPrivacy.getInstance().logCustom(new CustomEvent("AcceptTemp")); }); builder.setNegativeButton(getContext().getString(R.string.cancel), null); builder.show(); @@ -770,57 +766,55 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, accepted = false; builder.setTitle(MainApp.gs(R.string.confirmation)); builder.setMessage(confirmMessage); - builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - synchronized (builder) { - if (accepted) { - log.debug("guarding: already accepted"); - return; - } - accepted = true; - if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { - if (wizard.superBolus) { - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - if (activeloop != null) { - activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); - MainApp.bus().post(new EventRefreshOverview("WizardDialog")); - } - ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); + builder.setPositiveButton(getString(R.string.ok), (dialog, id) -> { + synchronized (builder) { + if (accepted) { + log.debug("guarding: already accepted"); + return; + } + accepted = true; + if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { + if (wizard.superBolus) { + final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); + if (loopPlugin.isEnabled(PluginType.LOOP)) { + loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); + MainApp.bus().post(new EventRefreshOverview("WizardDialog")); } - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; - detailedBolusInfo.insulin = finalInsulinAfterConstraints; - detailedBolusInfo.carbs = finalCarbsAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.boluscalc = boluscalcJSON; - detailedBolusInfo.source = Source.USER; - ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { + ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() { @Override public void run() { if (!result.success) { Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); i.putExtra("soundid", R.raw.boluserror); i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); + i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); MainApp.instance().startActivity(i); } } }); - FabricPrivacy.getInstance().logCustom(new CustomEvent("QuickWizard")); } + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.carbs = finalCarbsAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.boluscalc = boluscalcJSON; + detailedBolusInfo.source = Source.USER; + ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { + @Override + public void run() { + if (!result.success) { + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } + } + }); + FabricPrivacy.getInstance().logCustom(new CustomEvent("QuickWizard")); } } }); @@ -1026,24 +1020,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, apsModeView.setVisibility(View.VISIBLE); apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.loopenabled)); apsModeView.setTextColor(Color.BLACK); - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus()) { + final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); + if (loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isSuperBolus()) { apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); - apsModeView.setText(String.format(MainApp.gs(R.string.loopsuperbolusfor), activeloop.minutesToEndOfSuspend())); + apsModeView.setText(String.format(MainApp.gs(R.string.loopsuperbolusfor), loopPlugin.minutesToEndOfSuspend())); apsModeView.setTextColor(Color.WHITE); - } else if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isDisconnected()) { + } else if (loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isDisconnected()) { apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); - apsModeView.setText(String.format(MainApp.gs(R.string.loopdisconnectedfor), activeloop.minutesToEndOfSuspend())); + apsModeView.setText(String.format(MainApp.gs(R.string.loopdisconnectedfor), loopPlugin.minutesToEndOfSuspend())); apsModeView.setTextColor(Color.WHITE); - } else if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuspended()) { + } else if (loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isSuspended()) { apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); - apsModeView.setText(String.format(MainApp.gs(R.string.loopsuspendedfor), activeloop.minutesToEndOfSuspend())); + apsModeView.setText(String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend())); apsModeView.setTextColor(Color.WHITE); } else if (pump.isSuspended()) { apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); apsModeView.setText(MainApp.gs(R.string.pumpsuspended)); apsModeView.setTextColor(Color.WHITE); - } else if (activeloop != null && activeloop.isEnabled(activeloop.getType())) { + } else if (loopPlugin.isEnabled(PluginType.LOOP)) { if (closedLoopEnabled.value()) { apsModeView.setText(MainApp.gs(R.string.closedloop)); } else { @@ -1079,7 +1073,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.isChangeRequested(); // change is requested - if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) { + if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) { acceptTempLayout.setVisibility(View.VISIBLE); acceptTempButton.setText(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); } else { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java index 8308a2eb92..a0192a528c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java @@ -279,8 +279,7 @@ public class SmsCommunicatorPlugin extends PluginBase { FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Loop_Status")); break; case "RESUME": - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - activeloop.suspendTo(0); + LoopPlugin.getPlugin().suspendTo(0); MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_RESUME")); NSUpload.uploadOpenAPSOffline(0); reply = MainApp.sResources.getString(R.string.smscommunicator_loopresumed); @@ -517,8 +516,7 @@ public class SmsCommunicatorPlugin extends PluginBase { @Override public void run() { if (result.success) { - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - activeloop.suspendTo(System.currentTimeMillis() + suspendWaitingForConfirmation.duration * 60L * 1000); + LoopPlugin.getPlugin().suspendTo(System.currentTimeMillis() + suspendWaitingForConfirmation.duration * 60L * 1000); NSUpload.uploadOpenAPSOffline(suspendWaitingForConfirmation.duration * 60); MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_SUSPENDED")); String reply = MainApp.sResources.getString(R.string.smscommunicator_loopsuspended) + " " + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java index 48969d3dce..13d60a991d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java @@ -441,21 +441,21 @@ public class ActionStringHandler { private static String getLoopStatus() { String ret = ""; // decide if enabled/disabled closed/open; what Plugin as APS? - final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); - if (activeloop != null && activeloop.isEnabled(activeloop.getType())) { + final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); + if (loopPlugin.isEnabled(loopPlugin.getType())) { if (MainApp.getConstraintChecker().isClosedLoopAllowed().value()) { ret += "CLOSED LOOP\n"; } else { ret += "OPEN LOOP\n"; } - final APSInterface aps = MainApp.getConfigBuilder().getActiveAPS(); + final APSInterface aps = ConfigBuilderPlugin.getActiveAPS(); ret += "APS: " + ((aps == null) ? "NO APS SELECTED!" : ((PluginBase) aps).getName()); - if (activeloop.lastRun != null) { - if (activeloop.lastRun.lastAPSRun != null) - ret += "\nLast Run: " + DateUtil.timeString(activeloop.lastRun.lastAPSRun); + if (LoopPlugin.lastRun != null) { + if (LoopPlugin.lastRun.lastAPSRun != null) + ret += "\nLast Run: " + DateUtil.timeString(LoopPlugin.lastRun.lastAPSRun); - if (activeloop.lastRun.lastEnact != null) - ret += "\nLast Enact: " + DateUtil.timeString(activeloop.lastRun.lastEnact); + if (LoopPlugin.lastRun.lastEnact != null) + ret += "\nLast Enact: " + DateUtil.timeString(LoopPlugin.lastRun.lastEnact); } @@ -502,7 +502,7 @@ public class ActionStringHandler { return "No profile set :("; } - APSInterface usedAPS = MainApp.getConfigBuilder().getActiveAPS(); + APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS(); if (usedAPS == null) { return "No active APS :(!"; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java index 668ec3f829..dcda0bc0aa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java @@ -140,11 +140,7 @@ public class WearPlugin extends PluginBase { @Subscribe public void onStatusEvent(final EventRefreshOverview ev) { - - LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); - if (activeloop == null) return; - - if (WatchUpdaterService.shouldReportLoopStatus(activeloop.isEnabled(PluginType.LOOP))) { + if (WatchUpdaterService.shouldReportLoopStatus(LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))) { sendDataToWatch(true, false, false); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java index bde197b45f..a92738d336 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java @@ -666,12 +666,12 @@ public class WatchUpdaterService extends WearableListenerService implements return status; } - LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); + LoopPlugin activeloop = LoopPlugin.getPlugin(); - if (activeloop != null && !activeloop.isEnabled(PluginType.LOOP)) { + if (!activeloop.isEnabled(PluginType.LOOP)) { status += getString(R.string.disabledloop) + "\n"; lastLoopStatus = false; - } else if (activeloop != null && activeloop.isEnabled(PluginType.LOOP)) { + } else { lastLoopStatus = true; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java index b6b3c07e34..5ce277e399 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java @@ -108,12 +108,12 @@ public class StatuslinePlugin extends PluginBase { @NonNull private String buildStatusString(Profile profile) { String status = ""; - LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); + LoopPlugin loopPlugin = LoopPlugin.getPlugin(); - if (activeloop != null && !activeloop.isEnabled(PluginType.LOOP)) { + if (!loopPlugin.isEnabled(PluginType.LOOP)) { status += ctx.getString(R.string.disabledloop) + "\n"; lastLoopStatus = false; - } else if (activeloop != null && activeloop.isEnabled(PluginType.LOOP)) { + } else if (loopPlugin.isEnabled(PluginType.LOOP)) { lastLoopStatus = true; } @@ -179,13 +179,8 @@ public class StatuslinePlugin extends PluginBase { @Subscribe public void onStatusEvent(final EventRefreshOverview ev) { - //Filter events where loop is (de)activated - - LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - if (activeloop == null) return; - - if ((lastLoopStatus != activeloop.isEnabled(PluginType.LOOP))) { + if ((lastLoopStatus != LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))) { sendStatus(); } } diff --git a/app/src/main/java/info/nightscout/utils/LocalAlertUtils.java b/app/src/main/java/info/nightscout/utils/LocalAlertUtils.java index 58814ceddb..24b0d2ff05 100644 --- a/app/src/main/java/info/nightscout/utils/LocalAlertUtils.java +++ b/app/src/main/java/info/nightscout/utils/LocalAlertUtils.java @@ -13,6 +13,7 @@ import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.receivers.KeepAliveReceiver; @@ -38,7 +39,7 @@ public class LocalAlertUtils { boolean nextAlarmOccurrenceReached = SP.getLong("nextPumpDisconnectedAlarm", 0L) < System.currentTimeMillis(); if (Config.APS && SP.getBoolean(MainApp.sResources.getString(R.string.key_enable_pump_unreachable_alert), true) - && isStatusOutdated && alarmTimeoutExpired && nextAlarmOccurrenceReached && !ConfigBuilderPlugin.getActiveLoop().isDisconnected()) { + && isStatusOutdated && alarmTimeoutExpired && nextAlarmOccurrenceReached && !LoopPlugin.getPlugin().isDisconnected()) { log.debug("Generating pump unreachable alarm. lastConnection: " + DateUtil.dateAndTimeString(lastConnection) + " isStatusOutdated: " + isStatusOutdated); Notification n = new Notification(Notification.PUMP_UNREACHABLE, MainApp.sResources.getString(R.string.pump_unreachable), Notification.URGENT); n.soundId = R.raw.alarm; From e6ec114eb74f702229bc435a4bfb6888ac61e1f4 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 11 Apr 2018 16:11:12 +0200 Subject: [PATCH 09/56] gradle 3.1.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b958e8ab96..9693b3a9c5 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } } dependencies { - classpath 'com.android.tools.build:gradle:3.1.0' + classpath 'com.android.tools.build:gradle:3.1.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From 83421c7266d1921ce20ea9f42bd470871dd548f7 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 11 Apr 2018 16:23:35 +0200 Subject: [PATCH 10/56] show tests in travis --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 15015ca255..72b483c9fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -50,7 +50,7 @@ def generateGitBuild = { -> } tasks.matching {it instanceof Test}.all { - testLogging.events = ["failed", "skipped"] + testLogging.events = ["failed", "skipped", "started"] testLogging.exceptionFormat = "full" } From 1acefaea3c822cbb0b44de3694cb54eda1ab5b1c Mon Sep 17 00:00:00 2001 From: Roumen Georgiev Date: Wed, 11 Apr 2018 18:09:08 +0300 Subject: [PATCH 11/56] adding device name to AndroidAPS started note --- .../java/info/nightscout/utils/NSUpload.java | 28 +------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index ad6cc45ab8..6cb110abde 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -466,7 +466,7 @@ public class NSUpload { try { data.put("eventType", "Note"); data.put("created_at", DateUtil.toISOString(new Date())); - data.put("notes", MainApp.sResources.getString(R.string.androidaps_start)); + data.put("notes", MainApp.sResources.getString(R.string.androidaps_start)+" - "+ Build.MANUFACTURER + " "+ Build.MODEL); } catch (JSONException e) { log.error("Unhandled exception", e); } @@ -476,33 +476,7 @@ public class NSUpload { intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); context.sendBroadcast(intent); DbLogger.dbAdd(intent, data.toString()); - // now adding another note with the device running AndroidAPS - uploadDeviceNote(); - } - } - - public static void uploadDeviceNote(){ - if (SP.getBoolean(R.string.key_ns_logappstartedevent, true)) { - Context context = MainApp.instance().getApplicationContext(); - Bundle bundle = new Bundle(); - bundle.putString("action", "dbAdd"); - bundle.putString("collection", "treatments"); - JSONObject data = new JSONObject(); - try { - data.put("eventType", "Note"); - data.put("created_at", DateUtil.toISOString(new Date())); - data.put("notes", "Started on "+ Build.MANUFACTURER + " "+ Build.MODEL); -// log.debug("Running on: "+Build.MANUFACTURER + " "+ Build.MODEL); - } catch (JSONException e) { - log.error("Unhandled exception", e); } - bundle.putString("data", data.toString()); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbAdd(intent, data.toString()); - } } public static void uploadEvent(String careportalEvent, long time) { From b1f66d086a76d9e60a817fff9faa62e703058872 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 12 Apr 2018 00:42:12 +0200 Subject: [PATCH 12/56] Fix overshoot on last carb record. --- .../androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 1725fed14f..8bd7c98f88 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -413,7 +413,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C long smallCarbAmount = Math.round(remainingCarbs / (editDuration.getValue() * 4)); if (smallCarbAmount == 0) smallCarbAmount = 1; while (remainingCarbs > 0) { - createCarb(smallCarbAmount, carbTime); + createCarb(Math.min(smallCarbAmount, (long) remainingCarbs), carbTime); remainingCarbs -= smallCarbAmount; carbTime += 15 * 60 * 1000; } From 5ef2502b4f461783d50ab627c9e64557cc706a39 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 12 Apr 2018 00:50:28 +0200 Subject: [PATCH 13/56] Saner types. --- .../androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 8bd7c98f88..ef12b1ca0f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -408,12 +408,12 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C if (duration == 0) { createCarb(carbsAfterConstraints, time); } else { - double remainingCarbs = carbsAfterConstraints; + long remainingCarbs = carbsAfterConstraints; long carbTime = time; long smallCarbAmount = Math.round(remainingCarbs / (editDuration.getValue() * 4)); if (smallCarbAmount == 0) smallCarbAmount = 1; while (remainingCarbs > 0) { - createCarb(Math.min(smallCarbAmount, (long) remainingCarbs), carbTime); + createCarb(Math.min(smallCarbAmount, remainingCarbs), carbTime); remainingCarbs -= smallCarbAmount; carbTime += 15 * 60 * 1000; } From 613b8a2f30f9c47d8ca68cbf27bd58bdbae008bc Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 12 Apr 2018 09:40:12 +0200 Subject: [PATCH 14/56] log profile conditional --- app/src/main/java/info/nightscout/androidaps/Config.java | 1 + app/src/main/java/info/nightscout/androidaps/data/Profile.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index ff7b935355..afb40421df 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -37,6 +37,7 @@ public class Config { public static final boolean logCongigBuilderActions = true; public static final boolean logAutosensData = false; public static final boolean logEvents = false; + public static final boolean logProfile = false; // DanaR specific public static final boolean logDanaBTComm = true; diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java index e966c4d11d..783124168f 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -12,6 +12,7 @@ import java.text.DecimalFormat; import java.util.Calendar; import java.util.TimeZone; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -275,7 +276,7 @@ public class Profile { Integer getShitfTimeSecs(Integer originalTime) { Integer shiftedTime = originalTime + timeshift * 60 * 60; shiftedTime = (shiftedTime + 24 * 60 * 60) % (24 * 60 * 60); - if (timeshift != 0) + if (timeshift != 0 && Config.logProfile) log.debug("(Sec) Original time: " + originalTime + " ShiftedTime: " + shiftedTime); return shiftedTime; } From 80e81b1c25152bfae43fdf3d6b2e4ceb97ffaaed Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 12 Apr 2018 09:53:14 +0200 Subject: [PATCH 15/56] fix NPE --- .../java/info/nightscout/androidaps/queue/QueueThread.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java index f9e0739b45..8ec61932c8 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java @@ -53,6 +53,12 @@ public class QueueThread extends Thread { try { while (true) { PumpInterface pump = ConfigBuilderPlugin.getActivePump(); + if (pump == null) { + log.debug("QUEUE: pump == null"); + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.pumpNotInitialized))); + SystemClock.sleep(1000); + continue; + } long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000; if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) { From dfc869ba2bdbd0726989206c0afd4f234938ac47 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 12 Apr 2018 10:17:59 +0200 Subject: [PATCH 16/56] upload temptargets to NS properly --- .../interfaces/TreatmentsInterface.java | 1 + .../Dialogs/NewNSTreatmentDialog.java | 3 +-- .../Overview/Dialogs/NewCarbsDialog.java | 6 +++--- .../Overview/Dialogs/NewInsulinDialog.java | 2 +- .../plugins/Treatments/TreatmentsPlugin.java | 7 +++++++ .../plugins/Wear/ActionStringHandler.java | 5 +---- .../java/info/nightscout/utils/NSUpload.java | 17 +++++++++++++++++ 7 files changed, 31 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java index 30610ca2f6..27a6a0846b 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java @@ -55,6 +55,7 @@ public interface TreatmentsInterface { TempTarget getTempTargetFromHistory(); TempTarget getTempTargetFromHistory(long time); Intervals getTempTargetsFromHistory(); + void addToHistoryTempTarget(TempTarget tempTarget); ProfileSwitch getProfileSwitchFromHistory(long time); ProfileIntervals getProfileSwitchesFromHistory(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index 61122fb0c2..ab332dbe10 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -707,8 +707,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } else { tempTarget.low(0).high(0); } - log.debug("Creating new TempTarget db record: " + tempTarget.toString()); - MainApp.getDbHelper().createOrUpdate(tempTarget); + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); NSUpload.uploadCareportalEntryToNS(data); FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget")); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 19119450df..08f74773f3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -388,7 +388,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D .source(Source.USER) .low(Profile.toMgdl(finalActivityTT, currentProfile.getUnits())) .high(Profile.toMgdl(finalActivityTT, currentProfile.getUnits())); - MainApp.getDbHelper().createOrUpdate(tempTarget); + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); } else if (startEatingSoonTTCheckbox.isChecked()) { TempTarget tempTarget = new TempTarget() .date(System.currentTimeMillis()) @@ -397,7 +397,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D .source(Source.USER) .low(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits())) .high(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits())); - MainApp.getDbHelper().createOrUpdate(tempTarget); + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); } else if (startHypoTTCheckbox.isChecked()) { TempTarget tempTarget = new TempTarget() .date(System.currentTimeMillis()) @@ -406,7 +406,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D .source(Source.USER) .low(Profile.toMgdl(finalHypoTT, currentProfile.getUnits())) .high(Profile.toMgdl(finalHypoTT, currentProfile.getUnits())); - MainApp.getDbHelper().createOrUpdate(tempTarget); + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); } if (finalCarbsAfterConstraints > 0) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java index ce19009cf8..58971e3d80 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java @@ -288,7 +288,7 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener, .source(Source.USER) .low((int) finalTT) .high((int) finalTT); - MainApp.getDbHelper().createOrUpdate(tempTarget); + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); } if (finalInsulinAfterConstraints <= 0.01) { 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 36fac67834..2f5135c0cb 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 @@ -505,6 +505,13 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } } + @Override + public void addToHistoryTempTarget(TempTarget tempTarget) { + //log.debug("Adding new TemporaryBasal record" + profileSwitch.log()); + MainApp.getDbHelper().createOrUpdate(tempTarget); + NSUpload.uploadTempTarget(tempTarget); + } + // Profile Switch @Subscribe @SuppressWarnings("unused") diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java index 13d60a991d..fdc14f32d4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java @@ -622,10 +622,7 @@ public class ActionStringHandler { } else { tempTarget.low(0).high(0); } - MainApp.getDbHelper().createOrUpdate(tempTarget); - - //TODO: Nightscout-Treatment for Temp-Target! - //ConfigBuilderPlugin.uploadCareportalEntryToNS(data); + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); } private static void doFillBolus(final Double amount) { diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index 6cb110abde..f78e32f15d 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -28,6 +28,7 @@ import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.APSResult; @@ -302,6 +303,22 @@ public class NSUpload { } } + public static void uploadTempTarget(TempTarget tempTarget) { + try { + JSONObject data = new JSONObject(); + data.put("eventType", CareportalEvent.TEMPORARYTARGET); + data.put("duration", tempTarget.durationInMinutes); + data.put("reason", tempTarget.reason); + data.put("targetBottom", tempTarget.low); + data.put("targetTop", tempTarget.high); + data.put("created_at", DateUtil.toISOString(tempTarget.date)); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + uploadCareportalEntryToNS(data); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + } + public static void updateProfileSwitch(ProfileSwitch profileSwitch) { try { JSONObject data = new JSONObject(); From 5eee8054c45f2ebb6b586f95edad3fabd4b7bc0f Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 12 Apr 2018 10:21:38 +0200 Subject: [PATCH 17/56] remove duplicate upload --- .../plugins/Careportal/Dialogs/NewNSTreatmentDialog.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index ab332dbe10..a79e139a32 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -708,7 +708,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick tempTarget.low(0).high(0); } TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); - NSUpload.uploadCareportalEntryToNS(data); FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget")); } } catch (JSONException e) { From 0a377eb98e53914d136bc557b785fa15c19a668b Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 12 Apr 2018 10:32:52 +0200 Subject: [PATCH 18/56] cleanup --- .../Dialogs/NewNSTreatmentDialog.java | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index a79e139a32..b0c74eb390 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -54,6 +54,7 @@ import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.utils.DateUtil; import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.HardLimits; +import info.nightscout.utils.JsonHelper; import info.nightscout.utils.NSUpload; import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SP; @@ -694,24 +695,24 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } } } else if (options.executeTempTarget) { - try { - if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration") && data.getInt("duration") == 0)) { - TempTarget tempTarget = new TempTarget() - .date(eventTime.getTime()) - .duration(data.getInt("duration")) - .reason(data.getString("reason")) - .source(Source.USER); - if (tempTarget.durationInMinutes != 0) { - tempTarget.low(Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits())) - .high(Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits())); - } else { - tempTarget.low(0).high(0); - } - TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); - FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget")); + final int duration = JsonHelper.safeGetInt(data, "duration"); + final double targetBottom = JsonHelper.safeGetDouble(data, "targetBottom"); + final double targetTop = JsonHelper.safeGetDouble(data, "targetTop"); + final String reason = JsonHelper.safeGetString(data, "reason", ""); + if ((targetBottom != 0d && targetTop != 0d) || duration == 0) { + TempTarget tempTarget = new TempTarget() + .date(eventTime.getTime()) + .duration(duration) + .reason(reason) + .source(Source.USER); + if (tempTarget.durationInMinutes != 0) { + tempTarget.low(Profile.toMgdl(targetBottom, profile.getUnits())) + .high(Profile.toMgdl(targetTop, profile.getUnits())); + } else { + tempTarget.low(0).high(0); } - } catch (JSONException e) { - log.error("Unhandled exception", e); + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); + FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget")); } } else { NSUpload.uploadCareportalEntryToNS(data); From a075d87da1916dc21d10334d283c8fb78223d81b Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 12 Apr 2018 20:52:07 +0200 Subject: [PATCH 19/56] Remove help dialog. (cherry picked from commit b1ef8e1) --- .../Overview/Dialogs/NewCarbsDialog.java | 20 +------------------ .../res/layout/overview_newcarbs_dialog.xml | 13 ++++-------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index ef12b1ca0f..28e21bf0c4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -16,7 +16,6 @@ import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.CompoundButton; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RadioButton; @@ -39,8 +38,6 @@ import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Loop.APSResult; -import info.nightscout.androidaps.plugins.OpenAPSSMB.DetermineBasalResultSMB; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DateUtil; @@ -53,8 +50,6 @@ import info.nightscout.utils.ToastUtils; public class NewCarbsDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener { private static Logger log = LoggerFactory.getLogger(NewCarbsDialog.class); - private ImageView helpView; - private Button fav1Button; private Button fav2Button; private Button fav3Button; @@ -127,9 +122,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - helpView = view.findViewById(R.id.newcarbs_help); - helpView.setOnClickListener(this); - maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); editCarbs = view.findViewById(R.id.newcarb_carbsamount); @@ -147,6 +139,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C durationLayout = view.findViewById(R.id.newcarbs_duration_layout); durationLayout.setVisibility(MainApp.engineeringMode ? View.VISIBLE : View.GONE); + editDuration = view.findViewById(R.id.new_carbs_duration); editDuration.setParams(0d, 0d, 10d, 1d, new DecimalFormat("0"), false, textWatcher); @@ -180,17 +173,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C case R.id.cancel: dismiss(); break; - case R.id.newcarbs_help: - AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext()); - builder.setTitle("Help"); - builder.setMessage(Html.fromHtml("Time: relative offset to now
" + - "Duration: splits carb up over entered time, one every 15m
" + - "
" + - "Did I ever tell you the story about the old tree and the wooden house? So " + - "anyway, there I was, in the middle of the forest with all my clothes gone.
" + - "
Also: blablabla")); - builder.show(); - break; case R.id.newcarbs_plus1: editCarbs.setValue(Math.max(0, editCarbs.getValue() + SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))); diff --git a/app/src/main/res/layout/overview_newcarbs_dialog.xml b/app/src/main/res/layout/overview_newcarbs_dialog.xml index 944352af83..92fe1fc05d 100644 --- a/app/src/main/res/layout/overview_newcarbs_dialog.xml +++ b/app/src/main/res/layout/overview_newcarbs_dialog.xml @@ -36,20 +36,15 @@ - -
Date: Thu, 12 Apr 2018 20:55:45 +0200 Subject: [PATCH 20/56] Overview: fix rendering zero-temp covering entire displayed range. (cherry picked from commit 525eaef) --- .../androidaps/plugins/Overview/graphData/GraphData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java index 1a8816d0b3..9921d236a1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java @@ -172,7 +172,7 @@ public class GraphData { lastAbsoluteLineBasal = absoluteLineValue; lastLineBasal = baseBasalValue; lastTempBasal = tempBasalValue; - maxBasalValueFound = Math.max(maxBasalValueFound, basal); + maxBasalValueFound = Math.max(maxBasalValueFound, Math.max(tempBasalValue, baseBasalValue)); } basalLineArray.add(new ScaledDataPoint(toTime, lastLineBasal, basalScale)); From 42e36ab81897c559325d126d4f2e4be21736accf Mon Sep 17 00:00:00 2001 From: "Markus M. May" Date: Thu, 12 Apr 2018 21:08:06 +0200 Subject: [PATCH 21/56] Fix #842 --- .../ObjectivesFragment.java | 108 +++++++++++++----- .../ObjectivesFragmentTest.java | 71 ++++++++++++ 2 files changed, 150 insertions(+), 29 deletions(-) create mode 100644 app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragmentTest.java diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java index 23f5cb1fb8..688c741329 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java @@ -85,37 +85,52 @@ public class ObjectivesFragment extends SubscriberFragment { } }); - Long now = System.currentTimeMillis(); - if (position > 0 && objectives.get(position - 1).accomplished.getTime() == 0) { - // Phase 0: previous not completed - holder.startedLayout.setVisibility(View.GONE); - holder.durationLayout.setVisibility(View.GONE); - holder.progressLayout.setVisibility(View.GONE); - holder.verifyLayout.setVisibility(View.GONE); - } else if (o.started.getTime() == 0) { - // Phase 1: not started - holder.durationLayout.setVisibility(View.GONE); - holder.progressLayout.setVisibility(View.GONE); - holder.verifyLayout.setVisibility(View.GONE); - holder.started.setVisibility(View.GONE); - } else if (o.started.getTime() > 0 && !enableFake.isChecked() && o.accomplished.getTime() == 0 && !(o.started.getTime() + o.durationInDays * 24 * 60 * 60 * 1000 < now && requirementsMet.done)) { - // Phase 2: started, waiting for duration and met requirements - holder.startButton.setEnabled(false); - holder.verifyLayout.setVisibility(View.GONE); - } else if (o.accomplished.getTime() == 0) { - // Phase 3: started, after duration, requirements met - holder.startButton.setEnabled(false); - holder.accomplished.setVisibility(View.INVISIBLE); - } else { - // Phase 4: verified - holder.gateLayout.setVisibility(View.GONE); - holder.startedLayout.setVisibility(View.GONE); - holder.durationLayout.setVisibility(View.GONE); - holder.progressLayout.setVisibility(View.GONE); - holder.verifyButton.setVisibility(View.INVISIBLE); + long prevObjectiveAccomplishedTime = position > 0 ? + objectives.get(position - 1).accomplished.getTime() : -1; + + int phase = modifyVisibility(position, prevObjectiveAccomplishedTime, + o.started.getTime(), o.durationInDays, + o.accomplished.getTime(), requirementsMet.done, enableFake.isChecked()); + + switch (phase) { + case 0: + // Phase 0: previous not completed + holder.startedLayout.setVisibility(View.GONE); + holder.durationLayout.setVisibility(View.GONE); + holder.progressLayout.setVisibility(View.GONE); + holder.verifyLayout.setVisibility(View.GONE); + break; + case 1: + // Phase 1: not started + holder.durationLayout.setVisibility(View.GONE); + holder.progressLayout.setVisibility(View.GONE); + holder.verifyLayout.setVisibility(View.GONE); + holder.started.setVisibility(View.GONE); + break; + case 2: + // Phase 2: started, waiting for duration and met requirements + holder.startButton.setEnabled(false); + holder.verifyLayout.setVisibility(View.GONE); + break; + case 3: + // Phase 3: started, after duration, requirements met + holder.startButton.setEnabled(false); + holder.accomplished.setVisibility(View.INVISIBLE); + break; + case 4: + // Phase 4: verified + holder.gateLayout.setVisibility(View.GONE); + holder.startedLayout.setVisibility(View.GONE); + holder.durationLayout.setVisibility(View.GONE); + holder.progressLayout.setVisibility(View.GONE); + holder.verifyButton.setVisibility(View.INVISIBLE); + break; + default: + // should not happen } } + @Override public int getItemCount() { return objectives.size(); @@ -164,6 +179,40 @@ public class ObjectivesFragment extends SubscriberFragment { } } + /** + * returns an int, which represents the phase the current objective is at. + * + * this is mainly used for unit-testing the conditions + * + * @param currentPosition + * @param prevObjectiveAccomplishedTime + * @param objectiveStartedTime + * @param durationInDays + * @param objectiveAccomplishedTime + * @param requirementsMet + * @return + */ + public int modifyVisibility(int currentPosition, + long prevObjectiveAccomplishedTime, + long objectiveStartedTime, int durationInDays, + long objectiveAccomplishedTime, boolean requirementsMet, + boolean enableFakeValue) { + Long now = System.currentTimeMillis(); + if (currentPosition > 0 && prevObjectiveAccomplishedTime == 0) { + return 0; + } else if (objectiveStartedTime == 0) { + return 1; + } else if (objectiveStartedTime > 0 && !enableFakeValue + && objectiveAccomplishedTime == 0 + && !(objectiveStartedTime + durationInDays * 24 * 60 * 60 * 1000 >= now && requirementsMet)) { + return 2; + } else if (objectiveAccomplishedTime == 0) { + return 3; + } else { + return 4; + } + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -205,6 +254,7 @@ public class ObjectivesFragment extends SubscriberFragment { ObjectivesPlugin.objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_gate); ObjectivesPlugin.objectives.get(4).gate = MainApp.sResources.getString(R.string.objectives_4_gate); ObjectivesPlugin.objectives.get(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate); + updateGUI(); return view; @@ -225,4 +275,4 @@ public class ObjectivesFragment extends SubscriberFragment { }); } -} +} \ No newline at end of file diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragmentTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragmentTest.java new file mode 100644 index 0000000000..a4119e97e3 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragmentTest.java @@ -0,0 +1,71 @@ +package info.nightscout.androidaps.plugins.ConstraintsObjectives; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +public class ObjectivesFragmentTest { + + @Test + public void testModifyVisibility() { + + ObjectivesFragment fragment = new ObjectivesFragment(); + + int currentPosition = 1; + long prevObjectiveAccomplishedTime = 0; + long objectiveStartedTime = 0; + int durationInDays = 0; + long objectiveAccomplishedTime = 0; + boolean requirementsMet = false; + boolean enableFakeValue = false; + + // previous objective is not accomplished yet + assertEquals(0, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime, + objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue)); + + // not started yet + prevObjectiveAccomplishedTime = 4711; + assertEquals(1, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime, + objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue)); + + // started + // time calculation is true, requirements met is false + objectiveStartedTime = Long.MAX_VALUE; + durationInDays = 0; + assertEquals(2, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime, + objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue)); + + // started + // time calculation is false, requirements met is false + objectiveStartedTime = 10; + durationInDays = 0; + requirementsMet = true; + assertEquals(2, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime, + objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue)); + + // started + // time calculation is false, requirements met is true + objectiveStartedTime = 10; + durationInDays = 999999; + requirementsMet = true; + assertEquals(2, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime, + objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue)); + + // started, after duration, requirements met --> show verify + objectiveStartedTime = Long.MAX_VALUE; + durationInDays = 0; + requirementsMet = true; + assertEquals(3, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime, + objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue)); + + // finished + objectiveStartedTime = Long.MAX_VALUE; + durationInDays = 0; + requirementsMet = true; + objectiveAccomplishedTime = Long.MAX_VALUE; + assertEquals(4, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime, + objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue)); + + + } + +} \ No newline at end of file From 05e07cf943ae46e8f78f0115e489f350333c6faf Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 12 Apr 2018 21:28:32 +0200 Subject: [PATCH 22/56] Align style of labels, i18n. --- .../res/layout/overview_newcarbs_dialog.xml | 19 +++++++++++-------- app/src/main/res/values/strings.xml | 3 +++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/app/src/main/res/layout/overview_newcarbs_dialog.xml b/app/src/main/res/layout/overview_newcarbs_dialog.xml index 38dca30d8e..8d416467ef 100644 --- a/app/src/main/res/layout/overview_newcarbs_dialog.xml +++ b/app/src/main/res/layout/overview_newcarbs_dialog.xml @@ -125,7 +125,8 @@ android:layout_width="60dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:text="Time" /> + android:textStyle="bold" + android:text="@string/time" /> + android:text="@string/shortminute" /> + android:textStyle="bold" + android:text="@string/duration"/> + android:text="@string/shorthour"/> + android:textStyle="bold" + android:text="@string/overview_carbs_label" /> + android:text="@string/shortgramm" /> Connection timed out Food g + m + h ]]> kJ En @@ -995,4 +997,5 @@ openapsmb_max_iob Maximum total IOB OpenAPS can\'t go over [U] This value is called Max IOB in OpenAPS context\nOpenAPS will not add more insulin if current IOB is greater than this value + Time From bf02edd871a8e5dba5d837bb877b3d608e099533 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 12 Apr 2018 21:43:55 +0200 Subject: [PATCH 23/56] Make visibility of notes field a preference. --- .../androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java | 5 ++++- .../androidaps/plugins/Overview/Dialogs/WizardDialog.java | 3 +++ app/src/main/res/layout/overview_newcarbs_dialog.xml | 4 ++-- app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/xml/pref_overview.xml | 4 ++++ 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 8e0baabd99..ad603fa321 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -56,6 +56,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C private Button fav2Button; private Button fav3Button; + private LinearLayout notesLayout; private EditText notesEdit; private static final int FAV1_DEFAULT = 5; @@ -159,7 +160,9 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C fav3Button.setOnClickListener(this); fav3Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))); - notesEdit = (EditText) view.findViewById(R.id.newcarbs_notes); + notesLayout = view.findViewById(R.id.newcarbs_notes_layout); + notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE); + notesEdit = view.findViewById(R.id.newcarbs_notes); setCancelable(true); getDialog().setCanceledOnTouchOutside(false); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index 263bc7e090..b988a368fc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -105,6 +105,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com NumberPicker editCorr; NumberPicker editCarbTime; + LinearLayout notesLayout; EditText notesEdit; Integer calculatedCarbs = 0; @@ -209,6 +210,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com 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.newcarbs_notes); bgTrend = (TextView) view.findViewById(R.id.treatments_wizard_bgtrend); diff --git a/app/src/main/res/layout/overview_newcarbs_dialog.xml b/app/src/main/res/layout/overview_newcarbs_dialog.xml index 8d416467ef..09774fcd08 100644 --- a/app/src/main/res/layout/overview_newcarbs_dialog.xml +++ b/app/src/main/res/layout/overview_newcarbs_dialog.xml @@ -237,6 +237,7 @@ + android:layout_height="wrap_content" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 58c4eebc40..c205d0624a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -998,4 +998,6 @@ Maximum total IOB OpenAPS can\'t go over [U] This value is called Max IOB in OpenAPS context\nOpenAPS will not add more insulin if current IOB is greater than this value Time + show_notes_entry_dialogs + Show notes field in dialogs diff --git a/app/src/main/res/xml/pref_overview.xml b/app/src/main/res/xml/pref_overview.xml index aa0a188b31..a3d8245aa8 100644 --- a/app/src/main/res/xml/pref_overview.xml +++ b/app/src/main/res/xml/pref_overview.xml @@ -112,5 +112,9 @@ android:summary="@string/show_calibration_button_summary"/> + \ No newline at end of file From 54048b29c4a2469ad090076b18b317969134b33f Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 12 Apr 2018 21:45:59 +0200 Subject: [PATCH 24/56] NewNSTreatment dialog cleanup --- .../Dialogs/NewNSTreatmentDialog.java | 323 +++++++++--------- .../info/nightscout/utils/JsonHelper.java | 16 + app/src/test/java/info/AAPSMocker.java | 31 ++ app/src/test/java/info/BundleMock.java | 223 ++++++++++++ app/src/test/java/info/SPMocker.java | 3 +- .../Dialogs/NewNSTreatmentDialogTest.java | 63 ++++ 6 files changed, 489 insertions(+), 170 deletions(-) create mode 100644 app/src/test/java/info/BundleMock.java create mode 100644 app/src/test/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialogTest.java diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index b0c74eb390..c3f99dc630 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.Careportal.Dialogs; import android.app.Activity; -import android.content.DialogInterface; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; @@ -15,7 +14,6 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; -import android.widget.CompoundButton; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RadioButton; @@ -109,14 +107,14 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick public void setOptions(OptionsToShow options, int event) { this.options = options; - this.event = MainApp.sResources.getString(event); + this.event = MainApp.gs(event); } public NewNSTreatmentDialog() { super(); if (seconds == null) { - seconds = new Double(Math.random() * 59).intValue(); + seconds = Double.valueOf(Math.random() * 59).intValue(); } } @@ -136,7 +134,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (options == null) return null; - getDialog().setTitle(getString(options.eventName)); + getDialog().setTitle(MainApp.gs(options.eventName)); setStyle(DialogFragment.STYLE_NORMAL, getTheme()); View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false); @@ -193,32 +191,29 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick final Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, units); // temp target - final ArrayList reasonList = new ArrayList(); - reasonList.add(MainApp.sResources.getString(R.string.manual)); - reasonList.add(MainApp.sResources.getString(R.string.eatingsoon)); - reasonList.add(MainApp.sResources.getString(R.string.activity)); - ArrayAdapter adapterReason = new ArrayAdapter(getContext(), + final ArrayList reasonList = new ArrayList<>(); + reasonList.add(MainApp.gs(R.string.manual)); + reasonList.add(MainApp.gs(R.string.eatingsoon)); + reasonList.add(MainApp.gs(R.string.activity)); + ArrayAdapter adapterReason = new ArrayAdapter<>(getContext(), R.layout.spinner_centered, reasonList); reasonSpinner.setAdapter(adapterReason); reasonSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - double defaultDuration = 0; + double defaultDuration; double defaultTarget = 0; if (profile != null) { - defaultTarget = bg.doubleValue(); + defaultTarget = bg; } boolean erase = false; - if (MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))) { + if (MainApp.gs(R.string.eatingsoon).equals(reasonList.get(position))) { defaultDuration = SP.getDouble(R.string.key_eatingsoon_duration, 0d); defaultTarget = SP.getDouble(R.string.key_eatingsoon_target, 0d); - ; - } else if (MainApp.sResources.getString(R.string.activity).equals(reasonList.get(position))) { + } else if (MainApp.gs(R.string.activity).equals(reasonList.get(position))) { defaultDuration = SP.getDouble(R.string.key_activity_duration, 0d); - ; defaultTarget = SP.getDouble(R.string.key_activity_target, 0d); - ; } else { defaultDuration = 0; erase = true; @@ -267,12 +262,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher); editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false); } - sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits()); - editBg.setValue(bg); - } + sensorRadioButton.setOnCheckedChangeListener((buttonView, isChecked) -> { + Double bg1 = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits()); + editBg.setValue(bg1); }); Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); @@ -408,7 +400,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick tpd.show(context.getFragmentManager(), "Timepickerdialog"); break; case R.id.ok: - createNSTreatment(); + confirmNSTreatmentCreation(); dismiss(); break; case R.id.cancel: @@ -572,156 +564,151 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick String buildConfirmText(JSONObject data) { String ret = ""; - try { - if (data.has("eventType")) { - ret += getString(R.string.careportal_newnstreatment_eventtype); - ret += ": "; - ret += Translator.translate(data.getString("eventType")); - ret += "\n"; - } - if (data.has("glucose")) { - ret += getString(R.string.treatments_wizard_bg_label); - ret += ": "; - ret += data.get("glucose"); - ret += " " + units + "\n"; - } - if (data.has("glucoseType")) { - ret += getString(R.string.careportal_newnstreatment_glucosetype); - ret += ": "; - ret += Translator.translate(data.getString("glucoseType")); - ret += "\n"; - } - if (data.has("carbs")) { - ret += getString(R.string.careportal_newnstreatment_carbs_label); - ret += ": "; - ret += data.get("carbs"); - ret += " g\n"; - } - if (data.has("insulin")) { - ret += getString(R.string.careportal_newnstreatment_insulin_label); - ret += ": "; - ret += data.get("insulin"); - ret += " U\n"; - } - if (data.has("duration")) { - ret += getString(R.string.careportal_newnstreatment_duration_label); - ret += ": "; - ret += data.get("duration"); - ret += " min\n"; - } - if (data.has("percent")) { - ret += getString(R.string.careportal_newnstreatment_percent_label); - ret += ": "; - ret += data.get("percent"); - ret += " %\n"; - } - if (data.has("absolute")) { - ret += getString(R.string.careportal_newnstreatment_absolute_label); - ret += ": "; - ret += data.get("absolute"); - ret += " U/h\n"; - } - if (data.has("preBolus")) { - ret += getString(R.string.careportal_newnstreatment_carbtime_label); - ret += ": "; - ret += data.get("preBolus"); - ret += " min\n"; - } - if (data.has("notes")) { - ret += getString(R.string.careportal_newnstreatment_notes_label); - ret += ": "; - ret += data.get("notes"); - ret += "\n"; - } - if (data.has("profile")) { - ret += getString(R.string.careportal_newnstreatment_profile_label); - ret += ": "; - ret += data.get("profile"); - ret += "\n"; - } - if (data.has("percentage")) { - ret += getString(R.string.careportal_newnstreatment_percentage_label); - ret += ": "; - ret += data.get("percentage"); - ret += " %\n"; - } - if (data.has("timeshift")) { - ret += getString(R.string.careportal_newnstreatment_timeshift_label); - ret += ": "; - ret += data.get("timeshift"); - ret += " h\n"; - } - if (data.has("targetBottom") && data.has("targetTop")) { - ret += getString(R.string.target_range); - ret += " "; - ret += data.get("targetBottom"); - ret += " - "; - ret += data.get("targetTop"); - ret += "\n"; - } - if (data.has("created_at")) { - ret += getString(R.string.careportal_newnstreatment_eventtime_label); - ret += ": "; - ret += eventTime.toLocaleString(); - ret += "\n"; - } - if (data.has("enteredBy")) { - ret += getString(R.string.careportal_newnstreatment_enteredby_title); - ret += ": "; - ret += data.get("enteredBy"); - ret += "\n"; - } - } catch (JSONException e) { - log.error("Unhandled exception", e); + if (data.has("eventType")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_eventtype); + ret += ": "; + ret += Translator.translate(JsonHelper.safeGetString(data, "eventType", "")); + ret += "\n"; + } + if (data.has("glucose")) { + ret += MainApp.gs(R.string.treatments_wizard_bg_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "glucose", ""); + ret += " " + units + "\n"; + } + if (data.has("glucoseType")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_glucosetype); + ret += ": "; + ret += Translator.translate(JsonHelper.safeGetString(data, "glucoseType", "")); + ret += "\n"; + } + if (data.has("carbs")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_carbs_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "carbs", ""); + ret += " g\n"; + } + if (data.has("insulin")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_insulin_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "insulin", ""); + ret += " U\n"; + } + if (data.has("duration")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_duration_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "duration", ""); + ret += " min\n"; + } + if (data.has("percent")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_percent_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "percent", ""); + ret += " %\n"; + } + if (data.has("absolute")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_absolute_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "absolute", ""); + ret += " U/h\n"; + } + if (data.has("preBolus")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_carbtime_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "preBolus", ""); + ret += " min\n"; + } + if (data.has("notes")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_notes_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "notes", ""); + ret += "\n"; + } + if (data.has("profile")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_profile_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "profile", ""); + ret += "\n"; + } + if (data.has("percentage")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_percentage_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "percentage", ""); + ret += " %\n"; + } + if (data.has("timeshift")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_timeshift_label); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "timeshift", ""); + ret += " h\n"; + } + if (data.has("targetBottom") && data.has("targetTop")) { + ret += MainApp.gs(R.string.target_range); + ret += " "; + ret += JsonHelper.safeGetObject(data, "targetBottom", ""); + ret += " - "; + ret += JsonHelper.safeGetObject(data, "targetTop", ""); + ret += "\n"; + } + if (data.has("created_at")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_eventtime_label); + ret += ": "; + ret += eventTime.toLocaleString(); + ret += "\n"; + } + if (data.has("enteredBy")) { + ret += MainApp.gs(R.string.careportal_newnstreatment_enteredby_title); + ret += ": "; + ret += JsonHelper.safeGetObject(data, "enteredBy", ""); + ret += "\n"; } return ret; } - void createNSTreatment() { - final JSONObject data = gatherData(); - String confirmText = buildConfirmText(data); - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - builder.setTitle(getContext().getString(R.string.confirmation)); - builder.setMessage(confirmText); - builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - if (options.executeProfileSwitch) { - if (data.has("profile")) { - try { - doProfileSwitch(profileStore, data.getString("profile"), data.getInt("duration"), data.getInt("percentage"), data.getInt("timeshift")); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - } else if (options.executeTempTarget) { - final int duration = JsonHelper.safeGetInt(data, "duration"); - final double targetBottom = JsonHelper.safeGetDouble(data, "targetBottom"); - final double targetTop = JsonHelper.safeGetDouble(data, "targetTop"); - final String reason = JsonHelper.safeGetString(data, "reason", ""); - if ((targetBottom != 0d && targetTop != 0d) || duration == 0) { - TempTarget tempTarget = new TempTarget() - .date(eventTime.getTime()) - .duration(duration) - .reason(reason) - .source(Source.USER); - if (tempTarget.durationInMinutes != 0) { - tempTarget.low(Profile.toMgdl(targetBottom, profile.getUnits())) - .high(Profile.toMgdl(targetTop, profile.getUnits())); - } else { - tempTarget.low(0).high(0); - } - TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); - FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget")); - } - } else { - NSUpload.uploadCareportalEntryToNS(data); - FabricPrivacy.getInstance().logCustom(new CustomEvent("NSTreatment")); - } + void confirmNSTreatmentCreation() { + if (context != null) { + final JSONObject data = gatherData(); + final String confirmText = buildConfirmText(data); + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(MainApp.gs(R.string.confirmation)); + builder.setMessage(confirmText); + builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> createNSTreatment(data)); + builder.setNegativeButton(MainApp.gs(R.string.cancel), null); + builder.show(); + } + } + + + void createNSTreatment(JSONObject data) { + if (options.executeProfileSwitch) { + if (data.has("profile")) { + doProfileSwitch(profileStore, JsonHelper.safeGetString(data, "profile"), JsonHelper.safeGetInt(data, "duration"), JsonHelper.safeGetInt(data, "percentage"), JsonHelper.safeGetInt(data, "timeshift")); } - }); - builder.setNegativeButton(getContext().getString(R.string.cancel), null); - builder.show(); + } else if (options.executeTempTarget) { + final int duration = JsonHelper.safeGetInt(data, "duration"); + final double targetBottom = JsonHelper.safeGetDouble(data, "targetBottom"); + final double targetTop = JsonHelper.safeGetDouble(data, "targetTop"); + final String reason = JsonHelper.safeGetString(data, "reason", ""); + if ((targetBottom != 0d && targetTop != 0d) || duration == 0) { + TempTarget tempTarget = new TempTarget() + .date(eventTime.getTime()) + .duration(duration) + .reason(reason) + .source(Source.USER); + if (tempTarget.durationInMinutes != 0) { + tempTarget.low(Profile.toMgdl(targetBottom, profile.getUnits())) + .high(Profile.toMgdl(targetTop, profile.getUnits())); + } else { + tempTarget.low(0).high(0); + } + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); + FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget")); + } + } else { + NSUpload.uploadCareportalEntryToNS(data); + FabricPrivacy.getInstance().logCustom(new CustomEvent("NSTreatment")); + } } public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) { diff --git a/app/src/main/java/info/nightscout/utils/JsonHelper.java b/app/src/main/java/info/nightscout/utils/JsonHelper.java index ead68132af..503d0bf395 100644 --- a/app/src/main/java/info/nightscout/utils/JsonHelper.java +++ b/app/src/main/java/info/nightscout/utils/JsonHelper.java @@ -1,5 +1,7 @@ package info.nightscout.utils; +import android.support.annotation.Nullable; + import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; @@ -17,6 +19,20 @@ public class JsonHelper { private JsonHelper() {}; + public static Object safeGetObject(JSONObject json, String fieldName, Object defaultValue) { + Object result = defaultValue; + + if (json.has(fieldName)) { + try { + result = json.get(fieldName); + } catch (JSONException ignored) { + } + } + + return result; + } + + @Nullable public static String safeGetString(JSONObject json, String fieldName) { String result = null; diff --git a/app/src/test/java/info/AAPSMocker.java b/app/src/test/java/info/AAPSMocker.java index 1e11a5f401..0e8c5b2cdc 100644 --- a/app/src/test/java/info/AAPSMocker.java +++ b/app/src/test/java/info/AAPSMocker.java @@ -1,11 +1,17 @@ package info; import android.content.Context; +import android.content.Intent; +import android.os.Bundle; import com.squareup.otto.Bus; import org.json.JSONException; import org.json.JSONObject; +import org.junit.Assert; +import org.mockito.ArgumentMatchers; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.powermock.api.mockito.PowerMockito; import java.util.Locale; @@ -34,6 +40,8 @@ public class AAPSMocker { private static String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"; private static Profile profile; + public static Intent intentSent = null; + public static void mockStrings() { Locale.setDefault(new Locale("en", "US")); @@ -81,6 +89,7 @@ public class AAPSMocker { when(MainApp.gs(R.string.basalprofilenotaligned)).thenReturn("Basal values not aligned to hours: %s"); when(MainApp.gs(R.string.minago)).thenReturn("%d min ago"); when(MainApp.gs(R.string.hoursago)).thenReturn("%.1fh ago"); + when(MainApp.gs(R.string.careportal_profileswitch)).thenReturn("Profile Switch"); } public static MainApp mockMainApp() { @@ -116,6 +125,28 @@ public class AAPSMocker { public static void mockApplicationContext() { Context context = mock(Context.class); when(MainApp.instance().getApplicationContext()).thenReturn(context); + try { + PowerMockito.when(context, "sendBroadcast", ArgumentMatchers.any()).then(invocation -> { + Intent i = invocation.getArgument(0); + intentSent = i; + return null; + }); + } catch (Exception e) { + Assert.fail("Unable to mock the construction of the Context object: " + e.getMessage()); + } + } + + public static void mockBundle() { + try { + PowerMockito.whenNew(Bundle.class).withNoArguments().thenAnswer(new Answer() { + @Override + public Bundle answer(InvocationOnMock invocation) throws Throwable { + return BundleMock.mock(); + } + }); + } catch (Exception e) { + Assert.fail("Unable to mock the construction of the Bundle object: " + e.getMessage()); + } } public static void mockDatabaseHelper() { diff --git a/app/src/test/java/info/BundleMock.java b/app/src/test/java/info/BundleMock.java new file mode 100644 index 0000000000..62b4f28db6 --- /dev/null +++ b/app/src/test/java/info/BundleMock.java @@ -0,0 +1,223 @@ +package info; + +import android.os.Bundle; +import android.os.Parcelable; +import android.util.SparseArray; + +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyByte; +import static org.mockito.Matchers.anyChar; +import static org.mockito.Matchers.anyDouble; +import static org.mockito.Matchers.anyFloat; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyShort; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; + +public final class BundleMock { + + public static Bundle mock() { + return mock(new HashMap()); + } + + public static Bundle mock(final HashMap map) { + + Answer unsupported = new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + throw new UnsupportedOperationException(); + } + }; + Answer put = new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + map.put((String)invocation.getArguments()[0], invocation.getArguments()[1]); + return null; + } + }; + Answer get = new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + return map.get(invocation.getArguments()[0]); + } + }; + Answer getOrDefault = new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + Object key = invocation.getArguments()[0]; + return map.containsKey(key) ? map.get(key) : invocation.getArguments()[1]; + } + }; + + Bundle bundle = Mockito.mock(Bundle.class); + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + return map.size(); + } + }).when(bundle).size(); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + return map.isEmpty(); + } + }).when(bundle).isEmpty(); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + map.clear(); + return null; + } + }).when(bundle).clear(); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + return map.containsKey(invocation.getArguments()[0]); + } + }).when(bundle).containsKey(anyString()); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + return map.get(invocation.getArguments()[0]); + } + }).when(bundle).get(anyString()); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + map.remove(invocation.getArguments()[0]); + return null; + } + }).when(bundle).remove(anyString()); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + return map.keySet(); + } + }).when(bundle).keySet(); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + return BundleMock.class.getSimpleName() + "{map=" + map.toString() + "}"; + } + }).when(bundle).toString(); + + doAnswer(put).when(bundle).putBoolean(anyString(), anyBoolean()); + when(bundle.getBoolean(anyString())).thenAnswer(get); + when(bundle.getBoolean(anyString(), anyBoolean())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putByte(anyString(), anyByte()); + when(bundle.getByte(anyString())).thenAnswer(get); + when(bundle.getByte(anyString(), anyByte())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putChar(anyString(), anyChar()); + when(bundle.getChar(anyString())).thenAnswer(get); + when(bundle.getChar(anyString(), anyChar())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putInt(anyString(), anyShort()); + when(bundle.getShort(anyString())).thenAnswer(get); + when(bundle.getShort(anyString(), anyShort())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putLong(anyString(), anyLong()); + when(bundle.getLong(anyString())).thenAnswer(get); + when(bundle.getLong(anyString(), anyLong())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putFloat(anyString(), anyFloat()); + when(bundle.getFloat(anyString())).thenAnswer(get); + when(bundle.getFloat(anyString(), anyFloat())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putDouble(anyString(), anyDouble()); + when(bundle.getDouble(anyString())).thenAnswer(get); + when(bundle.getDouble(anyString(), anyDouble())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putString(anyString(), anyString()); + when(bundle.getString(anyString())).thenAnswer(get); + when(bundle.getString(anyString(), anyString())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putBooleanArray(anyString(), any(boolean[].class)); + when(bundle.getBooleanArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putLongArray(anyString(), any(long[].class)); + when(bundle.getLongArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putDoubleArray(anyString(), any(double[].class)); + when(bundle.getDoubleArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putIntArray(anyString(), any(int[].class)); + when(bundle.getIntArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putInt(anyString(), anyInt()); + when(bundle.getInt(anyString())).thenAnswer(get); + when(bundle.getInt(anyString(), anyInt())).thenAnswer(getOrDefault); + + doAnswer(unsupported).when(bundle).putAll(any(Bundle.class)); + when(bundle.hasFileDescriptors()).thenAnswer(unsupported); + + doAnswer(put).when(bundle).putShort(anyString(), anyShort()); + when(bundle.getShort(anyString())).thenAnswer(get); + when(bundle.getShort(anyString(), anyShort())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putFloat(anyString(), anyFloat()); + when(bundle.getFloat(anyString())).thenAnswer(get); + when(bundle.getFloat(anyString(), anyFloat())).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putCharSequence(anyString(), any(CharSequence.class)); + when(bundle.getCharSequence(anyString())).thenAnswer(get); + when(bundle.getCharSequence(anyString(), any(CharSequence.class))).thenAnswer(getOrDefault); + + doAnswer(put).when(bundle).putBundle(anyString(), any(Bundle.class)); + when(bundle.getBundle(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putParcelable(anyString(), any(Parcelable.class)); + when(bundle.getParcelable(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putParcelableArray(anyString(), any(Parcelable[].class)); + when(bundle.getParcelableArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putParcelableArrayList(anyString(), any(ArrayList.class)); + when(bundle.getParcelableArrayList(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putSparseParcelableArray(anyString(), any(SparseArray.class)); + when(bundle.getSparseParcelableArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putSerializable(anyString(), any(Serializable.class)); + when(bundle.getSerializable(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putIntegerArrayList(anyString(), any(ArrayList.class)); + when(bundle.getIntegerArrayList(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putStringArrayList(anyString(), any(ArrayList.class)); + when(bundle.getStringArrayList(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putCharSequenceArrayList(anyString(), any(ArrayList.class)); + when(bundle.getCharSequenceArrayList(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putCharArray(anyString(), any(char[].class)); + when(bundle.getCharArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putByteArray(anyString(), any(byte[].class)); + when(bundle.getByteArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putShortArray(anyString(), any(short[].class)); + when(bundle.getShortArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putFloatArray(anyString(), any(float[].class)); + when(bundle.getFloatArray(anyString())).thenAnswer(get); + + doAnswer(put).when(bundle).putCharSequenceArray(anyString(), any(CharSequence[].class)); + when(bundle.getCharSequenceArray(anyString())).thenAnswer(get); + + return bundle; + } +} \ No newline at end of file diff --git a/app/src/test/java/info/SPMocker.java b/app/src/test/java/info/SPMocker.java index 29fbdaa230..a6663175c6 100644 --- a/app/src/test/java/info/SPMocker.java +++ b/app/src/test/java/info/SPMocker.java @@ -36,8 +36,7 @@ public class SPMocker { return value; }); } catch (Exception e) { - Assert.fail("Unable to mock the construction of " - + "the SP object"); + Assert.fail("Unable to mock the construction of the SP object"); } } diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialogTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialogTest.java new file mode 100644 index 0000000000..d25faa0d45 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialogTest.java @@ -0,0 +1,63 @@ +package info.nightscout.androidaps.plugins.Careportal.Dialogs; + +import android.content.Context; +import android.os.Bundle; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.AAPSMocker; +import info.BundleMock; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; +import info.nightscout.utils.SP; + +import static org.junit.Assert.*; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, SP.class, Context.class}) +public class NewNSTreatmentDialogTest { + + NewNSTreatmentDialog dialog; + + @Test + public void createNSTreatmentTest() throws JSONException { + // Test profile creation + dialog.setOptions(CareportalFragment.PROFILESWITCH, R.string.careportal_profileswitch); + JSONObject data = new JSONObject(); + data.put("profile", AAPSMocker.getValidProfile().getData()); + data.put("duration", 0); + data.put("percentage", 110); + data.put("timeshift", 0); + dialog.createNSTreatment(data); + + Bundle bundles = AAPSMocker.intentSent.getExtras(); + Assert.assertTrue(bundles.getString("profile").contains("00:00")); + } + + @Test + public void doProfileSwitch() { + } + + @Test + public void doProfileSwitch1() { + } + + @Before + public void prepareMock() { + AAPSMocker.mockMainApp(); + AAPSMocker.mockApplicationContext(); + AAPSMocker.mockSP(); + AAPSMocker.mockStrings(); + AAPSMocker.mockBundle(); + + dialog = new NewNSTreatmentDialog(); + } +} \ No newline at end of file From 10b9171afe943f7b3d72b13cce8c346293a1dd86 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Fri, 13 Apr 2018 00:48:57 +0200 Subject: [PATCH 25/56] Distribute carbs strictly within timeframe --- .../plugins/Overview/Dialogs/NewCarbsDialog.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index ad603fa321..fa02b14ab0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -401,13 +401,12 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C createCarb(carbsAfterConstraints, time, finalNotes); } else { long remainingCarbs = carbsAfterConstraints; - long carbTime = time; - long smallCarbAmount = Math.round(remainingCarbs / (editDuration.getValue() * 4)); - if (smallCarbAmount == 0) smallCarbAmount = 1; - while (remainingCarbs > 0) { - createCarb(Math.min(smallCarbAmount, remainingCarbs), carbTime, finalNotes); + int ticks = (duration * 4); //duration guaranteed to be integer greater zero + for (int i = 0; i < ticks; i++){ + long carbTime = time + i * 15 * 60 * 1000; + long smallCarbAmount = Math.round((1d * remainingCarbs) / (ticks-i)); //on last iteration (ticks-i) is 1 -> smallCarbAmount == remainingCarbs remainingCarbs -= smallCarbAmount; - carbTime += 15 * 60 * 1000; + createCarb(smallCarbAmount, carbTime, finalNotes); } } } From efcc02775bcb495b2a36c1df78176b2a2cf0b43d Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Fri, 13 Apr 2018 21:20:11 +0200 Subject: [PATCH 26/56] FillDialog: add missed validation, notes field, align style. --- .../plugins/Actions/dialogs/FillDialog.java | 151 +++++++++----- .../plugins/Treatments/TreatmentsPlugin.java | 2 +- .../java/info/nightscout/utils/NSUpload.java | 8 +- .../main/res/layout/actions_fill_dialog.xml | 192 +++++++++++------- 4 files changed, 218 insertions(+), 135 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java index b3b15bf7fb..ba53b40935 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java @@ -5,7 +5,9 @@ import android.content.Intent; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; +import android.text.Editable; import android.text.Html; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -14,6 +16,8 @@ import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.LinearLayout; import com.crashlytics.android.answers.CustomEvent; import com.google.common.base.Joiner; @@ -21,8 +25,6 @@ import com.google.common.base.Joiner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.Constants; -import java.text.DecimalFormat; import java.util.LinkedList; import java.util.List; @@ -41,6 +43,9 @@ import info.nightscout.utils.NSUpload; import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; +import info.nightscout.utils.ToastUtils; + +import static info.nightscout.utils.DateUtil.now; public class FillDialog extends DialogFragment implements OnClickListener { private static Logger log = LoggerFactory.getLogger(FillDialog.class); @@ -49,11 +54,35 @@ public class FillDialog extends DialogFragment implements OnClickListener { double amount2 = 0d; double amount3 = 0d; - NumberPicker editInsulin; CheckBox pumpSiteChangeCheckbox; CheckBox insulinCartridgeChangeCheckbox; - public FillDialog() { + NumberPicker editInsulin; + + private LinearLayout notesLayout; + private EditText notesEdit; + + final private TextWatcher textWatcher = new TextWatcher() { + @Override + public void afterTextChanged(Editable s) { + validateInputs(); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + }; + + private void validateInputs() { + int time = editInsulin.getValue().intValue(); + if (Math.abs(time) > 12 * 60) { + editInsulin.setValue(0d); + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied)); + } } @Override @@ -67,45 +96,47 @@ public class FillDialog extends DialogFragment implements OnClickListener { getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - pumpSiteChangeCheckbox = view.findViewById(R.id.catheter_change); - insulinCartridgeChangeCheckbox = view.findViewById(R.id.cartridge_change); + pumpSiteChangeCheckbox = view.findViewById(R.id.fill_catheter_change); + insulinCartridgeChangeCheckbox = view.findViewById(R.id.fill_cartridge_change); Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep; - editInsulin = view.findViewById(R.id.treatments_newtreatment_insulinamount); - editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false); + editInsulin = view.findViewById(R.id.fill_insulinamount); + editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher); - //setup preset buttons - Button button1 = (Button) view.findViewById(R.id.fill_preset_button1); - Button button2 = (Button) view.findViewById(R.id.fill_preset_button2); - Button button3 = (Button) view.findViewById(R.id.fill_preset_button3); + Button preset1Button = view.findViewById(R.id.fill_preset_button1); amount1 = SP.getDouble("fill_button1", 0.3); - amount2 = SP.getDouble("fill_button2", 0d); - amount3 = SP.getDouble("fill_button3", 0d); - if (amount1 > 0) { - button1.setVisibility(View.VISIBLE); - button1.setText(DecimalFormatter.toPumpSupportedBolus(amount1)); // + "U"); - button1.setOnClickListener(this); + preset1Button.setVisibility(View.VISIBLE); + preset1Button.setText(DecimalFormatter.toPumpSupportedBolus(amount1)); // + "U"); + preset1Button.setOnClickListener(this); } else { - button1.setVisibility(View.GONE); + preset1Button.setVisibility(View.GONE); } + Button preset2Button = view.findViewById(R.id.fill_preset_button2); + amount2 = SP.getDouble("fill_button2", 0d); if (amount2 > 0) { - button2.setVisibility(View.VISIBLE); - button2.setText(DecimalFormatter.toPumpSupportedBolus(amount2)); // + "U"); - button2.setOnClickListener(this); + preset2Button.setVisibility(View.VISIBLE); + preset2Button.setText(DecimalFormatter.toPumpSupportedBolus(amount2)); // + "U"); + preset2Button.setOnClickListener(this); } else { - button2.setVisibility(View.GONE); + preset2Button.setVisibility(View.GONE); } + Button preset3Button = view.findViewById(R.id.fill_preset_button3); + amount3 = SP.getDouble("fill_button3", 0d); if (amount3 > 0) { - button3.setVisibility(View.VISIBLE); - button3.setText(DecimalFormatter.toPumpSupportedBolus(amount3)); // + "U"); - button3.setOnClickListener(this); + preset3Button.setVisibility(View.VISIBLE); + preset3Button.setText(DecimalFormatter.toPumpSupportedBolus(amount3)); // + "U"); + preset3Button.setOnClickListener(this); } else { - button3.setVisibility(View.GONE); + preset3Button.setVisibility(View.GONE); } + notesLayout = view.findViewById(R.id.fill_notes_layout); + notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE); + notesEdit = view.findViewById(R.id.fill_notes); + setCancelable(true); getDialog().setCanceledOnTouchOutside(false); return view; @@ -154,42 +185,50 @@ public class FillDialog extends DialogFragment implements OnClickListener { if (insulinCartridgeChangeCheckbox.isChecked()) confirmMessage.add("" + "" + getString(R.string.record_insulin_cartridge_change) + ""); + final String notes = notesEdit.getText().toString(); + if (!notes.isEmpty()) { + confirmMessage.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes); + } + final Double finalInsulinAfterConstraints = insulinAfterConstraints; final Context context = getContext(); AlertDialog.Builder builder = new AlertDialog.Builder(context); - if (confirmMessage.isEmpty()) - confirmMessage.add(MainApp.gs(R.string.no_action_selected)); - builder.setTitle(MainApp.gs(R.string.confirmation)); - builder.setMessage(Html.fromHtml(Joiner.on("
").join(confirmMessage))); - builder.setPositiveButton(getString(R.string.primefill), (dialog, id) -> { - if (finalInsulinAfterConstraints > 0) { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = finalInsulinAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.source = Source.USER; - detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) - ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); + if (insulinAfterConstraints > 0 || pumpSiteChangeCheckbox.isChecked() || insulinCartridgeChangeCheckbox.isChecked()) { + builder.setMessage(Html.fromHtml(Joiner.on("
").join(confirmMessage))); + builder.setPositiveButton(getString(R.string.primefill), (dialog, id) -> { + if (finalInsulinAfterConstraints > 0) { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.source = Source.USER; + detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) + detailedBolusInfo.notes = notes; + ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { + @Override + public void run() { + if (!result.success) { + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } } - } - }); - FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill")); - } - long now = System.currentTimeMillis(); - if (pumpSiteChangeCheckbox.isChecked()) NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now); - if (insulinCartridgeChangeCheckbox.isChecked()) NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now + 1000); - }); + }); + FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill")); + } + if (pumpSiteChangeCheckbox.isChecked()) + NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now(), notes); + if (insulinCartridgeChangeCheckbox.isChecked()) + NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now() + 1000, notes); + }); + } else { + builder.setMessage(MainApp.gs(R.string.no_action_selected)); + } builder.setNegativeButton(getString(R.string.cancel), null); builder.show(); dismiss(); 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 2f5135c0cb..8f82f71c35 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 @@ -452,7 +452,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface //log.debug("Adding new Treatment record" + carbsTreatment); } if (newRecordCreated && detailedBolusInfo.isValid) - NSUpload.uploadBolusWizardRecord(detailedBolusInfo); + NSUpload.uploadTreatmentRecord(detailedBolusInfo); return newRecordCreated; } diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index c56c4f1a51..e617191732 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -7,6 +7,7 @@ import android.content.pm.ResolveInfo; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.annotation.Nullable; import org.apache.commons.lang3.StringUtils; import org.json.JSONArray; @@ -258,7 +259,7 @@ public class NSUpload { } } - public static void uploadBolusWizardRecord(DetailedBolusInfo detailedBolusInfo) { + public static void uploadTreatmentRecord(DetailedBolusInfo detailedBolusInfo) { JSONObject data = new JSONObject(); try { data.put("eventType", detailedBolusInfo.eventType); @@ -500,7 +501,7 @@ public class NSUpload { } } - public static void uploadEvent(String careportalEvent, long time) { + public static void uploadEvent(String careportalEvent, long time, @Nullable String notes) { Context context = MainApp.instance().getApplicationContext(); Bundle bundle = new Bundle(); bundle.putString("action", "dbAdd"); @@ -510,6 +511,9 @@ public class NSUpload { data.put("eventType", careportalEvent); data.put("created_at", DateUtil.toISOString(time)); data.put("enteredBy", SP.getString("careportal_enteredby", MainApp.gs(R.string.app_name))); + if (notes != null) { + data.put("notes", notes); + } } catch (JSONException e) { log.error("Unhandled exception", e); } diff --git a/app/src/main/res/layout/actions_fill_dialog.xml b/app/src/main/res/layout/actions_fill_dialog.xml index 18a5886246..f1ee50c3ca 100644 --- a/app/src/main/res/layout/actions_fill_dialog.xml +++ b/app/src/main/res/layout/actions_fill_dialog.xml @@ -1,97 +1,137 @@ - + android:layout_height="wrap_content"> + + - - - - - - - - - - - - - - + android:layout_height="wrap_content" + android:layout_gravity="center" + android:orientation="horizontal"> -