From 42e36ab81897c559325d126d4f2e4be21736accf Mon Sep 17 00:00:00 2001 From: "Markus M. May" Date: Thu, 12 Apr 2018 21:08:06 +0200 Subject: [PATCH 1/9] 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 54048b29c4a2469ad090076b18b317969134b33f Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 12 Apr 2018 21:45:59 +0200 Subject: [PATCH 2/9] 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 abadcd4eaa171ffd81d35c80ef5b6294f36a1078 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 16 Apr 2018 23:29:53 +0200 Subject: [PATCH 3/9] fix test --- .../Dialogs/NewNSTreatmentDialog.java | 4 +- .../ProfileLocal/LocalProfilePlugin.java | 21 +++----- .../main/java/info/nightscout/utils/SP.java | 4 +- app/src/test/java/info/AAPSMocker.java | 53 +++++++++--------- app/src/test/java/info/SPMocker.java | 40 +++++++++++--- .../Dialogs/NewNSTreatmentDialogTest.java | 54 ++++++++++++++----- 6 files changed, 111 insertions(+), 65 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 c3f99dc630..5a57b62869 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 @@ -68,7 +68,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick private static String event; Profile profile; - ProfileStore profileStore; + public ProfileStore profileStore; String units = Constants.MGDL; TextView eventTypeText; @@ -680,7 +680,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } - void createNSTreatment(JSONObject data) { + public 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")); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java index 30e0d9b064..ce190b691b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java @@ -1,7 +1,5 @@ package info.nightscout.androidaps.plugins.ProfileLocal; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; import android.support.annotation.NonNull; import org.json.JSONArray; @@ -70,18 +68,15 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface { } public synchronized void storeSettings() { - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - SharedPreferences.Editor editor = settings.edit(); - editor.putBoolean(LOCAL_PROFILE + "mmol", mmol); - editor.putBoolean(LOCAL_PROFILE + "mgdl", mgdl); - editor.putString(LOCAL_PROFILE + "dia", dia.toString()); - editor.putString(LOCAL_PROFILE + "ic", ic.toString()); - editor.putString(LOCAL_PROFILE + "isf", isf.toString()); - editor.putString(LOCAL_PROFILE + "basal", basal.toString()); - editor.putString(LOCAL_PROFILE + "targetlow", targetLow.toString()); - editor.putString(LOCAL_PROFILE + "targethigh", targetHigh.toString()); + SP.putBoolean(LOCAL_PROFILE + "mmol", mmol); + SP.putBoolean(LOCAL_PROFILE + "mgdl", mgdl); + SP.putString(LOCAL_PROFILE + "dia", dia.toString()); + SP.putString(LOCAL_PROFILE + "ic", ic.toString()); + SP.putString(LOCAL_PROFILE + "isf", isf.toString()); + SP.putString(LOCAL_PROFILE + "basal", basal.toString()); + SP.putString(LOCAL_PROFILE + "targetlow", targetLow.toString()); + SP.putString(LOCAL_PROFILE + "targethigh", targetHigh.toString()); - editor.apply(); createAndStoreConvertedProfile(); edited = false; if (Config.logPrefsChange) diff --git a/app/src/main/java/info/nightscout/utils/SP.java b/app/src/main/java/info/nightscout/utils/SP.java index 16015d8956..23a95840a8 100644 --- a/app/src/main/java/info/nightscout/utils/SP.java +++ b/app/src/main/java/info/nightscout/utils/SP.java @@ -24,7 +24,7 @@ public class SP { return sharedPreferences.getString(key, defaultValue); } - static public boolean getBoolean(int resourceID, boolean defaultValue) { + static public boolean getBoolean(int resourceID, Boolean defaultValue) { try { return sharedPreferences.getBoolean(MainApp.sResources.getString(resourceID), defaultValue); } catch (Exception e) { @@ -32,7 +32,7 @@ public class SP { } } - static public boolean getBoolean(String key, boolean defaultValue) { + static public boolean getBoolean(String key, Boolean defaultValue) { try { return sharedPreferences.getBoolean(key, defaultValue); } catch (Exception e) { diff --git a/app/src/test/java/info/AAPSMocker.java b/app/src/test/java/info/AAPSMocker.java index 0e8c5b2cdc..c02c69cd07 100644 --- a/app/src/test/java/info/AAPSMocker.java +++ b/app/src/test/java/info/AAPSMocker.java @@ -2,16 +2,12 @@ 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; @@ -21,8 +17,10 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.ConstraintChecker; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Treatments.TreatmentService; import info.nightscout.androidaps.queue.CommandQueue; import info.nightscout.utils.SP; @@ -39,6 +37,8 @@ import static org.mockito.Mockito.when; 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; + private static ProfileStore profileStore; + public static final String TESTPROFILENAME = "someProfile"; public static Intent intentSent = null; @@ -125,28 +125,6 @@ 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() { @@ -159,6 +137,11 @@ public class AAPSMocker { when(ConfigBuilderPlugin.getCommandQueue()).thenReturn(queue); } + public static void mockTreatmentService() throws Exception { + TreatmentService treatmentService = PowerMockito.mock(TreatmentService.class); + PowerMockito.whenNew(TreatmentService.class).withNoArguments().thenReturn(treatmentService); + } + public static Profile getValidProfile() { try { if (profile == null) @@ -168,6 +151,24 @@ public class AAPSMocker { return profile; } + public static ProfileStore getValidProfileStore() { + try { + if (profileStore == null) { + JSONObject json = new JSONObject(); + JSONObject store = new JSONObject(); + JSONObject profile = new JSONObject(validProfile); + + json.put("defaultProfile", TESTPROFILENAME); + json.put("store", store); + store.put(TESTPROFILENAME, profile); + profileStore = new ProfileStore(json); + } + } catch (JSONException ignored) { + Assert.fail("getValidProfileStore() failed"); + } + return profileStore; + } + private static MockedBus bus = new MockedBus(); public static void prepareMockedBus() { diff --git a/app/src/test/java/info/SPMocker.java b/app/src/test/java/info/SPMocker.java index a6663175c6..af6f0ba295 100644 --- a/app/src/test/java/info/SPMocker.java +++ b/app/src/test/java/info/SPMocker.java @@ -2,17 +2,12 @@ package info; import org.junit.Assert; import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import org.powermock.api.mockito.PowerMockito; import java.util.HashMap; import info.nightscout.utils.SP; -import static org.powermock.api.mockito.PowerMockito.when; - public class SPMocker { static HashMap data = new HashMap<>(); @@ -24,19 +19,48 @@ public class SPMocker { PowerMockito.when(SP.class, "putString", ArgumentMatchers.anyString(), ArgumentMatchers.anyString()).then(invocation -> { String key = invocation.getArgument(0); String value = invocation.getArgument(1); - data.put(key,value); + data.put(key, value); + System.out.print("putString " + key + " " + value + "\n"); return null; }); - PowerMockito.when(SP.class, "getString", ArgumentMatchers.anyString(), ArgumentMatchers.anyString()).then(invocation -> { + PowerMockito.when(SP.class, "getString", ArgumentMatchers.anyString(), ArgumentMatchers.any()).then(invocation -> { String key = invocation.getArgument(0); String def = invocation.getArgument(1); String value = (String) data.get(key); if (value == null) value = def; + System.out.print("getString " + key + " " + value + "\n"); return value; }); + + PowerMockito.when(SP.class, "putBoolean", ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean()).then(invocation -> { + String key = invocation.getArgument(0); + Boolean value = invocation.getArgument(1); + data.put(key, value); + System.out.print("putBoolean " + key + " " + value + "\n"); + return null; + }); + + PowerMockito.when(SP.class, "getBoolean", ArgumentMatchers.anyString(), ArgumentMatchers.any()).then(invocation -> { + String key = invocation.getArgument(0); + Boolean def = invocation.getArgument(1); + Boolean value = (Boolean) data.get(key); + if (value == null) value = def; + System.out.print("getBoolean " + key + " " + value + "\n"); + return value; + }); + + PowerMockito.when(SP.class, "getDouble", ArgumentMatchers.anyString(), ArgumentMatchers.any()).then(invocation -> { + String key = invocation.getArgument(0); + Double def = invocation.getArgument(1); + Double value = (Double) data.get(key); + if (value == null) value = def; + System.out.print("getDouble " + key + " " + value + "\n"); + 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: " + e.getMessage()); } } 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 index d25faa0d45..185f400e4f 100644 --- 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 @@ -1,45 +1,62 @@ 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.mockito.ArgumentMatchers; +import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import info.AAPSMocker; -import info.BundleMock; +import info.SPMocker; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; +import info.nightscout.androidaps.plugins.Treatments.TreatmentService; +import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; -import static org.junit.Assert.*; +import static info.nightscout.androidaps.plugins.Careportal.CareportalFragment.PROFILESWITCH; +import static org.powermock.api.mockito.PowerMockito.doAnswer; +import static org.powermock.api.mockito.PowerMockito.when; @RunWith(PowerMockRunner.class) -@PrepareForTest({MainApp.class, SP.class, Context.class}) +@PrepareForTest({SP.class, MainApp.class, ConfigBuilderPlugin.class, Context.class, NSUpload.class, TreatmentsPlugin.class, TreatmentService.class, DatabaseHelper.class}) public class NewNSTreatmentDialogTest { NewNSTreatmentDialog dialog; + ProfileSwitch profileSwitchUpload = null; @Test - public void createNSTreatmentTest() throws JSONException { + public void createNSTreatmentTest() throws Exception { // Test profile creation - dialog.setOptions(CareportalFragment.PROFILESWITCH, R.string.careportal_profileswitch); + doAnswer(invocation -> { + ProfileSwitch ps = invocation.getArgument(0); + profileSwitchUpload = ps; + return null; + }).when(NSUpload.class, "uploadProfileSwitch", ArgumentMatchers.any()); + PROFILESWITCH.executeProfileSwitch = true; + dialog.setOptions(PROFILESWITCH, R.string.careportal_profileswitch); + dialog.profileStore = AAPSMocker.getValidProfileStore(); JSONObject data = new JSONObject(); - data.put("profile", AAPSMocker.getValidProfile().getData()); + data.put("profile", AAPSMocker.TESTPROFILENAME); 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")); + // Profile should be sent to NS + Assert.assertEquals(AAPSMocker.TESTPROFILENAME, profileSwitchUpload.profileName); } @Test @@ -51,12 +68,21 @@ public class NewNSTreatmentDialogTest { } @Before - public void prepareMock() { + public void prepareMock() throws Exception { AAPSMocker.mockMainApp(); + SPMocker.prepareMock(); + SP.putString("profile", AAPSMocker.getValidProfileStore().getData().toString()); + AAPSMocker.mockConfigBuilder(); AAPSMocker.mockApplicationContext(); - AAPSMocker.mockSP(); AAPSMocker.mockStrings(); - AAPSMocker.mockBundle(); + PowerMockito.mockStatic(NSUpload.class); + AAPSMocker.mockTreatmentService(); + AAPSMocker.mockBus(); + AAPSMocker.mockDatabaseHelper(); + + NSProfilePlugin profilePlugin = NSProfilePlugin.getPlugin(); + when(MainApp.getConfigBuilder().getActiveProfileInterface()) + .thenReturn(profilePlugin); dialog = new NewNSTreatmentDialog(); } From 8dd589c5fed6aab0e9ffcef26bc07f862478a6d9 Mon Sep 17 00:00:00 2001 From: Alessya Date: Tue, 17 Apr 2018 14:52:06 +0300 Subject: [PATCH 4/9] New icons added for local profile screen --- .../drawable-hdpi/icon_local-activatehdpi.png | Bin 0 -> 1357 bytes .../res/drawable-hdpi/icon_local-resethdpi.png | Bin 0 -> 963 bytes .../res/drawable-hdpi/icon_local-savehdpi.png | Bin 0 -> 912 bytes .../drawable-mdpi/icon_local-activatemdpi.png | Bin 0 -> 881 bytes .../res/drawable-mdpi/icon_local-resetmdpi.png | Bin 0 -> 692 bytes .../res/drawable-mdpi/icon_local-savemdpi.png | Bin 0 -> 619 bytes .../drawable-xhdpi/icon_local-activatexhdpi.png | Bin 0 -> 1700 bytes .../res/drawable-xhdpi/icon_local-resetxhdpi.png | Bin 0 -> 1241 bytes .../res/drawable-xhdpi/icon_local-savexhdpi.png | Bin 0 -> 1154 bytes .../icon_local-activatexxhdpi.png | Bin 0 -> 2678 bytes .../drawable-xxhdpi/icon_local-resetxxhdpi.png | Bin 0 -> 1884 bytes .../drawable-xxhdpi/icon_local-savexxhdpi.png | Bin 0 -> 1694 bytes .../icon_local-activatexxxhdpi.png | Bin 0 -> 3549 bytes .../drawable-xxxhdpi/icon_local-resetxxxhdpi.png | Bin 0 -> 2510 bytes .../drawable-xxxhdpi/icon_local-savexxxhdpi.png | Bin 0 -> 2249 bytes 15 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/icon_local-activatehdpi.png create mode 100644 app/src/main/res/drawable-hdpi/icon_local-resethdpi.png create mode 100644 app/src/main/res/drawable-hdpi/icon_local-savehdpi.png create mode 100644 app/src/main/res/drawable-mdpi/icon_local-activatemdpi.png create mode 100644 app/src/main/res/drawable-mdpi/icon_local-resetmdpi.png create mode 100644 app/src/main/res/drawable-mdpi/icon_local-savemdpi.png create mode 100644 app/src/main/res/drawable-xhdpi/icon_local-activatexhdpi.png create mode 100644 app/src/main/res/drawable-xhdpi/icon_local-resetxhdpi.png create mode 100644 app/src/main/res/drawable-xhdpi/icon_local-savexhdpi.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_local-activatexxhdpi.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_local-resetxxhdpi.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_local-savexxhdpi.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_local-activatexxxhdpi.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_local-resetxxxhdpi.png create mode 100644 app/src/main/res/drawable-xxxhdpi/icon_local-savexxxhdpi.png diff --git a/app/src/main/res/drawable-hdpi/icon_local-activatehdpi.png b/app/src/main/res/drawable-hdpi/icon_local-activatehdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..4ef567ffb65bb11825ac52978c03cb378a338646 GIT binary patch literal 1357 zcmV-T1+w~yP)002t}1^@s6I8J)%00009a7bBm000o1 z000o10d$F+O8@`_|4BqaRCt{2TuXA=KoISuvbT3yMmd4W34jv>pTKyho$(1mPGG## z&TxX@6BwN!_yid*wKFGhswsvK;W~l!Pf%JvZ+Q?d$GGcgk)VxrChZpGv+iD+8pnGzJS6`ha;^O{;{ zkPj+efHKe4vEL&qS%s?4iD*VdSJ57_!#y7kp*p9T9{k4^+ou+<`*thof8rN zIfq{xSZL-85shQ{v?yd1s%F1**YXo4XwGE1XaY2q{oVKgao1&@&E2Fv3~{mwRnJ?@ zu7arque^mHT$Fh>4t>r(M9FF)Y6J6Fial)i%n`KIWbUGbiILS}de7`{Vme;DKRNa6rwVQkTudiSAsR!4cCZBIK2URbnWuKrx#f;72SD;Bz}*E zYaGFTav%uQGF`4SUsLzhEYrh6N*Q*%UkxFj5C9Z{f)7k`9hIyqG~wfrUgjC6BDY9C z_Q6_wSEzdB>YyQ)Zi=0f)zdzU^^eLto8kWY3lgHQPnx02=hdvIT|Teq=-& zGvT@q6C&O0*ko=wqxWnHo8;<_EcgoD?n5RycMbL0Bl`Iv?Ovig)Nhi5OtmmUo9}2kKV#Luzz(Z zVd7H#EEeS2@YNMe(t8SQ1KfYrK-9IAFBChDf(>I$?cd;mX%leYb;Cxsh2-ASw5QYo zv34u7kPj_CiM?C-Hn2o8;*|EmuQ4U!F_;1|+dkC5av%J*Yx?i(gWm!#JjDbiHljz~ zuFmfC5Y}Uz-4XGFhtTz@uzW9xl{ghP>*9dZ7RNkqIN0+=JxkxV#(6{W!v{7vssH6D zon-xwkPehPAd%&OM3w^*Sq?~KIUtecfJBx95?KyNWH}&_<$y$%Er{q3J~1+q+rF88 P00000NkvXXu0mjf^*DY- literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/icon_local-resethdpi.png b/app/src/main/res/drawable-hdpi/icon_local-resethdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..7d38cf0b5026b936e9435c4d54078c0793274382 GIT binary patch literal 963 zcmeAS@N?(olHy`uVBq!ia0vp^-XP4u1|%)~s$Kyp&H|6fVg?3**&xhV(m4mHg1OYw z#WAFU@$GEivReiM4a;lqs%z&zWIL#?VXpCJkG7>_b@L(K9gZ)~?Y<;^fKw(fU|ZZ( z^#%TKEzZy6id24my#LI1Ic^uFDd&whnH1fN)e{$ZQ=vcajbJ2?ix~67qYf#C0=SvY z{K;}LbH$Arb}WAz87ddllOA$(zm>ii!-6=kOU~!}%^3;~T(?_&Dt_Vd=`mq*#e*3l z7BAV&7(16CVRq=#bB{m7P4oc@f7f`~{e0c|RrduhO*(O?X&DH=4Rkp0xS+b;Z@E?zh#2{5oe?YcKgL_|P}IV{*P?%jODwjr?5Lthv*e z)9B0HbJe@{iT2xFGFrCgxpw&uUcWOrp0nQ1NUEy8QezVlAre^{_r@eV*7dT|ky$Ix zaf_zjH<8zEUy@P~8P2vY?{l&I#grfSL>X)*K4aS-UViz7>Web=@CO%N5AF}$*Y(W( zQcZj2E0-606=fr4S2?Svu?%bN2|T-4_^ArHPxP%**krIuZOKi|FSQM;f9Srs`;)0$wz9cu*7hU=bt%&F)dE+;8`E?U>pT;}E+)3P-2K{Sz6hm%zgeA6>F%hnS?QD#>UrAI@xawztFt(s z^ECWUIN{y7;~e+$%R(Zh3hK6jDVe8?+|TJpFIW6GF?QaDywtOzfrbkor^e>In^RgO znkL}-o2O}+!p#EnpVu~RkTWS4yrz8WXIP&1bCW%%?J{`pxkk)i;h}Du{Yk;|v5~*k z+;$&SnMO9xH(bfxl z<$s4PPrbl3PgAE=61M<>4&dDNag-MPipYnjkfQT^(}^Eh^M20kcOu64a}wxdaa zzpW%lD9=-*rK)S$UH5yFG$d}=R1U{%`DM+z-r^44$rj JF6*2UngBe%s?Pub literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/icon_local-savehdpi.png b/app/src/main/res/drawable-hdpi/icon_local-savehdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..e5c1d5cedc61cbdb3069090d90f1611cbb5da670 GIT binary patch literal 912 zcmeAS@N?(olHy`uVBq!ia0vp^-XP4u1|%)~s$Kyp&H|6fVg?3**&xhV(m4mHg4xN_ z#WAFU@$H=Rxwj2O+T*+L-Jac-tKMPWVZOpVqe^&z^Jd3KypNh0Wao0e;+^FaP~D{F zes>mU3`YeE&&(x1b4a@&0PCg;saNDWwIQI9BK| zVPV$H@b#QIC3h=BgXq7n+caN^zuT%;b!}nJYE_0e3=fp$s+b#C!*3itCXjvQy>MWI z{r!UVl_ztrh5c$0*Ib>mx|(4}(VTmQ>#GYl8Pt{cU4Ff6#rHee-8Q_ZxBY7IpYv|( zo2|mhpRQht*!`$HqwAO5GM$T?PHl@yWDMpsTJw7m+oR)oH+TbM*+sr;Zxi6z6}9Qb z)TO`w_CF4KeItt1FjvgY|4*lI$J%K-PJQBH;1|l55 zTHd<~?1GM+H+U{rv+0Lqnx=N?AD+#VU3=xfvAfQgsbZmGS=lC^;UkjA3g8Z?p84c28Zsw7pC_P2rt!@ zlxW}e$bA3Ipg%49zw^ZlwiZ5mUKO=TGFFVQDqeSaQw#5r{JBbXZ6UmSR-3;SH50JE ze&)IE{uy;aCtu|~cwq5d_*w7#$2)S(Tv}8%ZSai@YI&%$M!)V&E4$vwUy&k-XMXhh zUGmFZv7wQ5!V8dK^@qko`z+6;cFtEkU7+qTqc`WHaf-CGQA=v~e8txevlMi)|M1*Q zmt|^6?Vq106l@}w*sgixyur+$Yy2eiPX2fB?BBsQ)3&bdsez%KJ V0^^&Ve}P$y!PC{xWt~$(69DLjngjp< literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/icon_local-activatemdpi.png b/app/src/main/res/drawable-mdpi/icon_local-activatemdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..b39c72b40776a28bcec7cfb5604bcac60b4b5da2 GIT binary patch literal 881 zcmV-%1CIQOP)$W=H2wPDBVHX22b>FDpAD0NOph^; z=_>{@eZ`wo$mK)f08IFj2y|sGS)XFx&WffF1qnU_FaF zT(o?|4#2z%QqLmeL$LsGQ}NXvKn@^wr_%MREVm)6W-j^JR-RU5d??D5W)_HmNy{h}^L@%^8YZDsu@Xj89Ag zY^gO9HNj*VABs7EuaZdSl9_eWnrBbg;-%YdGM8Lho}so3XRU=;sw6@}`B0dIz@wFN zj-e74tUNU=Znh9w`<+fJh!Eii06%;va@Mwm5G9Upa!-r9smSmHuf@{5CWSijnd0if zhaxrlKPgSd&s2M()-uxkTVsLyOf^UAdaR^WEU8^hOGauZJ@Pw=t;kR#cDPhgSIGO?3IvcU1vT7rlD2R8NOM>RXEL7k+@-eC--+d_7 z4H}n9>&!CJE!0FLIL2I*sV+E{7B#oY4nUO^tsOwCo(WIYo`U%Ur*^QFZfXe0Y^lnI z|6rvpEfG}CJ#vq&wzg@>NK1@4khP$;=6&Xpg=W5It4K21_DM&Eg}9R&)WnVymIC}s z=8}nV1eT-5z9Nm+!aC2$#_=zWvCy|noJgp(il@{~UG|?nEvGgA=h%!#&8LyOUHech z+Z;Yfa2G9!>@7oCiL*Ltdd?wW8jaF;afg7BP}bvF$CbT5$FmY09h_6v(sUI^(d8=* z$HmU_N@LXpi4rIIQ^SjY+0+LNFKGLUflOa9km)PVhYWyU{6KY-rJ5bI00000NkvXX Hu0mjfCsK~e literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/icon_local-resetmdpi.png b/app/src/main/res/drawable-mdpi/icon_local-resetmdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..ad2e0eaf6d9f16886f3d30f1a9d6656874d6a1f9 GIT binary patch literal 692 zcmV;l0!#ggP)w z&Vphb$Ju#CY62(Ts2NFQf7{P}S>9B?W+I~kG!ld%d+ zt|~COs=(x`lY%*)(s^6eR{$0OZUM{y%mG{g*a6rB_yEuV*eIj-W8XK)+N`Z=`uHaR zHv`OG$wnDXfKf^c(^fV0{-y`QMugg3A8GTOp$11P8BAN%b55BHar+a%n(iy3-;dZV z`I2@7y%-v$Brpz;F90iL^h=;UMQR1$m$*$nZe5*lOrv2OAY1O$!D+(2C`~W<){cRK ze2ps2VvJajS7mhY%e&$z5YUbv(YOkVE)vW$lp3-ZS0nv_J7URcM*7Ls(W__}onzI)KRhG z(r(Aj!q+}FGFRev6X_#V*8ioieJqU3->G5#O`5){77H_rw3}3AbC#>V1B@J>y;ZY! zr^zLlu8+|2D+cL%q7{Ml_vQNrUu0;adZP~unStA?e&P0SogR%+Th$A(i1k)YAB^o; za@cUB`atd-wqqn0uHIFKcR$nl$Q_4WZlvxwf)eB*bYs@@UW&>e{`;wnKH8C1-U6VE zUh-iBcz@A!=9%>bAhS*+g0>bx)yx6(C?3m$iP0dex!k!bqc+9 z+mHpO)!;J#$3RD7kZ28_G#wGj0t91DXE;JlE+Cldc=ms(EHraffyq?`CRY`hTvcGQ a6o9{!hU6)1qygao00009q)MCqjUgPAXcDOAjiz)09GJWAeWuV z5j%hmumk7-kGVkwI6ISICMIk)o4A>s{cc18`;njbvcap<>4dg$-5QflCSf|6ROw_= zrByOF30%V;2&W4G6978^BbMa{mwCyp4B>PtL<$A~rml07k|CV-0nD`Fz3Y6hm=R7# zKJyG5Se9><;U$2c@_5IxeChgPm1GE~GqLPFho`&n0$_{Zcs*!y##LU-Sw{I%hGNaK zdF=Gv--ks+Mk8brRUt)z zx-gsb#;|1Wu_gX^4OfREPgj1W4OT4_PEh8fJsSUsC zLXOqTD_)Wy1%PGw_>xdryh0JInw1ExwDDTa(MHhHY!d=-r;XKWjy8h#8HWEBZMA>RG(#eotwE*qMw_wEZ+dw#C{)i$Fm9JB_j?v zf?~LTaXOM!@m-mv&&`t!vE5O32}hq^(^ZZXD#mT?d>5sFF zSoZs(i~GEhBkL+ZVd!-K)Q~EjOsaG;snW@$N_%7g`~cdCzk%b?snh@f002ovPDHLk FV1fk79&G>s literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/icon_local-activatexhdpi.png b/app/src/main/res/drawable-xhdpi/icon_local-activatexhdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..75e9af38ed98e928829a6f2a5dd78896bb8bfdb5 GIT binary patch literal 1700 zcma)-{Xf$Q0LMpRTbZqfQPD7Nj1D>L0b84FL&w+C##BeLxH_icJe_RPK}}PR_VcZ~fUmaC(n()&(HsTzC*psnM@u6w#i9;r!hS z={0GmGvedReeTKSTML|Zud*h%!Wj6mLLwe(I3q#vKB2rBNVNQVs%0F#H6!{WT>a0g zRygn;%`^0Qy|TJmEAle8(y%I?eJc~ULD4E6+zic2i|?A!v-28C3>jQEwXDS}O99Vi z%q2P$j_A$?e|5M1^r45DMR^tg!4N^bbvds+2a1;AN@MfNem&Fg)woTV47G_rgMJ@C zgU0l>InWnsc8wHw9DcH#&7BW0OR=|&<8fXg>e3D*Ks8CQ)}tFayFZuTr!oWLJcK2H zr!(Wx%_4u3ApfNl>mWY@&dqrhl-B08&=nh0hCEzRP*lLqHEr}zfmLe9lo;J{QALa- zwXf9z2Z=}a2*CCG zW3P*}i=R2e>>&^z)ug^ltBHBDy$7qeY(lZ}yCd2!7v<8MB@@3ty7bIZ<22J|u&7;5u86U$umto}kEhbfBLPQ_y zGN}qlhqR-jwpTKgnSZ|iBZ#v|pl$3*sm92tNXv4Cm+U5@X+iYwp-$mG&J%Ag{;cfe zeD)mt#NA5*{dPqp|HVB}WJ%8E{zli>;#^KjA~xCF{w!7n!ls@7^);IB^L%&&iJ-jv zrQGSImL^mfH}Q1$^5E%1%_3gwgq`%>2a?rD zV?jZc4HW#~gmm7WnKYgEx4sbADv%^OQsguqv%gkUipip!N~NCH+2X248+`?3-lMJK z$~r-mD%4%{V;bKdGw<%%|22cwSo6SQ_11Gj2K#n+ zyAQtuL;h9yK-g6;5g$+m3vZ7eT^8Q|jB0KBJqXB;WBF}lY!J&zcpc3afNsg&Q zVh`0m*F@T`nUZeW;=)0w-*Liaj4y41QmPnqyFEgJl|22+K78DW-g{tj$$RNC_AU{Q z&OaSB)snpt#zWE{9sH?v1~TTFanuiZ8}s)Gx1lvPx5X62rU&N1?_7y`{5_-t_0Abe z1v-fJuf!y^W^YQY^Y*p6k5?UM=b(fDfg+pr#jZK%mYz~Hz4nHmypRAF#3@?=#y^5%c38q*!aJU>vsx`TRBZ+uh zrPN7wub8mBMNa2@QXIabL@f0Q^y9kE_9u+yc>NYu&*5TZWL*~~kw3jHVh8Q93fXa7 z%ln&g~aA0dpY4~cCv;U|aW=v#;^Q^h}R$@6~gGVNanf$T+ifSor8>+CV z{OoA5cE)gzoZoGHr4LVAw0eXOOkJ^<9V5+l2y9&1Lp=uEZbQhtWxJ=4i#LSNix7Zp zZMwKTqruOAPwC5FxVK3Yg^%RpZ05}5f{`{k-vX7~yij^W#`WsnzzXJOuIDtz!?s>| zU>tCLxoR!*uHW-iy#@yLi)Tf-l|uPP`a5g>!>iJ=;{I>)bLUy#>HTIqa&6P_^IbpB zsg-zyuHj(WP;f}t%@6FHSq<#kasLfqSHX7Oq0a3Jsw>#x;od4FHwpNZk_blYj7U3I V0$TRMx;JkJMD;yJZaQ)@??0b02G{@q literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/icon_local-resetxhdpi.png b/app/src/main/res/drawable-xhdpi/icon_local-resetxhdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..2813cb448d86b4f8186c955c0bf3ce3727e41214 GIT binary patch literal 1241 zcmeAS@N?(olHy`uVBq!ia0vp^sX&~Qk(@Ik;M!QVyYm_=ozH)fq{Xg z+tbA{q=ND7+|z;5jsk7B_3j__3_rn;%c92o`1ZX9jx{_!Y;7D9@~pZz1O(SiVT}3y zq?h6P4c+N`&b)E9?XQpd8=5QHy5z3w{9V=a9v!}YTUs-sCPcnsg@{84mx30nz*MFV zFGiQ842yyo0yP^53!hm2|0(~z+75(5l`h-?$z4*&KwKv1vfu^wz;>s zuOxqoU;OsIzK4C$4h9=$NFV=urgquJlpqV$n$0#>3e(t)pxyQa*ua9y$^&+28){fHg!ZZ2|_d8-i=m+Y@ndFY#? z)zoDhM1pdP#SgMeIv?m2iuU%Ia%hp)%M7Du5~|fX-`~CZ%db?n{swOX<7Ovj_v3>kiA9Or|9XteK9G* znx`1R>2Jb~pk346X!N*s$?q}y8rmf=uS=j*?Dh%~%WI0FCs&kd}b+`zo=Bp zsmN*KlxtPXb31;1y;gMX7*BiyZ^A9B&P5BAGnf3?ynB_N*ZS^xy05#{Wef!hSmsB+ zb5%K7?pwK{`_k!E#~Q0cf*#NMC7RkJ&>E+s#;$nh)uyYHmzF3l3^{e_<8StRkL_kL zMk@up>da1_Xi?j} zqFA5C$4&EYc>7N5I_b&r{vFq@C)ZvtTi9p5{o%Ko)XJRa8DT;TCagQ_d~e&W%G}zo zE2&2KydG89i=A^q<=K^M!4VHWb5GLr>SibsJ62zXeL*tVD7Vvif*kD z9age;gcdu=sQi=?n746HuwvPl{W;8wR!0(-#jzC#yh^`VUznc|*}CigU0_+o;OXk; Jvd$@?2>{2kD+>Ss literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/icon_local-savexhdpi.png b/app/src/main/res/drawable-xhdpi/icon_local-savexhdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..0cf81430cc21e8ef2d92fca605c7b4ef16cd2f99 GIT binary patch literal 1154 zcmeAS@N?(olHy`uVBq!ia0vp^sX&~Qk(@Ik;M!QVyYm_=ozH)fq{X= z#M8wwq+-t7IR|rZI|#U{JH9LQvpKfzz{>-EtYPfeCNl7cX?esrK4E5*Tg&w*L|`TJ zZsyk~X2&)*v8D+g6xiwg_RXh!i}xA9Dofq#iqhL_w%>m1aq!XJUk99*GAs&W2-Iv? zA>t6irJ%(sFqNspi_rzU@RP$=>KhcN+uwTbq77a#Lp4ub`^iC-XW_Z!@yi|HsNynbGxYW3s5-M%B7$0dI_#=By4@ zGTPo_d|X_ndHJ#x`%B(zzj;5tulCn9k*`L_>fEh^Pi-@5UNwK?HT?qz7vK4umo4ng zadc8q!jtY}x=A^aM;>>tm#udR*YeKDkzDv_@sHZ1J3{W(Yg;)w*Dk-|El)PR5mRZwQV{p zPwCuVw&Hr{HdB!qH#RMq^l46pb@PLbB0f2hYS9z!tTy{H(PW!W@H(NxN2jGu3bNRy zC)2IkuY3B*5{2W_QoGW*a)1g|RZX_}#IDa-y>H_Tj>!{+q@t^v&rG(c{?V^FS99UU zRJ;F?74!L+E-RjNU-UE3=jH#SGFN>AyLqfwlTI%;Q)6op5!+N3oVZW#cGh9j&C?r7 zy^n?&1w6{W7x>BC{rjx?8OfZzYum5I}@Ci(g&57JJhwqz+G5<^%>B%|IU&tnf#XLDPX^pgc z#F@9V?eBlQzghKnp4hx4zg%46J74G=TRku6bNrt7zyz@3{C*y{`)5(p`INj#<_{x- zJa;~LwnOK^%BOmZ?2FWOm#%l2cT`2V+^y{GYcp3{->MHc%0*(Q=BBb$cpup%a@t_; z;qG~TGgN-dKE4{%FPCe#vuIkH;D zvPL-hu5v)F|KLALWRN8)z4*}Q$iB}G&v0a literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_local-activatexxhdpi.png b/app/src/main/res/drawable-xxhdpi/icon_local-activatexxhdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..600e6ee61c33f54be6ebc656cfe97ab182d9695d GIT binary patch literal 2678 zcmbuB>pv3=8^6`-VWh5CX|+}5tEXIun-z4 zIjrRnMUKf~8Rf9y&Z)b2^bb5Qp6A8y`h7mX>w59~T(7>F_I4HkNo7ePAt8X3CE9V% z^Y%m&7u%bI9m*4XCJ|pOwm`pkdQM$YWsFf(7!-^sc ze@wAsoli;|s`S|rYAi3w-PzqFt@bag8|>nW3(04t!Vw}oQ-SF92!VNwE=r}Il~uQ9 zGH8@S&f*E>xXZ>Z94`GGIZZZ1@~cTRX``sCDxW)U`q^_yjOKS}=l(e&R7#J4POmx@~j>Uy7 z4h<*jkTfdr>|HZHYds}lbFw;T^}m#3H0!ZUJa;ps&jHI%mYM^@i!(2mOko=p&wc3~(iu_kUKtfhGEo#~&p zeJfJEE2uOU?UkxSxcc3^x`4Bb(45eX_L7-InQv^CEcNeiqPK=J)q|TL;MV2vZsh|z zQ>M3DZ`6%X=eJrbPo=j<{R>&whYs*U-lm*`BFc&Lw!{~(U{58r|gFTU)I)zSeoxV_eK>tMCU(ExG$ z>v#v(!LI5&Dhp+atL9_~3_3v6H5$E~uB_Fm=oYukFmTWDy$0OAViL4^^ibouIrLX{ zY+=0F9cKboEB!J0gRu!+`3G?R$d%hNc>Aivfm%i*fqDZtb#7xv)u7ANLUX}zrbd)K zUfjTvDX_b6tkM%RK@7NK6qHh-U;nV^<7o_>`JP?Tqq|;N%Z{BjUjyr_JiMS0Bpq@|A>tcZF$u_}V7lQ6{?!%%oJ3wuDr+D243|54N`|A7yy{$nti#E@;Y<4+&5i}FI#`Wr zd?(2aL{z+6TG~&y9*}Fa&$TM~))~DKJ)+_zC0Kb5z(+NB$Iy4hQw_}koaW$BQUWF7 zw#f)?@3$?P()cjH>yMKX)dwuLg? zADpqd1wbYbJe>L>tQhmd=#-qK>v5^=QaUJ=2Fv~9RO{bw;|r50CU;DI%TI&q3c7r6 zf26@W(Fx{$x|?5H6gB6$}8CdE)Y*1ekAXap-7{QUQ}{wa$z8}o)IQ- z@a_eTC6N@Mb;4)3k0Ta5#ZBNC@zk0$n)IvV6?L}KfRvOMQ zSb4F+rH&yGnWz4Mb)Y6dFU`Mm3YBqi5GW7+nfv~m(yELcK;|pWz=Z}nU+b1o@#@0( z;`?L=`_ULJB@d(o|At#7Pm@i)Zr%mXYc@>y4qsvjS~hBWXR|dU=6Mfz>BL7(bcqE5Lopnd$alLF}wXX zQ99C&YPa4ic*IH&bK_RQXdB8RK>uXYpoNl9SCSJQxmMynABNobWv6gu$l{|ckgZ(q zM?%<#N<7veMy5O+k9frjxcb_WHCQL-5D5Vd9$7DMN~b}rUPp&yBn^95sk9aQS1Ou) zOIiqfbU?4h(kqVnXLW>2rqtlE=$SL8;POSNAjRrM!St zx|i0dBIt%lvRe=De&ZPfxXi;z$Wl(C0+oKy_VGq4b-=uY0@q<<>d@qu%`Ir;;C1uY2l<@S z%Vzd6dL5W&g4iq_Ht)VF_fCF}l@BGg_Uz&L&0+yZ=djLzmI;u0gZ_O2eRR>SVl1mt zEJ+%Xq6?P6re*lviP8F3`#`?#8~BeUf1c|0zc{HLKwAXjo4qA^{{l+e{ScK!oL=cq z*x;~~=;cH)C{r0*7g#l3zkL-JxVH#z-tR%e1pAR5<1xn$gz;OPO9W*;1Q_jjHT`V tzIPf9`g>G`EyMnwIQ3s(Ot!CSR|rLSMR|Jv#n=N$AuDq`G!x}X`VTK&0rvm^ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_local-resetxxhdpi.png b/app/src/main/res/drawable-xxhdpi/icon_local-resetxxhdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9d659dd714b05dd4f0fb92712dc8f1701d0814 GIT binary patch literal 1884 zcmcJQX*Ao38pbnf32AfD6t%U2ia{(@Tdfsas1g-IsG==`Dyo*sSnAlKA|!u14T2(w zXd5%Moz^}nqG(Y}g&35nV#d;O-LLoay&sT`eKq|)n(GM5Bs}eyVF{l&D=6Zbjmx^l`1qWE>WzEe& zv~Ntho<>%*P)E7aXJOj4lw_f|;-t7~k*f16!V<>TGdP^a`HA;6bd1}}%CW=!&CMoE z>hKAY{roQ*#BW^(0079^g41p!c#2C5*#)>Eh0>#?7lKsZll&bK!0T>; zQS7RMcQ;{(sh_xWc>g=%<&;|*W9tOwSaTRhn!0L1Geu)t@VrAEX<(Inxj;L2nPtYQ zts&ke?Wv}YpG}KE-YMj+s_dL@K{E?#s9)l(oY6O}s&_WT@ylQTyC4{yw0|5}L~q9;G1d z*?Qd9V&T0jJ%q!zO;Y?bwWV%R(J+bld1WV(h2z@P8)XG9$s@3^MyRO`Ybm&+G{e-n z0=~3bx{I-Y)N}4PtXaR4g`n`lC!^u2#6xd`v@;r0DOuEq8zHZ_lt%$}gA*Rj6(lyR z0ZnFXwfDc`&jfeuOIYe?^bV-Y9)0xCF2fct{~hpxFnyq`No}YZp#12btV)Y8Kt{Ki zke4@d1;0bGm)#Lpn9NYwO0FHIrtyi3k=6mR)q*%X7yg&@M0#O2p7-(l`n?dTz-|?8 zMSj38BbWErP}j&rO_gVn_d)DcLNDj5$@a)-IxwpWjM%PdIN8f&lfZ!TrcQjnr7x$8 zQISY0o#UOt0T6=Ybs`3OfN)33nL02t`t>_<7%_fBTz;T3E2gRrj{)lPpqtT%1_cNw zn>`RKbG#++dB{=ZBv|tTh3>6YuLn8P%_?-J)3A7B-R`O-YlSma8S)E!ISxDbxodkA z62>zpdi?hZDFHfv^GWQ+NUcZ;#rOEvfX5&~_iwnLP=sM}wq-t#zvXo8 zeOjE3rIS9K6wasAHfkxnY~r-u&qC?y#8}x?+PW4vLl$9cMMpoBk;8^qa~>}gl%`T` z1aQD8n1PSPk0@vYi$`&tEfjOm6xTRb3P#2Aqb+*xIQaJ`=07a1TBw#f~Fz7ejk`cc|CUa zeG#m8jto2_Oz+KY*NNdW)XiAn>6x?(tx0HEbAfxArD&27Bp2^DK3&*D?NnM{!%n*8 z=aj$U&V33e^!8->-`71~if@y?mxX`a`;i$a!3dX(O0S$#mQS#Hm*Go>@SnheHQO9` zvEbclyTK)?PU88a_-1Ib+v~*0P>l4n8GiJZg?scKd(lRCO%toHKCY~#x4|lM4ttgy z_aH@L(xdt3Ul|RdCyK4+) z2&iNeyTzB?&}e(Hoo|;_DTJr z3c3trNNhv(gJzL7?Q8MFc1XK#UlOVnB?7^AdG{?QtY}X{Bb|y&(}kOCv{nDe4Dyw9 z_%v!*BEMfC(qz~CJi?o?367IJNC;(*eb%>c=zeP7Y#V%gXKh74Ln5EgH>elKws>n& z`0rV%SJisaq+o&0E{qhY?#L?)v=FKB&ZZoa2zGioR6U%FzzQzci!KkJ%rTK91>Ulz zG=gQH;WLwP0-Lz#f`<#z=>Hos{+mGodVPlw{;$PjZ}i92j&TWcvU5c-uLPw18(*Dg AVE_OC literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/icon_local-savexxhdpi.png b/app/src/main/res/drawable-xxhdpi/icon_local-savexxhdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..20448e4bf98468272a5b298fae35794acb74ce3d GIT binary patch literal 1694 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/icon_local-savexxxhdpi.png b/app/src/main/res/drawable-xxxhdpi/icon_local-savexxxhdpi.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ecc45ac029723637b70dfd5093978a97a8c84a GIT binary patch literal 2249 zcmb_e`#;l*8=sTDnM-X-e!ZR_p4W4Ub8$YTAd8fRKp+YZ zM7*oS3nXZh`H#fn(pw%%9MqQx20$Q&hyR9DP{>s$2t+2-0dIFaIOFT6o$JWK9S!2Z z_8-sgdsj}hO*%J14^n0FyCMoHQk77*E>AapI_C?&c6)WuTYCDuN8 zH1PCS>F)b;0sNGEt9L|1%%{%DNeX1X{6X;Ln*(s@LoLMvcEHU@B4jfQB8!$n;D6I& zNV~xP?Sz=ULngc+J;XN3cROzI+LHT76wH~;ZAnu*9aafU6Z(30p`vX2rF(`i{<2-& zJL|XX#VJZ(Lr3{mk56V9os%0VgFzinIE5o{DFFp!bJwMUVYro{S8fZlx+bt9 ztU-d#f&qBQ)od|B_`H69u%$)ZXf72?>kLrklFFHnE_}Xxt;y4v8BjQy`~CTh+g>EM zB#qm0!r7SACXVG@vc3WZ+P#EO=Yy1f`>n0`e!*@d36=?t!Uf;=(CBzTiEK(!=1O08!<)ckDE)$7(s3ohRSzaez(kB8SdI`1 z35nLv5Od4~bU(bS4Zj$VcYRjYS{!JgJK)%XWFguG9J=l@Lx5zZc1*AluPJO#_R_N` z_cWp`^}CdlDmT8?5W_<7C9-2Z-sj^US#8(+GZlOB^l%*|o>%t7Y?ZdLT!_i?Vdzsx zpXn)X{Ng40TI$L&&mOo)R0&x9D5&!9>-`!#EquG%;}C`9r&5*0@@YC%)7({C_IQ2F zhUBzPu;H9$TGK$!stz6WYDCy{>An&AaM!32&d=ok?6nIb@nB=uV75f3y0Lx*E^x!T z-}t#J)#gDexfgq+KStSt_7oPE#6m4KRl1oiz8lMP<{Ku+9j-nI{Blsgw>4J2#aDQb zYd%BAlP|WpNCsruU_R}I`HTe`93!f-DApTnmw) zxxoaX4C*H9=o}+GQ_I3m&Rqs^U$4EMW?|lSag#x-w&U#6F3#N;qUAIywR;AK^?VU5 ziEk4vk$Q-PnPt(=QZ0@lI_}SNdTjG`s<7M+V1>wf8+{ziw_FbUlsf`*h}6KXQhkqS zVmnk=z-LtIaVE%TG~dj1QQ?Lh01m1}HFElt&{$J{Jtk<4Qlw}{O9*ZBr&kTxBUsvE z0x`to_rFux$r=i<_JWMGI~s6@?hyI+U2m;j4-S zD~N&SD|?At>*oWd6~wI)o_xZoPTjBR&6jS0F(x^)uwW?td;W}S^0JO+{$MD8HQux1 z$aKUd!UuKD8ioNc_zv)aAd>9#oY;>hp#MqniDsvxm|4K8R#E%BI>{+q$Hz#qZDlyi z^@WmHkB|}n^MhFY`qdkcqc&4FbgY`~WwJ*LJ^hYFcM4`+8rR#22sXk_|4Kb_P}vNz zaoN0hJxLR3GnF__xl1$fPbhN^)qjNMi_}WkWOYH-IOS~J57*zI7GHj2W8-{&y+F|W zet6zaQ4`F`tpvICkbo&gfq&&nyE=_K?=tZeRcYG-A zaw%1P1eoy9->vv?n Date: Tue, 17 Apr 2018 15:59:00 +0300 Subject: [PATCH 5/9] Rename Icon files --- ...activatehdpi.png => icon_local_activatehdpi.png} | Bin ...local-resethdpi.png => icon_local_resethdpi.png} | Bin ...n_local-savehdpi.png => icon_local_savehdpi.png} | Bin ...activatemdpi.png => icon_local_activatemdpi.png} | Bin ...local-resetmdpi.png => icon_local_resetmdpi.png} | Bin ...n_local-savemdpi.png => icon_local_savemdpi.png} | Bin ...tivatexhdpi.png => icon_local_activatexhdpi.png} | Bin ...cal-resetxhdpi.png => icon_local_resetxhdpi.png} | Bin ...local-savexhdpi.png => icon_local_savexhdpi.png} | Bin ...vatexxhdpi.png => icon_local_activatexxhdpi.png} | Bin ...l-resetxxhdpi.png => icon_local_resetxxhdpi.png} | Bin ...cal-savexxhdpi.png => icon_local_savexxhdpi.png} | Bin ...texxxhdpi.png => icon_local_activatexxxhdpi.png} | Bin ...resetxxxhdpi.png => icon_local_resetxxxhdpi.png} | Bin ...l-savexxxhdpi.png => icon_local_savexxxhdpi.png} | Bin 15 files changed, 0 insertions(+), 0 deletions(-) rename app/src/main/res/drawable-hdpi/{icon_local-activatehdpi.png => icon_local_activatehdpi.png} (100%) rename app/src/main/res/drawable-hdpi/{icon_local-resethdpi.png => icon_local_resethdpi.png} (100%) rename app/src/main/res/drawable-hdpi/{icon_local-savehdpi.png => icon_local_savehdpi.png} (100%) rename app/src/main/res/drawable-mdpi/{icon_local-activatemdpi.png => icon_local_activatemdpi.png} (100%) rename app/src/main/res/drawable-mdpi/{icon_local-resetmdpi.png => icon_local_resetmdpi.png} (100%) rename app/src/main/res/drawable-mdpi/{icon_local-savemdpi.png => icon_local_savemdpi.png} (100%) rename app/src/main/res/drawable-xhdpi/{icon_local-activatexhdpi.png => icon_local_activatexhdpi.png} (100%) rename app/src/main/res/drawable-xhdpi/{icon_local-resetxhdpi.png => icon_local_resetxhdpi.png} (100%) rename app/src/main/res/drawable-xhdpi/{icon_local-savexhdpi.png => icon_local_savexhdpi.png} (100%) rename app/src/main/res/drawable-xxhdpi/{icon_local-activatexxhdpi.png => icon_local_activatexxhdpi.png} (100%) rename app/src/main/res/drawable-xxhdpi/{icon_local-resetxxhdpi.png => icon_local_resetxxhdpi.png} (100%) rename app/src/main/res/drawable-xxhdpi/{icon_local-savexxhdpi.png => icon_local_savexxhdpi.png} (100%) rename app/src/main/res/drawable-xxxhdpi/{icon_local-activatexxxhdpi.png => icon_local_activatexxxhdpi.png} (100%) rename app/src/main/res/drawable-xxxhdpi/{icon_local-resetxxxhdpi.png => icon_local_resetxxxhdpi.png} (100%) rename app/src/main/res/drawable-xxxhdpi/{icon_local-savexxxhdpi.png => icon_local_savexxxhdpi.png} (100%) diff --git a/app/src/main/res/drawable-hdpi/icon_local-activatehdpi.png b/app/src/main/res/drawable-hdpi/icon_local_activatehdpi.png similarity index 100% rename from app/src/main/res/drawable-hdpi/icon_local-activatehdpi.png rename to app/src/main/res/drawable-hdpi/icon_local_activatehdpi.png diff --git a/app/src/main/res/drawable-hdpi/icon_local-resethdpi.png b/app/src/main/res/drawable-hdpi/icon_local_resethdpi.png similarity index 100% rename from app/src/main/res/drawable-hdpi/icon_local-resethdpi.png rename to app/src/main/res/drawable-hdpi/icon_local_resethdpi.png diff --git a/app/src/main/res/drawable-hdpi/icon_local-savehdpi.png b/app/src/main/res/drawable-hdpi/icon_local_savehdpi.png similarity index 100% rename from app/src/main/res/drawable-hdpi/icon_local-savehdpi.png rename to app/src/main/res/drawable-hdpi/icon_local_savehdpi.png diff --git a/app/src/main/res/drawable-mdpi/icon_local-activatemdpi.png b/app/src/main/res/drawable-mdpi/icon_local_activatemdpi.png similarity index 100% rename from app/src/main/res/drawable-mdpi/icon_local-activatemdpi.png rename to app/src/main/res/drawable-mdpi/icon_local_activatemdpi.png diff --git a/app/src/main/res/drawable-mdpi/icon_local-resetmdpi.png b/app/src/main/res/drawable-mdpi/icon_local_resetmdpi.png similarity index 100% rename from app/src/main/res/drawable-mdpi/icon_local-resetmdpi.png rename to app/src/main/res/drawable-mdpi/icon_local_resetmdpi.png diff --git a/app/src/main/res/drawable-mdpi/icon_local-savemdpi.png b/app/src/main/res/drawable-mdpi/icon_local_savemdpi.png similarity index 100% rename from app/src/main/res/drawable-mdpi/icon_local-savemdpi.png rename to app/src/main/res/drawable-mdpi/icon_local_savemdpi.png diff --git a/app/src/main/res/drawable-xhdpi/icon_local-activatexhdpi.png b/app/src/main/res/drawable-xhdpi/icon_local_activatexhdpi.png similarity index 100% rename from app/src/main/res/drawable-xhdpi/icon_local-activatexhdpi.png rename to app/src/main/res/drawable-xhdpi/icon_local_activatexhdpi.png diff --git a/app/src/main/res/drawable-xhdpi/icon_local-resetxhdpi.png b/app/src/main/res/drawable-xhdpi/icon_local_resetxhdpi.png similarity index 100% rename from app/src/main/res/drawable-xhdpi/icon_local-resetxhdpi.png rename to app/src/main/res/drawable-xhdpi/icon_local_resetxhdpi.png diff --git a/app/src/main/res/drawable-xhdpi/icon_local-savexhdpi.png b/app/src/main/res/drawable-xhdpi/icon_local_savexhdpi.png similarity index 100% rename from app/src/main/res/drawable-xhdpi/icon_local-savexhdpi.png rename to app/src/main/res/drawable-xhdpi/icon_local_savexhdpi.png diff --git a/app/src/main/res/drawable-xxhdpi/icon_local-activatexxhdpi.png b/app/src/main/res/drawable-xxhdpi/icon_local_activatexxhdpi.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/icon_local-activatexxhdpi.png rename to app/src/main/res/drawable-xxhdpi/icon_local_activatexxhdpi.png diff --git a/app/src/main/res/drawable-xxhdpi/icon_local-resetxxhdpi.png b/app/src/main/res/drawable-xxhdpi/icon_local_resetxxhdpi.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/icon_local-resetxxhdpi.png rename to app/src/main/res/drawable-xxhdpi/icon_local_resetxxhdpi.png diff --git a/app/src/main/res/drawable-xxhdpi/icon_local-savexxhdpi.png b/app/src/main/res/drawable-xxhdpi/icon_local_savexxhdpi.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/icon_local-savexxhdpi.png rename to app/src/main/res/drawable-xxhdpi/icon_local_savexxhdpi.png diff --git a/app/src/main/res/drawable-xxxhdpi/icon_local-activatexxxhdpi.png b/app/src/main/res/drawable-xxxhdpi/icon_local_activatexxxhdpi.png similarity index 100% rename from app/src/main/res/drawable-xxxhdpi/icon_local-activatexxxhdpi.png rename to app/src/main/res/drawable-xxxhdpi/icon_local_activatexxxhdpi.png diff --git a/app/src/main/res/drawable-xxxhdpi/icon_local-resetxxxhdpi.png b/app/src/main/res/drawable-xxxhdpi/icon_local_resetxxxhdpi.png similarity index 100% rename from app/src/main/res/drawable-xxxhdpi/icon_local-resetxxxhdpi.png rename to app/src/main/res/drawable-xxxhdpi/icon_local_resetxxxhdpi.png diff --git a/app/src/main/res/drawable-xxxhdpi/icon_local-savexxxhdpi.png b/app/src/main/res/drawable-xxxhdpi/icon_local_savexxxhdpi.png similarity index 100% rename from app/src/main/res/drawable-xxxhdpi/icon_local-savexxxhdpi.png rename to app/src/main/res/drawable-xxxhdpi/icon_local_savexxxhdpi.png From eb2f628f1f0313f6ad5004b141153b7ec79cdad8 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Tue, 17 Apr 2018 20:28:52 +0200 Subject: [PATCH 6/9] unify names of same icon with different resolution --- ...cal_activatehdpi.png => icon_local_activate.png} | Bin ...con_local_resethdpi.png => icon_local_reset.png} | Bin ...{icon_local_savehdpi.png => icon_local_save.png} | Bin ...cal_activatemdpi.png => icon_local_activate.png} | Bin ...con_local_resetmdpi.png => icon_local_reset.png} | Bin ...{icon_local_savemdpi.png => icon_local_save.png} | Bin ...al_activatexhdpi.png => icon_local_activate.png} | Bin ...on_local_resetxhdpi.png => icon_local_reset.png} | Bin ...icon_local_savexhdpi.png => icon_local_save.png} | Bin ...l_activatexxhdpi.png => icon_local_activate.png} | Bin ...n_local_resetxxhdpi.png => icon_local_reset.png} | Bin ...con_local_savexxhdpi.png => icon_local_save.png} | Bin ..._activatexxxhdpi.png => icon_local_activate.png} | Bin ..._local_resetxxxhdpi.png => icon_local_reset.png} | Bin ...on_local_savexxxhdpi.png => icon_local_save.png} | Bin 15 files changed, 0 insertions(+), 0 deletions(-) rename app/src/main/res/drawable-hdpi/{icon_local_activatehdpi.png => icon_local_activate.png} (100%) rename app/src/main/res/drawable-hdpi/{icon_local_resethdpi.png => icon_local_reset.png} (100%) rename app/src/main/res/drawable-hdpi/{icon_local_savehdpi.png => icon_local_save.png} (100%) rename app/src/main/res/drawable-mdpi/{icon_local_activatemdpi.png => icon_local_activate.png} (100%) rename app/src/main/res/drawable-mdpi/{icon_local_resetmdpi.png => icon_local_reset.png} (100%) rename app/src/main/res/drawable-mdpi/{icon_local_savemdpi.png => icon_local_save.png} (100%) rename app/src/main/res/drawable-xhdpi/{icon_local_activatexhdpi.png => icon_local_activate.png} (100%) rename app/src/main/res/drawable-xhdpi/{icon_local_resetxhdpi.png => icon_local_reset.png} (100%) rename app/src/main/res/drawable-xhdpi/{icon_local_savexhdpi.png => icon_local_save.png} (100%) rename app/src/main/res/drawable-xxhdpi/{icon_local_activatexxhdpi.png => icon_local_activate.png} (100%) rename app/src/main/res/drawable-xxhdpi/{icon_local_resetxxhdpi.png => icon_local_reset.png} (100%) rename app/src/main/res/drawable-xxhdpi/{icon_local_savexxhdpi.png => icon_local_save.png} (100%) rename app/src/main/res/drawable-xxxhdpi/{icon_local_activatexxxhdpi.png => icon_local_activate.png} (100%) rename app/src/main/res/drawable-xxxhdpi/{icon_local_resetxxxhdpi.png => icon_local_reset.png} (100%) rename app/src/main/res/drawable-xxxhdpi/{icon_local_savexxxhdpi.png => icon_local_save.png} (100%) diff --git a/app/src/main/res/drawable-hdpi/icon_local_activatehdpi.png b/app/src/main/res/drawable-hdpi/icon_local_activate.png similarity index 100% rename from app/src/main/res/drawable-hdpi/icon_local_activatehdpi.png rename to app/src/main/res/drawable-hdpi/icon_local_activate.png diff --git a/app/src/main/res/drawable-hdpi/icon_local_resethdpi.png b/app/src/main/res/drawable-hdpi/icon_local_reset.png similarity index 100% rename from app/src/main/res/drawable-hdpi/icon_local_resethdpi.png rename to app/src/main/res/drawable-hdpi/icon_local_reset.png diff --git a/app/src/main/res/drawable-hdpi/icon_local_savehdpi.png b/app/src/main/res/drawable-hdpi/icon_local_save.png similarity index 100% rename from app/src/main/res/drawable-hdpi/icon_local_savehdpi.png rename to app/src/main/res/drawable-hdpi/icon_local_save.png diff --git a/app/src/main/res/drawable-mdpi/icon_local_activatemdpi.png b/app/src/main/res/drawable-mdpi/icon_local_activate.png similarity index 100% rename from app/src/main/res/drawable-mdpi/icon_local_activatemdpi.png rename to app/src/main/res/drawable-mdpi/icon_local_activate.png diff --git a/app/src/main/res/drawable-mdpi/icon_local_resetmdpi.png b/app/src/main/res/drawable-mdpi/icon_local_reset.png similarity index 100% rename from app/src/main/res/drawable-mdpi/icon_local_resetmdpi.png rename to app/src/main/res/drawable-mdpi/icon_local_reset.png diff --git a/app/src/main/res/drawable-mdpi/icon_local_savemdpi.png b/app/src/main/res/drawable-mdpi/icon_local_save.png similarity index 100% rename from app/src/main/res/drawable-mdpi/icon_local_savemdpi.png rename to app/src/main/res/drawable-mdpi/icon_local_save.png diff --git a/app/src/main/res/drawable-xhdpi/icon_local_activatexhdpi.png b/app/src/main/res/drawable-xhdpi/icon_local_activate.png similarity index 100% rename from app/src/main/res/drawable-xhdpi/icon_local_activatexhdpi.png rename to app/src/main/res/drawable-xhdpi/icon_local_activate.png diff --git a/app/src/main/res/drawable-xhdpi/icon_local_resetxhdpi.png b/app/src/main/res/drawable-xhdpi/icon_local_reset.png similarity index 100% rename from app/src/main/res/drawable-xhdpi/icon_local_resetxhdpi.png rename to app/src/main/res/drawable-xhdpi/icon_local_reset.png diff --git a/app/src/main/res/drawable-xhdpi/icon_local_savexhdpi.png b/app/src/main/res/drawable-xhdpi/icon_local_save.png similarity index 100% rename from app/src/main/res/drawable-xhdpi/icon_local_savexhdpi.png rename to app/src/main/res/drawable-xhdpi/icon_local_save.png diff --git a/app/src/main/res/drawable-xxhdpi/icon_local_activatexxhdpi.png b/app/src/main/res/drawable-xxhdpi/icon_local_activate.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/icon_local_activatexxhdpi.png rename to app/src/main/res/drawable-xxhdpi/icon_local_activate.png diff --git a/app/src/main/res/drawable-xxhdpi/icon_local_resetxxhdpi.png b/app/src/main/res/drawable-xxhdpi/icon_local_reset.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/icon_local_resetxxhdpi.png rename to app/src/main/res/drawable-xxhdpi/icon_local_reset.png diff --git a/app/src/main/res/drawable-xxhdpi/icon_local_savexxhdpi.png b/app/src/main/res/drawable-xxhdpi/icon_local_save.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/icon_local_savexxhdpi.png rename to app/src/main/res/drawable-xxhdpi/icon_local_save.png diff --git a/app/src/main/res/drawable-xxxhdpi/icon_local_activatexxxhdpi.png b/app/src/main/res/drawable-xxxhdpi/icon_local_activate.png similarity index 100% rename from app/src/main/res/drawable-xxxhdpi/icon_local_activatexxxhdpi.png rename to app/src/main/res/drawable-xxxhdpi/icon_local_activate.png diff --git a/app/src/main/res/drawable-xxxhdpi/icon_local_resetxxxhdpi.png b/app/src/main/res/drawable-xxxhdpi/icon_local_reset.png similarity index 100% rename from app/src/main/res/drawable-xxxhdpi/icon_local_resetxxxhdpi.png rename to app/src/main/res/drawable-xxxhdpi/icon_local_reset.png diff --git a/app/src/main/res/drawable-xxxhdpi/icon_local_savexxxhdpi.png b/app/src/main/res/drawable-xxxhdpi/icon_local_save.png similarity index 100% rename from app/src/main/res/drawable-xxxhdpi/icon_local_savexxxhdpi.png rename to app/src/main/res/drawable-xxxhdpi/icon_local_save.png From 00a0bf2f1a1376166294669a8c46472b7ccbac47 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Tue, 17 Apr 2018 20:37:28 +0200 Subject: [PATCH 7/9] local profile icons --- app/src/main/res/layout/localprofile_fragment.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/localprofile_fragment.xml b/app/src/main/res/layout/localprofile_fragment.xml index a08c6964e9..02aec264f8 100644 --- a/app/src/main/res/layout/localprofile_fragment.xml +++ b/app/src/main/res/layout/localprofile_fragment.xml @@ -151,7 +151,7 @@ android:paddingLeft="10dp" android:paddingRight="10dp" android:text="@string/activate_profile" - android:textColor="@color/colorProfileSwitchButton" /> + android:drawableLeft="@drawable/icon_local_activate" /> + android:drawableLeft="@drawable/icon_local_reset" />