diff --git a/.circleci/config.yml b/.circleci/config.yml index 795c6415f1..f9479bd008 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,7 +20,10 @@ jobs: # The next step will run the unit tests - android/run-tests: - test-command: ./gradlew -Pcoverage -PfirebaseDisable testFullDebugUnitTest jacocoTestFullDebugUnitTestReport + test-command: ./gradlew testFullDebugUnitTest + + - android/run-tests: + test-command: ./gradlew jacocoAllDebugReport # Then start the emulator and run the Instrumentation tests! # - android/start-emulator-and-run-tests: @@ -33,35 +36,7 @@ jobs: # command: | # ./gradlew assembleRelease - codecov/upload: - file: './app/build/jacoco/jacoco.xml' - - codecov/upload: - file: './automation/build/jacoco/jacoco.xml' - - codecov/upload: - file: './combo/build/jacoco/jacoco.xml' - - codecov/upload: - file: './core/build/jacoco/jacoco.xml' - - codecov/upload: - file: './dana/build/jacoco/jacoco.xml' - - codecov/upload: - file: './danar/build/jacoco/jacoco.xml' - - codecov/upload: - file: './danars/build/jacoco/jacoco.xml' - - codecov/upload: - file: './database/build/jacoco/jacoco.xml' - - codecov/upload: - file: './insight/build/jacoco/jacoco.xml' - - codecov/upload: - file: './medtronic/build/jacoco/jacoco.xml' - - codecov/upload: - file: './omnipod-common/build/jacoco/jacoco.xml' - - codecov/upload: - file: './omnipod-dash/build/jacoco/jacoco.xml' - - codecov/upload: - file: './omnipod-eros/build/jacoco/jacoco.xml' - - codecov/upload: - file: './rileylink/build/jacoco/jacoco.xml' - - codecov/upload: - file: './wear/build/jacoco/jacoco.xml' + file: './build/reports/jacoco/jacocoAllDebugReport/jacocoAllDebugReport.xml' workflows: # Below is the definition of your workflow. diff --git a/README.md b/README.md index 04e093e02b..a656d723e1 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,19 @@ # AndroidAPS - * Check the wiki: https://androidaps.readthedocs.io * Everyone who’s been looping with AndroidAPS needs to fill out the form after 3 days of looping https://docs.google.com/forms/d/14KcMjlINPMJHVt28MDRupa4sz4DDIooI4SrW0P3HSN8/viewform?c=0&w=1 [![Support Server](https://img.shields.io/discord/629952586895851530.svg?label=Discord&logo=Discord&colorB=7289da&style=for-the-badge)](https://discord.gg/4fQUWHZ4Mw) -[![Build status](https://travis-ci.org/nightscout/AndroidAPS.svg?branch=master)](https://travis-ci.org/nightscout/AndroidAPS) +[![CircleCI](https://circleci.com/gh/nightscout/AndroidAPS/tree/master.svg?style=svg)](https://circleci.com/gh/nightscout/AndroidAPS/tree/master) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/androidaps/localized.svg)](https://translations.androidaps.org/project/androidaps) [![Documentation Status](https://readthedocs.org/projects/androidaps/badge/?version=latest)](https://androidaps.readthedocs.io/en/latest/?badge=latest) -[![codecov](https://codecov.io/gh/MilosKozak/AndroidAPS/branch/master/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS) -dev: [![codecov](https://codecov.io/gh/MilosKozak/AndroidAPS/branch/dev/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS) +[![codecov](https://codecov.io/gh/nightscout/AndroidAPS/branch/master/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS) + +DEV: +[![CircleCI](https://circleci.com/gh/nightscout/AndroidAPS/tree/dev.svg?style=svg)](https://circleci.com/gh/nightscout/AndroidAPS/tree/dev) +[![codecov](https://codecov.io/gh/nightscout/AndroidAPS/branch/dev/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS) -![BTC](https://bitit.io/assets/coins/icon-btc-1e5a37bc0eb730ac83130d7aa859052bd4b53ac3f86f99966627801f7b0410be.svg) 3KawK8aQe48478s6fxJ8Ms6VTWkwjgr9f2 +Bitcoin Icon + +3KawK8aQe48478s6fxJ8Ms6VTWkwjgr9f2 diff --git a/app/build.gradle b/app/build.gradle index 8790d898fe..ec56c4557a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -109,7 +109,7 @@ android { defaultConfig { multiDexEnabled true versionCode 1500 - version "3.0.0.1" + version "3.0.0.1-dev" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' diff --git a/app/src/main/assets/OpenAPSAMA/determine-basal.js b/app/src/main/assets/OpenAPSAMA/determine-basal.js index 8202e7c74b..4e052e8e01 100644 --- a/app/src/main/assets/OpenAPSAMA/determine-basal.js +++ b/app/src/main/assets/OpenAPSAMA/determine-basal.js @@ -69,10 +69,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ if (bg < 39) { //Dexcom is in ??? mode or calibrating rT.reason = "CGM is calibrating or in ??? state"; if (basal <= currenttemp.rate * 1.2) { // high temp is running - rT.reason += "; setting current basal of " + basal + " as temp"; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp"; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } else { //do nothing. - rT.reason += ", temp " + currenttemp.rate + " <~ current basal " + basal + "U/hr"; + rT.reason += ", temp " + currenttemp.rate + " <~ current basal " + round(basal, 2) + "U/hr"; return rT; } } @@ -291,7 +291,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ rT.COB=meal_data.mealCOB; rT.IOB=iob_data.iob; - rT.reason="COB: " + meal_data.mealCOB + ", Dev: " + deviation + ", BGI: " + bgi + ", ISF: " + convert_bg(sens, profile) + ", Target: " + convert_bg(target_bg, profile) + "; "; + rT.reason="COB: " + round(meal_data.mealCOB, 1) + ", Dev: " + deviation + ", BGI: " + bgi + ", ISF: " + convert_bg(sens, profile) + ", Target: " + convert_bg(target_bg, profile) + "; "; if (typeof autosens_data !== 'undefined' && profile.autosens_adjust_targets && autosens_data.ratio != 1) rT.reason += "Autosens: " + autosens_data.ratio + "; "; if (bg < threshold) { // low glucose suspend mode: BG is < ~80 @@ -306,10 +306,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ rT.reason += ", min delta " + minDelta.toFixed(2) + ">0"; } if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) { - rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr"; + rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr"; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp"; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp"; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } @@ -327,7 +327,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr"; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp"; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp"; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } @@ -338,10 +338,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ rT.reason += ", bolus snooze: eventual BG range " + convert_bg(eventualBG, profile) + "-" + convert_bg(snoozeBG, profile); //console.error(currenttemp, basal ); if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) { - rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr"; + rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr"; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp"; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp"; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } else { @@ -363,7 +363,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ // if required temp < existing temp basal var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60; if (insulinScheduled < insulinReq - basal*0.3) { // if current temp would deliver a lot (30% of basal) less than the required insulin, raise the rate - rT.reason += ", "+currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " < req " + insulinReq + "-" + basal*0.3; + rT.reason += ", "+currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " < req " + insulinReq + "-" + (basal*0.3).toFixed(2); return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp); } if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate >= currenttemp.rate * 0.8)) { @@ -405,10 +405,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " > " + convert_bg(min_bg, profile) + " but Min. Delta " + minDelta.toFixed(2) + " < Exp. Delta " + expectedDelta; } if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) { - rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr"; + rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr"; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp"; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp"; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } @@ -422,10 +422,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ rT.reason += convert_bg(eventualBG, profile)+"-"+convert_bg(snoozeBG, profile)+" in range: no temp required"; if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) { - rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr"; + rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr"; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp"; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp"; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } @@ -439,10 +439,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ if (basaliob > max_iob) { rT.reason += "basaliob " + round(basaliob,2) + " > max_iob " + max_iob; if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) { - rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr"; + rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr"; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp"; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp"; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } else { // otherwise, calculate 30m high-temp required to get projected BG down to target diff --git a/app/src/main/assets/OpenAPSSMB/determine-basal.js b/app/src/main/assets/OpenAPSSMB/determine-basal.js index 13a220e528..020cd1b85b 100644 --- a/app/src/main/assets/OpenAPSSMB/determine-basal.js +++ b/app/src/main/assets/OpenAPSSMB/determine-basal.js @@ -169,7 +169,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ return rT; //return tempBasalFunctions.setTempBasal(0, 30, profile, rT, currenttemp); } else { //do nothing. - rT.reason += ". Temp " + currenttemp.rate + " <= current basal " + basal + "U/hr; doing nothing. "; + rT.reason += ". Temp " + currenttemp.rate + " <= current basal " + round(basal, 2) + "U/hr; doing nothing. "; return rT; } } @@ -920,10 +920,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ rT.reason += ", but Min. Delta " + minDelta.toFixed(2) + " > Exp. Delta " + convert_bg(expectedDelta, profile); } if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) { - rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr. "; + rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr. "; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp. "; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp. "; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } @@ -992,10 +992,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " > " + convert_bg(min_bg, profile) + " but Min. Delta " + minDelta.toFixed(2) + " < Exp. Delta " + convert_bg(expectedDelta, profile); } if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) { - rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr. "; + rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr. "; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp. "; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp. "; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } @@ -1006,10 +1006,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ if (! (microBolusAllowed && enableSMB )) { rT.reason += convert_bg(eventualBG, profile)+"-"+convert_bg(minPredBG, profile)+" in range: no temp required"; if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) { - rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr. "; + rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr. "; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp. "; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp. "; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } @@ -1023,10 +1023,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ if (iob_data.iob > max_iob) { rT.reason += "IOB " + round(iob_data.iob,2) + " > max_iob " + max_iob; if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) { - rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr. "; + rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr. "; return rT; } else { - rT.reason += "; setting current basal of " + basal + " as temp. "; + rT.reason += "; setting current basal of " + round(basal, 2) + " as temp. "; return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp); } } else { // otherwise, calculate 30m high-temp required to get projected BG down to target diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt index f4614d5a41..3ed805966e 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt @@ -271,6 +271,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { _binding = null } + private fun timestamp(ml: MealLink): Long = ml.bolusCalculatorResult?.let { it.timestamp } ?: ml.bolus?.let { it.timestamp } ?: ml.carbs?.let { it.timestamp } ?: 0L + inner class RecyclerViewAdapter internal constructor(var mealLinks: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder = @@ -280,16 +282,20 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { val profile = profileFunction.getProfile() ?: return val ml = mealLinks[position] + val sameDayPrevious = position > 0 && dateUtil.isSameDay(timestamp(ml), timestamp(mealLinks[position - 1])) + holder.binding.date.visibility = sameDayPrevious.not().toVisibility() + holder.binding.date.text = dateUtil.dateString(timestamp(ml)) + // Metadata holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || binding.showInvalidated.isChecked)).toVisibility() ml.bolusCalculatorResult?.let { bolusCalculatorResult -> - holder.binding.date.text = dateUtil.dateAndTimeString(bolusCalculatorResult.timestamp) + holder.binding.calcTime.text = dateUtil.timeString(bolusCalculatorResult.timestamp) } // Bolus holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus.isValid || binding.showInvalidated.isChecked)).toVisibility() ml.bolus?.let { bolus -> - holder.binding.bolusDate.text = dateUtil.timeString(bolus.timestamp) + holder.binding.bolusTime.text = dateUtil.timeString(bolus.timestamp) holder.binding.insulin.text = rh.gs(R.string.formatinsulinunits, bolus.amount) holder.binding.bolusNs.visibility = (bolus.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.bolusPump.visibility = (bolus.interfaceIDs.pumpId != null).toVisibility() @@ -317,7 +323,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { // Carbs holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || binding.showInvalidated.isChecked)).toVisibility() ml.carbs?.let { carbs -> - holder.binding.carbsDate.text = dateUtil.timeString(carbs.timestamp) + holder.binding.carbsTime.text = dateUtil.timeString(carbs.timestamp) holder.binding.carbs.text = rh.gs(R.string.format_carbs, carbs.amount.toInt()) holder.binding.carbsDuration.text = if (carbs.duration > 0) rh.gs(R.string.format_mins, T.msecs(carbs.duration).mins().toInt()) else "" holder.binding.carbsNs.visibility = (carbs.interfaceIDs.nightscoutId != null).toVisibility() @@ -330,6 +336,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { holder.binding.bolusRemove.tag = ml holder.binding.carbsRemove.tag = ml holder.binding.calculation.tag = ml + val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L + holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility() } override fun getItemCount(): Int { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt index ac640df4f6..0dca0e416f 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt @@ -152,7 +152,7 @@ class TreatmentsCareportalFragment : DaggerFragment() { _binding = null } - inner class RecyclerViewAdapter internal constructor(private var list: List) : RecyclerView.Adapter() { + inner class RecyclerViewAdapter internal constructor(private var therapyList: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TherapyEventsViewHolder { val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_careportal_item, viewGroup, false) @@ -160,18 +160,23 @@ class TreatmentsCareportalFragment : DaggerFragment() { } override fun onBindViewHolder(holder: TherapyEventsViewHolder, position: Int) { - val therapyEvent = list[position] + val therapyEvent = therapyList[position] holder.binding.ns.visibility = (therapyEvent.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = therapyEvent.isValid.not().toVisibility() - holder.binding.date.text = dateUtil.dateAndTimeString(therapyEvent.timestamp) + val sameDayPrevious = position > 0 && dateUtil.isSameDay(therapyEvent.timestamp, therapyList[position - 1].timestamp) + holder.binding.date.visibility = sameDayPrevious.not().toVisibility() + holder.binding.date.text = dateUtil.dateString(therapyEvent.timestamp) + holder.binding.time.text = dateUtil.timeString(therapyEvent.timestamp) holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh) holder.binding.note.text = therapyEvent.note holder.binding.type.text = translator.translate(therapyEvent.type) holder.binding.remove.tag = therapyEvent + val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L + holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility() } override fun getItemCount(): Int { - return list.size + return therapyList.size } inner class TherapyEventsViewHolder(view: View) : RecyclerView.ViewHolder(view) { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt index 4f9609043e..bdd0e4f424 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt @@ -125,13 +125,16 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility() holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility() + val sameDayPrevious = position > 0 && dateUtil.isSameDay(extendedBolus.timestamp, extendedBolusList[position-1].timestamp) + holder.binding.date.visibility = sameDayPrevious.not().toVisibility() + holder.binding.date.text = dateUtil.dateString(extendedBolus.timestamp) @SuppressLint("SetTextI18n") if (extendedBolus.isInProgress(dateUtil)) { - holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.timestamp) - holder.binding.date.setTextColor(rh.gc(R.color.colorActive)) + holder.binding.time.text = dateUtil.timeString(extendedBolus.timestamp) + holder.binding.time.setTextColor(rh.gc(R.color.colorActive)) } else { - holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.timestamp) + " - " + dateUtil.timeString(extendedBolus.end) - holder.binding.date.setTextColor(holder.binding.insulin.currentTextColor) + holder.binding.time.text = dateUtil.timeRangeString(extendedBolus.timestamp, extendedBolus.end) + holder.binding.time.setTextColor(holder.binding.insulin.currentTextColor) } val profile = profileFunction.getProfile(extendedBolus.timestamp) ?: return holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(extendedBolus.duration).mins()) @@ -141,6 +144,8 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate) if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor) holder.binding.remove.tag = extendedBolus + val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L + holder.binding.delimiter.visibility = dateUtil.isSameDay(extendedBolus.timestamp, nextTimestamp).toVisibility() } override fun getItemCount(): Int = extendedBolusList.size diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt index 7b48ff9684..91b46228be 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt @@ -181,7 +181,10 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { val profileSwitch = profileSwitchList[position] holder.binding.ph.visibility = (profileSwitch is ProfileSealed.EPS).toVisibility() holder.binding.ns.visibility = (profileSwitch.interfaceIDs_backing?.nightscoutId != null).toVisibility() - holder.binding.date.text = dateUtil.dateAndTimeString(profileSwitch.timestamp) + val sameDayPrevious = position > 0 && dateUtil.isSameDay(profileSwitch.timestamp, profileSwitchList[position - 1].timestamp) + holder.binding.date.visibility = sameDayPrevious.not().toVisibility() + holder.binding.date.text = dateUtil.dateString(profileSwitch.timestamp) + holder.binding.time.text = dateUtil.timeString(profileSwitch.timestamp) holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins()) holder.binding.name.text = if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName() else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else "" if (profileSwitch.isInProgress(dateUtil)) holder.binding.date.setTextColor(rh.gc(R.color.colorActive)) @@ -196,6 +199,8 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility() holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility() holder.binding.root.setBackgroundColor(rh.gc(if (profileSwitch is ProfileSealed.PS) R.color.defaultbackground else R.color.list_delimiter)) + val nextTimestamp = if (profileSwitchList.size != position + 1) profileSwitchList[position + 1].timestamp else 0L + holder.binding.delimiter.visibility = dateUtil.isSameDay(profileSwitch.timestamp, nextTimestamp).toVisibility() } override fun getItemCount(): Int { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt index 53e3fa5eba..c408fd4299 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt @@ -164,18 +164,23 @@ class TreatmentsTempTargetFragment : DaggerFragment() { holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility() holder.binding.remove.visibility = tempTarget.isValid.toVisibility() - holder.binding.date.text = dateUtil.dateAndTimeString(tempTarget.timestamp) + " - " + dateUtil.timeString(tempTarget.end) + val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position-1].timestamp) + holder.binding.date.visibility = sameDayPrevious.not().toVisibility() + holder.binding.date.text = dateUtil.dateString(tempTarget.timestamp) + holder.binding.time.text = dateUtil.timeRangeString(tempTarget.timestamp, tempTarget.end) holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(tempTarget.duration).mins()) holder.binding.low.text = tempTarget.lowValueToUnitsToString(units) holder.binding.high.text = tempTarget.highValueToUnitsToString(units) holder.binding.reason.text = translator.translate(tempTarget.reason) - holder.binding.date.setTextColor( + holder.binding.time.setTextColor( when { tempTarget.id == currentlyActiveTarget?.id -> rh.gc(R.color.colorActive) tempTarget.timestamp > dateUtil.now() -> rh.gc(R.color.colorScheduled) else -> holder.binding.reasonColon.currentTextColor }) holder.binding.remove.tag = tempTarget + val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L + holder.binding.delimiter.visibility = dateUtil.isSameDay(tempTarget.timestamp, nextTimestamp).toVisibility() } override fun getItemCount(): Int = tempTargetList.size diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt index 9fb0c844ba..6d4c536236 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt @@ -15,7 +15,6 @@ import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.entities.ExtendedBolus import info.nightscout.androidaps.database.entities.TemporaryBasal -import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.ValueWithUnit @@ -165,12 +164,15 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { holder.binding.ns.visibility = (tempBasal.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = tempBasal.isValid.not().toVisibility() holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility() + val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position-1].timestamp) + holder.binding.date.visibility = sameDayPrevious.not().toVisibility() + holder.binding.date.text = dateUtil.dateString(tempBasal.timestamp) if (tempBasal.isInProgress) { - holder.binding.date.text = dateUtil.dateAndTimeString(tempBasal.timestamp) - holder.binding.date.setTextColor(rh.gc(R.color.colorActive)) + holder.binding.time.text = dateUtil.timeString(tempBasal.timestamp) + holder.binding.time.setTextColor(rh.gc(R.color.colorActive)) } else { - holder.binding.date.text = dateUtil.dateAndTimeRangeString(tempBasal.timestamp, tempBasal.end) - holder.binding.date.setTextColor(holder.binding.duration.currentTextColor) + holder.binding.time.text = dateUtil.timeRangeString(tempBasal.timestamp, tempBasal.end) + holder.binding.time.setTextColor(holder.binding.duration.currentTextColor) } holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(tempBasal.duration).mins()) if (tempBasal.isAbsolute) holder.binding.rate.text = rh.gs(R.string.pump_basebasalrate, tempBasal.rate) @@ -186,6 +188,9 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility() if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor) holder.binding.remove.tag = tempBasal + + val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L + holder.binding.delimiter.visibility = dateUtil.isSameDay(tempBasal.timestamp, nextTimestamp).toVisibility() } override fun getItemCount(): Int = tempBasalList.size diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt index 8cb5681995..4d3620052b 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt @@ -20,6 +20,7 @@ import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.events.EventTreatmentUpdateGui +import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T @@ -131,14 +132,19 @@ class TreatmentsUserEntryFragment : DaggerFragment() { override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) { val current = entries[position] - holder.binding.date.text = dateUtil.dateAndTimeAndSecondsString(current.timestamp) + val sameDayPrevious = position > 0 && dateUtil.isSameDay(current.timestamp, entries[position-1].timestamp) + holder.binding.date.visibility = sameDayPrevious.not().toVisibility() + holder.binding.date.text = dateUtil.dateString(current.timestamp) + holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp) holder.binding.action.text = userEntryPresentationHelper.actionToColoredString(current.action) - holder.binding.s.text = current.note - holder.binding.s.visibility = if (current.note != "") View.VISIBLE else View.GONE + holder.binding.notes.text = current.note + holder.binding.notes.visibility = if (current.note != "") View.VISIBLE else View.GONE holder.binding.iconSource.setImageResource(userEntryPresentationHelper.iconId(current.source)) holder.binding.iconSource.visibility = View.VISIBLE holder.binding.values.text = userEntryPresentationHelper.listToPresentationString(current.values) holder.binding.values.visibility = if (holder.binding.values.text != "") View.VISIBLE else View.GONE + val nextTimestamp = if (entries.size != position + 1) entries[position + 1].timestamp else 0L + holder.binding.delimiter.visibility = dateUtil.isSameDay(current.timestamp, nextTimestamp).toVisibility() } inner class UserEntryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt index 56dbe3ccb7..29e6290571 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt @@ -179,9 +179,17 @@ class TreatmentDialog : DialogFragmentWithDate() { } } }) - } else + } else { uel.log(action, Sources.TreatmentDialog, - ValueWithUnit.Gram(carbsAfterConstraints).takeIf { carbs != 0 }) + ValueWithUnit.Gram(carbsAfterConstraints).takeIf { carbsAfterConstraints != 0 }) + if (detailedBolusInfo.carbs > 0) { + disposable += repository.runTransactionForResult(detailedBolusInfo.insertCarbsTransaction()) + .subscribe( + { result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") } }, + { aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it) } + ) + } + } } }) } diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt index c6624bb3d3..408b49ed38 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt @@ -4,11 +4,7 @@ import android.content.Context import android.os.Bundle import android.text.Editable import android.text.TextWatcher -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.Window -import android.view.WindowManager +import android.view.* import android.widget.AdapterView import android.widget.AdapterView.OnItemSelectedListener import android.widget.ArrayAdapter @@ -136,33 +132,36 @@ class WizardDialog : DaggerDialogFragment() { val maxCorrection = constraintChecker.getMaxBolusAllowed().value() bolusStep = activePlugin.activePump.pumpDescription.bolusStep - if (profileFunction.getUnits() == GlucoseUnit.MGDL) - binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input") - ?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher) - else - binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input") - ?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.ok, textWatcher) + if (profileFunction.getUnits() == GlucoseUnit.MGDL) { + binding.bgInput.setParams( + savedInstanceState?.getDouble("bg_input") + ?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher) + } else { + binding.bgInput.setParams( + savedInstanceState?.getDouble("bg_input") + ?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok, textWatcher) + } binding.carbsInput.setParams(savedInstanceState?.getDouble("carbs_input") - ?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, binding.ok, textWatcher) + ?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher) if (correctionPercent) { calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble() - binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.ok, textWatcher) + binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher) binding.correctionInput.value = calculatedPercentage binding.correctionUnit.text = "%" } else { binding.correctionInput.setParams( savedInstanceState?.getDouble("correction_input") - ?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.ok, textWatcher) + ?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher) binding.correctionUnit.text = rh.gs(R.string.insulin_unit_shortname) } binding.carbTimeInput.setParams(savedInstanceState?.getDouble("carb_time_input") - ?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher) + ?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher) initDialog() calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble() binding.percentUsed.text = rh.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100)) // ok button - binding.ok.setOnClickListener { + binding.okcancel.ok.setOnClickListener { if (okClicked) { aapsLogger.debug(LTag.UI, "guarding: ok already clicked") } else { @@ -175,12 +174,12 @@ class WizardDialog : DaggerDialogFragment() { } dismiss() } - binding.bgEnabledIcon.setOnClickListener { binding.bgCheckbox.isChecked = !binding.bgCheckbox.isChecked } - binding.trendEnabledIcon.setOnClickListener { binding.bgTrendCheckbox.isChecked = !binding.bgTrendCheckbox.isChecked } - binding.cobEnabledIcon.setOnClickListener { binding.cobCheckbox.isChecked = !binding.cobCheckbox.isChecked; processCobCheckBox(); } - binding.iobEnabledIcon.setOnClickListener { if (!binding.cobCheckbox.isChecked) binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked } + binding.bgCheckboxIcon.setOnClickListener { binding.bgCheckbox.isChecked = !binding.bgCheckbox.isChecked } + binding.trendCheckboxIcon.setOnClickListener { binding.bgTrendCheckbox.isChecked = !binding.bgTrendCheckbox.isChecked } + binding.cobCheckboxIcon.setOnClickListener { binding.cobCheckbox.isChecked = !binding.cobCheckbox.isChecked; processCobCheckBox(); } + binding.iobCheckboxIcon.setOnClickListener { if (!binding.cobCheckbox.isChecked) binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked } // cancel button - binding.cancel.setOnClickListener { + binding.okcancel.cancel.setOnClickListener { aapsLogger.debug(LTag.APS, "Dialog canceled: ${this.javaClass.name}") dismiss() } @@ -212,11 +211,17 @@ class WizardDialog : DaggerDialogFragment() { sp.putBoolean(rh.gs(R.string.key_wizard_correction_percent), isChecked) binding.correctionUnit.text = if (isChecked) "%" else rh.gs(R.string.insulin_unit_shortname) correctionPercent = binding.correctionPercent.isChecked - if (correctionPercent) - binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.ok, textWatcher) - else - binding.correctionInput.setParams(savedInstanceState?.getDouble("correction_input") - ?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.ok, textWatcher) + if (correctionPercent) { + binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher) + binding.correctionInput.customContentDescription = rh.gs(R.string.a11_correction_percentage) + } else { + binding.correctionInput.setParams( + savedInstanceState?.getDouble("correction_input") + ?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher + ) + binding.correctionInput.customContentDescription = rh.gs(R.string.a11_correction_units) + } + binding.correctionInput.updateA11yDescription() binding.correctionInput.value = if (correctionPercent) calculatedPercentage else Round.roundTo(calculatedCorrection, bolusStep) } } @@ -224,12 +229,12 @@ class WizardDialog : DaggerDialogFragment() { binding.profile.onItemSelectedListener = object : OnItemSelectedListener { override fun onNothingSelected(parent: AdapterView<*>?) { ToastUtils.showToastInUiThread(ctx, rh.gs(R.string.noprofileset)) - binding.ok.visibility = View.GONE + binding.okcancel.ok.visibility = View.GONE } override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { calculateInsulin() - binding.ok.visibility = View.VISIBLE + binding.okcancel.ok.visibility = View.VISIBLE } } // bus @@ -241,6 +246,14 @@ class WizardDialog : DaggerDialogFragment() { }, fabricPrivacy::logException) ) + setA11yLabels() + } + + private fun setA11yLabels() { + binding.bgInput.editText?.id?.let { binding.bgInputLabel.labelFor = it } + binding.carbsInput.editText?.id?.let { binding.carbsInputLabel.labelFor = it } + binding.correctionInput.editText?.id?.let { binding.correctionInputLabel.labelFor = it } + binding.carbTimeInput.editText?.id?.let { binding.carbTimeInputLabel.labelFor = it } } override fun onDestroyView() { @@ -268,14 +281,14 @@ class WizardDialog : DaggerDialogFragment() { } private fun processEnabledIcons() { - binding.bgEnabledIcon.alpha = if (binding.bgCheckbox.isChecked) 1.0f else 0.2f - binding.trendEnabledIcon.alpha = if (binding.bgTrendCheckbox.isChecked) 1.0f else 0.2f - binding.iobEnabledIcon.alpha = if (binding.iobCheckbox.isChecked) 1.0f else 0.2f - binding.cobEnabledIcon.alpha = if (binding.cobCheckbox.isChecked) 1.0f else 0.2f - binding.bgEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() - binding.trendEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() - binding.iobEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() - binding.cobEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() + binding.bgCheckboxIcon.alpha = if (binding.bgCheckbox.isChecked) 1.0f else 0.2f + binding.trendCheckboxIcon.alpha = if (binding.bgTrendCheckbox.isChecked) 1.0f else 0.2f + binding.iobCheckboxIcon.alpha = if (binding.iobCheckbox.isChecked) 1.0f else 0.2f + binding.cobCheckboxIcon.alpha = if (binding.cobCheckbox.isChecked) 1.0f else 0.2f + binding.bgCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() + binding.trendCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() + binding.iobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() + binding.cobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() } private fun saveCheckedStates() { @@ -442,10 +455,10 @@ class WizardDialog : DaggerDialogFragment() { val insulinText = if (wizard.calculatedTotalInsulin > 0.0) rh.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin).formatColor(rh, R.color.bolus) else "" val carbsText = if (carbsAfterConstraint > 0.0) rh.gs(R.string.format_carbs, carbsAfterConstraint).formatColor(rh, R.color.carbs) else "" binding.total.text = HtmlHelper.fromHtml(rh.gs(R.string.result_insulin_carbs, insulinText, carbsText)) - binding.ok.visibility = View.VISIBLE + binding.okcancel.ok.visibility = View.VISIBLE } else { binding.total.text = HtmlHelper.fromHtml(rh.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt()).formatColor(rh, R.color.carbs)) - binding.ok.visibility = View.INVISIBLE + binding.okcancel.ok.visibility = View.INVISIBLE } binding.percentUsed.text = rh.gs(R.string.format_percent, wizard.percentageCorrection) calculatedPercentage = wizard.calculatedPercentage diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt index 7184302bea..14deed2bb4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt @@ -110,7 +110,7 @@ class OpenAPSAMAFragment : DaggerFragment() { binding.profile.text = jsonFormatter.format(determineBasalAdapterAMAJS.profileParam) binding.mealdata.text = jsonFormatter.format(determineBasalAdapterAMAJS.mealDataParam) - binding.scriptdebugdata.text = determineBasalAdapterAMAJS.scriptDebug + binding.scriptdebugdata.text = determineBasalAdapterAMAJS.scriptDebug.replace("\\s+".toRegex(), " ") } if (openAPSAMAPlugin.lastAPSRun != 0L) { binding.lastrun.text = dateUtil.dateAndTimeString(openAPSAMAPlugin.lastAPSRun) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.kt index 647f60ef04..b93170d2ac 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.kt @@ -110,7 +110,7 @@ class OpenAPSSMBFragment : DaggerFragment() { binding.profile.text = jsonFormatter.format(determineBasalAdapterSMBJS.profileParam) binding.mealdata.text = jsonFormatter.format(determineBasalAdapterSMBJS.mealDataParam) - binding.scriptdebugdata.text = determineBasalAdapterSMBJS.scriptDebug + binding.scriptdebugdata.text = determineBasalAdapterSMBJS.scriptDebug.replace("\\s+".toRegex(), " ") openAPSSMBPlugin.lastAPSResult?.inputConstraints?.let { binding.constraints.text = it.getReasons(aapsLogger) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt index 8b2be42563..111df21369 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt @@ -107,6 +107,7 @@ class ActionsFragment : DaggerFragment() { private var sensorLevelLabel: TextView? = null private var insulinLevelLabel: TextView? = null private var pbLevelLabel: TextView? = null + private var cannulaOrPatch: TextView? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -153,6 +154,7 @@ class ActionsFragment : DaggerFragment() { sensorLevelLabel = view.findViewById(R.id.sensor_level_label) insulinLevelLabel = view.findViewById(R.id.insulin_level_label) pbLevelLabel = view.findViewById(R.id.pb_level_label) + cannulaOrPatch = view.findViewById(R.id.cannula_or_patch) profileSwitch?.setOnClickListener { ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog") @@ -319,6 +321,10 @@ class ActionsFragment : DaggerFragment() { tempTarget?.visibility = (profile != null && !loop.isDisconnected).toVisibility() tddStats?.visibility = pump.pumpDescription.supportsTDDs.toVisibility() + cannulaOrPatch?.text = if (pump.pumpDescription.isPatchPump) rh.gs(R.string.patch_pump) else rh.gs(R.string.cannula) + val imageResource = if (pump.pumpDescription.isPatchPump) R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula + cannulaOrPatch?.setCompoundDrawablesWithIntrinsicBounds(imageResource, 0, 0, 0) + if (!config.NSCLIENT) { statusLightHandler.updateStatusLights(cannulaAge, insulinAge, reservoirLevel, sensorAge, sensorLevel, pbAge, batteryLevel) sensorLevelLabel?.text = if (activeBgSource.sensorBatteryLevel == -1) "" else rh.gs(R.string.careportal_level_label) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt index 50ce24891a..d82e315359 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt @@ -823,7 +823,15 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList fun updateTime(from: String) { binding.infoLayout.time.text = dateUtil.timeString(dateUtil.now()) // Status lights - binding.statusLightsLayout.statusLights.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility() + val isPatchPump = activePlugin.activePump.pumpDescription.isPatchPump + binding.statusLightsLayout.apply { + cannulaOrPatch.setImageResource(if (isPatchPump) R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula) + cannulaOrPatch.contentDescription = rh.gs(if (isPatchPump) R.string.statuslights_patch_pump_age else R.string.statuslights_cannula_age) + cannulaOrPatch.scaleX = if (isPatchPump) 1.4f else 2f + cannulaOrPatch.scaleY = cannulaOrPatch.scaleX + insulinAge.visibility = isPatchPump.not().toVisibility() + statusLights.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility() + } statusLightHandler.updateStatusLights( binding.statusLightsLayout.cannulaAge, binding.statusLightsLayout.insulinAge, diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt index 61e632306b..ba73fab429 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt @@ -40,12 +40,7 @@ class StatusLightHandler @Inject constructor( val pump = activePlugin.activePump val bgSource = activePlugin.activeBgSource handleAge(careportal_cannula_age, TherapyEvent.Type.CANNULA_CHANGE, R.string.key_statuslights_cage_warning, 48.0, R.string.key_statuslights_cage_critical, 72.0) - if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) { - careportal_insulin_age?.visibility = View.GONE - } else { - careportal_insulin_age?.visibility = View.VISIBLE - handleAge(careportal_insulin_age, TherapyEvent.Type.INSULIN_CHANGE, R.string.key_statuslights_iage_warning, 72.0, R.string.key_statuslights_iage_critical, 144.0) - } + handleAge(careportal_insulin_age, TherapyEvent.Type.INSULIN_CHANGE, R.string.key_statuslights_iage_warning, 72.0, R.string.key_statuslights_iage_critical, 144.0) handleAge(careportal_sensor_age, TherapyEvent.Type.SENSOR_CHANGE, R.string.key_statuslights_sage_warning, 216.0, R.string.key_statuslights_sage_critical, 240.0) if (pump.pumpDescription.isBatteryReplaceable || (pump is OmnipodErosPumpPlugin && pump.isUseRileyLinkBatteryLevel && pump.isBatteryChangeLoggingEnabled)) { handleAge(careportal_pb_age, TherapyEvent.Type.PUMP_BATTERY_CHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/insulin/ActivityGraph.kt b/app/src/main/java/info/nightscout/androidaps/plugins/insulin/ActivityGraph.kt index 93932d5633..c7f66ef4eb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/insulin/ActivityGraph.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/insulin/ActivityGraph.kt @@ -18,10 +18,11 @@ class ActivityGraph : GraphView { constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) - fun show(insulin: Insulin) { + fun show(insulin: Insulin, diaSample: Double? = null) { removeAllSeries() + val dia = diaSample ?: insulin.dia mSecondScale = null - val hours = floor(insulin.dia + 1).toLong() + val hours = floor(dia + 1).toLong() val bolus = Bolus( timestamp = 0, amount = 1.0, @@ -31,7 +32,7 @@ class ActivityGraph : GraphView { val iobArray: MutableList = ArrayList() var time: Long = 0 while (time <= T.hours(hours).msecs()) { - val iob = insulin.iobCalcForTreatment(bolus, time, insulin.dia) + val iob = insulin.iobCalcForTreatment(bolus, time, dia) activityArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.activityContrib)) iobArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.iobContrib)) time += T.mins(5).msecs() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt index 87c6875084..8892c397a9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.profile.local import android.os.Bundle import android.text.Editable import android.text.TextWatcher +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -20,7 +21,6 @@ import info.nightscout.androidaps.dialogs.ProfileSwitchDialog import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.GlucoseUnit import info.nightscout.androidaps.interfaces.Profile -import info.nightscout.shared.logging.AAPSLogger import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged @@ -31,8 +31,10 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.ui.SpinnerHelper import info.nightscout.androidaps.utils.ui.TimeListEdit import info.nightscout.shared.SafeParse +import info.nightscout.shared.logging.AAPSLogger import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign +import java.math.RoundingMode import java.text.DecimalFormat import javax.inject.Inject @@ -61,6 +63,8 @@ class LocalProfileFragment : DaggerFragment() { binding.basalGraph.show(ProfileSealed.Pure(it)) binding.icGraph.show(ProfileSealed.Pure(it)) binding.isfGraph.show(ProfileSealed.Pure(it)) + binding.targetGraph.show(ProfileSealed.Pure(it)) + binding.insulinGraph.show(activePlugin.activeInsulin, SafeParse.stringToDouble(binding.dia.text)) } } @@ -130,14 +134,22 @@ class LocalProfileFragment : DaggerFragment() { binding.name.addTextChangedListener(textWatch) binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch) binding.dia.tag = "LP_DIA" - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic_holder, "IC", rh.gs(R.string.ic_label), currentProfile.ic, null, hardLimits.minIC(), hardLimits.maxIC(), 0.1, DecimalFormat("0.0"), save) - basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", rh.gs(R.string.basal_label) + ": " + sumLabel(), currentProfile.basal, null, pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate, 0.01, DecimalFormat("0.00"), save) + TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic_holder, "IC", rh.gs(R.string.ic_long_label), currentProfile.ic, null, doubleArrayOf(hardLimits.minIC(), hardLimits.maxIC()), null, 0.1, DecimalFormat ("0.0"), save) + basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", rh.gs(R.string.basal_long_label) + ": " + sumLabel(), currentProfile.basal, null, doubleArrayOf(pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate), null, 0.01, DecimalFormat("0.00"), save) if (units == Constants.MGDL) { - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_label), currentProfile.isf, null, HardLimits.MIN_ISF, HardLimits.MAX_ISF, 1.0, DecimalFormat("0"), save) - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", rh.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1], 1.0, DecimalFormat("0"), save) + val isfRange = doubleArrayOf(HardLimits.MIN_ISF, HardLimits.MAX_ISF) + TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null, isfRange , null, 1.0, DecimalFormat("0"), save) + TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_MIN_BG, HardLimits.VERY_HARD_LIMIT_TARGET_BG, 1.0, DecimalFormat("0"), save) } else { - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_label), currentProfile.isf, null, Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL), Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL), 0.1, DecimalFormat("0.0"), save) - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", rh.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], GlucoseUnit.MMOL), Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[1], GlucoseUnit.MMOL), 0.1, DecimalFormat("0.0"), save) + val isfRange = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL)), + roundDown(Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL))) + TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null,isfRange , null, 0.1, DecimalFormat("0.0"), save) + val range1 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[0], GlucoseUnit.MMOL)), + roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[1], GlucoseUnit.MMOL))) + val range2 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[0], GlucoseUnit.MMOL)), + roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[1], GlucoseUnit.MMOL))) + Log.i("TimeListEdit", "build: range1" + range1[0] + " " + range1[1] + " range2" + range2[0] + " " + range2[1]) + TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, range1 , range2, 0.1, DecimalFormat("0.0"), save) } // Spinner @@ -175,6 +187,8 @@ class LocalProfileFragment : DaggerFragment() { binding.basalGraph.show(ProfileSealed.Pure(it)) binding.icGraph.show(ProfileSealed.Pure(it)) binding.isfGraph.show(ProfileSealed.Pure(it)) + binding.targetGraph.show(ProfileSealed.Pure(it)) + binding.insulinGraph.show(activePlugin.activeInsulin, SafeParse.stringToDouble(binding.dia.text)) } binding.profileAdd.setOnClickListener { @@ -265,6 +279,14 @@ class LocalProfileFragment : DaggerFragment() { updateGUI() } + private fun roundUp(number: Double): Double { + return number.toBigDecimal().setScale(1, RoundingMode.UP).toDouble() + } + + private fun roundDown(number: Double): Double { + return number.toBigDecimal().setScale(1, RoundingMode.DOWN).toDouble() + } + private fun updateGUI() { if (_binding == null) return val isValid = localProfilePlugin.isValidEditState(activity) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt index 6b00421a14..901bed4b26 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt @@ -7,8 +7,6 @@ import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import androidx.work.ListenableWorker -import androidx.work.workDataOf import dagger.android.support.DaggerFragment import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository @@ -118,7 +116,10 @@ class BGSourceFragment : DaggerFragment() { val glucoseValue = glucoseValues[position] holder.binding.ns.visibility = (glucoseValue.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = (!glucoseValue.isValid).toVisibility() - holder.binding.date.text = dateUtil.dateAndTimeString(glucoseValue.timestamp) + val sameDayPrevious = position > 0 && dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position-1].timestamp) + holder.binding.date.visibility = sameDayPrevious.not().toVisibility() + holder.binding.date.text = dateUtil.dateString(glucoseValue.timestamp) + holder.binding.time.text = dateUtil.timeString(glucoseValue.timestamp) holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits()) holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon()) holder.binding.remove.tag = glucoseValue diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt index 33f0c361e5..db01f9d7c0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt @@ -75,7 +75,7 @@ class MM640gPlugin @Inject constructor( when (val type = jsonObject.getString("type")) { "sgv" -> glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( - timestamp = jsonObject.getLong("sgv"), + timestamp = jsonObject.getLong("date"), value = jsonObject.getDouble("sgv"), raw = jsonObject.getDouble("sgv"), noise = null, diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt index f6b0a81b70..6be6a5ad2e 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt +++ b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt @@ -55,12 +55,8 @@ open class DataReceiver : DaggerBroadcastReceiver() { Intents.NS_EMULATOR -> OneTimeWorkRequest.Builder(MM640gPlugin.MM640gWorker::class.java) .setInputData(Data.Builder().also { - it.copyDouble(Intents.EXTRA_BG_ESTIMATE, bundle) - it.copyString(Intents.EXTRA_BG_SLOPE_NAME, bundle) - it.copyLong(Intents.EXTRA_TIMESTAMP, bundle) - it.copyDouble(Intents.EXTRA_RAW, bundle) - it.copyInt(Intents.EXTRA_SENSOR_BATTERY, bundle, -1) - it.copyString(Intents.XDRIP_DATA_SOURCE_DESCRIPTION, bundle) + it.copyString("collection", bundle) + it.copyString("data", bundle) }.build()).build() Telephony.Sms.Intents.SMS_RECEIVED_ACTION -> OneTimeWorkRequest.Builder(SmsCommunicatorPlugin.SmsCommunicatorWorker::class.java) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/ui/TimeListEdit.java b/app/src/main/java/info/nightscout/androidaps/utils/ui/TimeListEdit.java index 5f435b91d3..246792e17b 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/ui/TimeListEdit.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/ui/TimeListEdit.java @@ -57,6 +57,8 @@ public class TimeListEdit { private final double step; private final double min; private final double max; + private final double min2; + private final double max2; private final NumberFormat formatter; private final Runnable save; private LinearLayout layout; @@ -68,7 +70,7 @@ public class TimeListEdit { Context context, AAPSLogger aapsLogger, DateUtil dateUtil, - View view, int resLayoutId, String tagPrefix, String label, JSONArray data1, JSONArray data2, double min, double max, double step, NumberFormat formatter, Runnable save) { + View view, int resLayoutId, String tagPrefix, String label, JSONArray data1, JSONArray data2, double[] range1, double[] range2, double step, NumberFormat formatter, Runnable save) { this.context = context; this.aapsLogger = aapsLogger; this.dateUtil = dateUtil; @@ -79,8 +81,10 @@ public class TimeListEdit { this.data1 = data1; this.data2 = data2; this.step = step; - this.min = min; - this.max = max; + this.min = range1[0]; + this.max = range1[1]; + this.min2 = range2 != null ? range2[0] : 0; + this.max2 = range2 != null ? range2[1] : 0; this.formatter = formatter; this.save = save; buildView(); @@ -177,7 +181,13 @@ public class TimeListEdit { numberPickers1[position].setTextWatcher(new TextWatcher() { @Override public void afterTextChanged(Editable s) { - editItem(position, secondFromMidnight(position), SafeParse.stringToDouble(numberPickers1[position].getText()), value2(position)); + Double value1 = SafeParse.stringToDouble(numberPickers1[position].getText()); + Double value2 = value2(position); + if (data2 != null && value1 > value2) { + value2 = value1; + numberPickers2[position].setValue(value2); + } + editItem(position, secondFromMidnight(position), value1, value2); callSave(); log(); } @@ -197,7 +207,13 @@ public class TimeListEdit { numberPickers2[position].setTextWatcher(new TextWatcher() { @Override public void afterTextChanged(Editable s) { - editItem(position, secondFromMidnight(position), value1(position), SafeParse.stringToDouble(numberPickers2[position].getText())); + Double value1 = value1(position); + Double value2 = SafeParse.stringToDouble(numberPickers2[position].getText()); + if (data2 != null && value2 < value1) { + value1 = value2; + numberPickers1[position].setValue(value1); + } + editItem(position, secondFromMidnight(position), value1, value2); callSave(); log(); } @@ -246,7 +262,7 @@ public class TimeListEdit { fillSpinner(timeSpinner, secondFromMidnight(i), previous, next); editText1.setParams(value1(i), min, max, step, formatter, false, null); - editText2.setParams(value2(i), min, max, step, formatter, false, null); + editText2.setParams(value2(i), min2, max2, step, formatter, false, null); if (data2 == null) { editText2.setVisibility(View.GONE); diff --git a/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt index d1f9321746..c9a361dca5 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/wizard/BolusWizard.kt @@ -347,6 +347,8 @@ class BolusWizard @Inject constructor( ) else commonProcessing(ctx) + } else { + OKDialog.show(ctx, rh.gs(R.string.boluswizard), rh.gs(R.string.no_action_selected)) } } diff --git a/app/src/main/res/drawable/cb_backgroud_bg.xml b/app/src/main/res/drawable/cb_backgroud_bg.xml new file mode 100644 index 0000000000..cf493051a9 --- /dev/null +++ b/app/src/main/res/drawable/cb_backgroud_bg.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/drawable/cb_backgroud_cob.xml b/app/src/main/res/drawable/cb_backgroud_cob.xml new file mode 100644 index 0000000000..b73f1f3b39 --- /dev/null +++ b/app/src/main/res/drawable/cb_backgroud_cob.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/drawable/cb_backgroud_iob.xml b/app/src/main/res/drawable/cb_backgroud_iob.xml new file mode 100644 index 0000000000..bce5594f2a --- /dev/null +++ b/app/src/main/res/drawable/cb_backgroud_iob.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/drawable/cb_backgroud_trend.xml b/app/src/main/res/drawable/cb_backgroud_trend.xml new file mode 100644 index 0000000000..74e90acb2f --- /dev/null +++ b/app/src/main/res/drawable/cb_backgroud_trend.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/drawable/checkbox_bg_icon.xml b/app/src/main/res/drawable/checkbox_bg_icon.xml new file mode 100644 index 0000000000..0e2e6b7ed9 --- /dev/null +++ b/app/src/main/res/drawable/checkbox_bg_icon.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/drawable/checkbox_cob_icon.xml b/app/src/main/res/drawable/checkbox_cob_icon.xml new file mode 100644 index 0000000000..01184068a2 --- /dev/null +++ b/app/src/main/res/drawable/checkbox_cob_icon.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/drawable/checkbox_iob_icon.xml b/app/src/main/res/drawable/checkbox_iob_icon.xml new file mode 100644 index 0000000000..aba6d56c20 --- /dev/null +++ b/app/src/main/res/drawable/checkbox_iob_icon.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/drawable/checkbox_trend_icon.xml b/app/src/main/res/drawable/checkbox_trend_icon.xml new file mode 100644 index 0000000000..de7ca8e81d --- /dev/null +++ b/app/src/main/res/drawable/checkbox_trend_icon.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/drawable/ic_patch_pump_outline.xml b/app/src/main/res/drawable/ic_patch_pump_outline.xml new file mode 100644 index 0000000000..6e95a27545 --- /dev/null +++ b/app/src/main/res/drawable/ic_patch_pump_outline.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/layout/activity_logsetting.xml b/app/src/main/res/layout/activity_logsetting.xml index 50e1354cf1..4011279d11 100644 --- a/app/src/main/res/layout/activity_logsetting.xml +++ b/app/src/main/res/layout/activity_logsetting.xml @@ -23,7 +23,7 @@ + card_view:cardUseCompatPadding="true"> + android:orientation="vertical"> + android:background="@color/list_delimiter" + android:gravity="center" + android:text="1.1.2000" + android:textAppearance="?android:attr/textAppearanceMedium" /> - + android:gravity="center" + android:orientation="horizontal" + android:padding="6dp"> - + - + - + - + + + + + + + diff --git a/app/src/main/res/layout/careportal_stats_fragment.xml b/app/src/main/res/layout/careportal_stats_fragment.xml index b42553aa31..24e86b19f1 100644 --- a/app/src/main/res/layout/careportal_stats_fragment.xml +++ b/app/src/main/res/layout/careportal_stats_fragment.xml @@ -8,7 +8,8 @@ + android:layout_height="wrap_content" + android:focusable="true"> - + android:layout_height="wrap_content" + android:focusable="true"> + android:layout_height="wrap_content" + android:focusable="true"> + android:layout_height="wrap_content" + android:focusable="true"> + android:layout_height="wrap_content" + android:focusable="true"> + android:layout_height="wrap_content" + android:focusable="true"> + android:layout_height="wrap_content" + android:focusable="true"> + android:layout_height="wrap_content" + android:focusable="true"> - - - - - + + + android:layout_height="40dp" + app:customContentDescription="@string/a11y_current_bg" /> - + android:layout_gravity="center_horizontal" + app:customContentDescription="@string/treatments_wizard_carbs_label" /> - - - + android:layoutDirection="rtl" + android:padding="2dp" + android:text="%" + android:textAppearance="@style/TextAppearance.AppCompat.Medium" + android:textStyle="bold" /> - + android:layout_gravity="center_horizontal" + app:customContentDescription="@string/a11_correction_units" /> - - + android:drawableEnd="@drawable/ic_visibility" /> - + android:layout_height="fill_parent" + android:button="@drawable/checkbox_bg_icon" + android:checked="true" + android:contentDescription="@string/treatments_wizard_bg_label" /> - + android:layout_height="fill_parent" + android:button="@drawable/checkbox_trend_icon" + android:checked="true" + android:contentDescription="@string/bg_trend_label" /> - + android:layout_height="fill_parent" + android:button="@drawable/checkbox_iob_icon" + android:checked="true" + android:contentDescription="@string/iob" /> - + android:layout_height="fill_parent" + android:button="@drawable/checkbox_cob_icon" + android:checked="true" + android:contentDescription="@string/treatments_wizard_cob_label" /> -