diff --git a/README.md b/README.md
index bb32ee30d0..a656d723e1 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,16 @@
[![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
+
+
+3KawK8aQe48478s6fxJ8Ms6VTWkwjgr9f2
diff --git a/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt
index 1f45202ab0..25fc86cf2e 100644
--- a/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt
+++ b/app/src/main/java/info/nightscout/androidaps/activities/ProfileHelperActivity.kt
@@ -239,6 +239,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
}
ToastUtils.showToastInUiThread(this, R.string.invalidinput)
}
+ binding.age.editText?.id?.let { binding.ageLabel.labelFor = it }
+ binding.tdd.editText?.id?.let { binding.tddLabel.labelFor = it }
+ binding.weight.editText?.id?.let { binding.weightLabel.labelFor = it }
+ binding.basalpctfromtdd.editText?.id?.let { binding.basalpctfromtddLabel.labelFor = it }
switchTab(0, typeSelected[0], false)
}
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 e979e09104..da98848fcd 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 ac4c2da1e2..db151a6e2e 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 59e6622b4c..af8a39fe16 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 20b8070583..67a2cc512a 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 b227f667df..ec01cc7b3a 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 4cb88c4290..75c0b3cc19 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 ad3d7bde20..f0fcf32180 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/CalibrationDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/CalibrationDialog.kt
index 35f387144c..bd5daaf965 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/CalibrationDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/CalibrationDialog.kt
@@ -64,6 +64,7 @@ class CalibrationDialog : DialogFragmentWithDate() {
binding.bg.setParams(savedInstanceState?.getDouble("bg")
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
binding.units.text = if (units == GlucoseUnit.MMOL) rh.gs(R.string.mmol) else rh.gs(R.string.mgdl)
+ binding.bg.editText?.id?.let { binding.bgLabel.labelFor = it }
}
override fun onDestroyView() {
diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt
index aeb5fc52a5..f073e122f0 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt
@@ -137,32 +137,39 @@ class CarbsDialog : DialogFragmentWithDate() {
savedInstanceState?.getDouble("carbs")
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher
)
-
- binding.plus1.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
+ val plus1text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
+ binding.plus1.text = plus1text
+ binding.plus1.contentDescription = rh.gs(R.string.treatments_wizard_carbs_label) + " " + plus1text
binding.plus1.setOnClickListener {
binding.carbs.value = max(
0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)
)
validateInputs()
+ binding.carbs.announceValue()
}
- binding.plus2.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
+ val plus2text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
+ binding.plus2.text = plus2text
+ binding.plus2.contentDescription = rh.gs(R.string.treatments_wizard_carbs_label) + " " + plus2text
binding.plus2.setOnClickListener {
binding.carbs.value = max(
0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)
)
validateInputs()
+ binding.carbs.announceValue()
}
-
- binding.plus3.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
+ val plus3text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
+ binding.plus3.text = plus3text
+ binding.plus2.contentDescription = rh.gs(R.string.treatments_wizard_carbs_label) + " " + plus3text
binding.plus3.setOnClickListener {
binding.carbs.value = max(
0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)
)
validateInputs()
+ binding.carbs.announceValue()
}
setOnValueChangedListener { eventTime: Long ->
@@ -188,6 +195,9 @@ class CarbsDialog : DialogFragmentWithDate() {
binding.hypoTt.isChecked = false
binding.activityTt.isChecked = false
}
+ binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
+ binding.time.editText?.id?.let { binding.timeLabel.labelFor = it }
+ binding.carbs.editText?.id?.let { binding.carbsLabel.labelFor = it }
}
override fun onDestroyView() {
diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt
index 0006ce0cbe..03cb215a7f 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt
@@ -165,6 +165,8 @@ class CareDialog : DialogFragmentWithDate() {
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, binding.okcancel.ok)
if (options == EventType.NOTE || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT || options == EventType.EXERCISE)
binding.notesLayout.root.visibility = View.VISIBLE // independent to preferences
+ binding.bg.editText?.id?.let { binding.bgLabel.labelFor = it }
+ binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
}
override fun onDestroyView() {
diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt
index 4c86819465..7205a36939 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt
@@ -70,6 +70,8 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
binding.duration.setParams(savedInstanceState?.getDouble("duration")
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, binding.okcancel.ok)
+ binding.insulin.editText?.id?.let { binding.insulinLabel.labelFor = it }
+ binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
}
override fun onDestroyView() {
diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt
index b7423dc564..54b222ce2c 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt
@@ -96,7 +96,7 @@ class FillDialog : DialogFragmentWithDate() {
} else {
binding.fillPresetButton3.visibility = View.GONE
}
-
+ binding.fillInsulinamount.editText?.id?.let { binding.fillLabel.labelFor = it }
}
override fun onDestroyView() {
diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt
index d35446e818..21eb81ebce 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt
@@ -116,29 +116,40 @@ class InsulinDialog : DialogFragmentWithDate() {
binding.amount.setParams(savedInstanceState?.getDouble("amount")
?: 0.0, 0.0, maxInsulin, activePlugin.activePump.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
- binding.plus05.text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
+ val plus05Text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
+ binding.plus05.text = plus05Text
+ binding.plus05.contentDescription = rh.gs(R.string.overview_insulin_label) + " " + plus05Text
binding.plus05.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
validateInputs()
+ binding.amount.announceValue()
}
- binding.plus10.text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
+ val plus10Text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
+ binding.plus10.text = plus10Text
+ binding.plus10.contentDescription = rh.gs(R.string.overview_insulin_label) + " " + plus10Text
binding.plus10.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
validateInputs()
+ binding.amount.announceValue()
}
- binding.plus20.text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
+ val plus20Text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
+ binding.plus20.text = plus20Text
+ binding.plus20.contentDescription = rh.gs(R.string.overview_insulin_label) + " " + plus20Text
binding.plus20.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
validateInputs()
+ binding.amount.announceValue()
}
binding.timeLayout.visibility = View.GONE
binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean ->
binding.timeLayout.visibility = isChecked.toVisibility()
}
+ binding.amount.editText?.id?.let { binding.insulinLabel.labelFor = it }
+ binding.time.editText?.id?.let { binding.timeLabel.labelFor = it }
}
override fun onDestroyView() {
diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt
index c869c22e6d..c64539af14 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt
@@ -148,6 +148,9 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
}
}
binding.ttLayout.visibility = View.GONE
+ binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
+ binding.percentage.editText?.id?.let { binding.percentageLabel.labelFor = it }
+ binding.timeshift.editText?.id?.let { binding.timeshiftLabel.labelFor = it }
}
override fun onDestroyView() {
diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt
index 65ee820eeb..d458055b9d 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt
@@ -86,6 +86,9 @@ class TempBasalDialog : DialogFragmentWithDate() {
binding.percentLayout.visibility = View.GONE
binding.absoluteLayout.visibility = View.VISIBLE
}
+ binding.basalPercentInput.editText?.id?.let { binding.basalPercentLabel.labelFor = it }
+ binding.basalAbsoluteInput.editText?.id?.let { binding.basalAbsoluteLabel.labelFor = it }
+ binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
}
override fun onDestroyView() {
diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt
index 54801c723d..c1ed8faf5b 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt
@@ -120,6 +120,8 @@ class TempTargetDialog : DialogFragmentWithDate() {
longClick(it)
return@setOnLongClickListener true
}
+ binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
+ binding.temptarget.editText?.id?.let { binding.temptargetLabel.labelFor = it }
}
}
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 ac88f7e074..0e8a509517 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt
@@ -106,6 +106,8 @@ class TreatmentDialog : DialogFragmentWithDate() {
binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
binding.recordOnlyLayout.visibility = View.GONE
+ binding.insulin.editText?.id?.let { binding.insulinLabel.labelFor = it }
+ binding.carbs.editText?.id?.let { binding.carbsLabel.labelFor = it }
}
override fun onDestroyView() {
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 3fce025b61..b7f943a313 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() {
@@ -261,21 +274,29 @@ class WizardDialog : DaggerDialogFragment() {
private fun processCobCheckBox() {
if (binding.cobCheckbox.isChecked) {
binding.iobCheckbox.isEnabled = false
+ binding.iobCheckboxIcon.isEnabled = false
binding.iobCheckbox.isChecked = true
} else {
binding.iobCheckbox.isEnabled = true
+ binding.iobCheckboxIcon.isEnabled = true
}
}
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.isChecked = binding.bgCheckbox.isChecked
+ binding.trendCheckboxIcon.isChecked = binding.bgTrendCheckbox.isChecked
+ binding.iobCheckboxIcon.isChecked = binding.iobCheckbox.isChecked
+ binding.cobCheckboxIcon.isChecked = binding.cobCheckbox.isChecked
+
+ 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 +463,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/dialogs/WizardInfoDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardInfoDialog.kt
index 6a6aaf32fa..37a653f5e5 100644
--- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardInfoDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardInfoDialog.kt
@@ -69,13 +69,15 @@ class WizardInfoDialog : DaggerDialogFragment() {
binding.close.setOnClickListener { dismiss() }
val units = profileFunction.getUnits()
val bgString = Profile.toUnitsString(data.glucoseValue, data.glucoseValue * Constants.MGDL_TO_MMOLL, units)
+ val isf = Profile.toUnits(data.isf, data.isf * Constants.MGDL_TO_MMOLL, units)
+ val trend = Profile.toUnitsString(data.glucoseTrend * 3, data.glucoseTrend * 3 * Constants.MGDL_TO_MMOLL, units)
// BG
- binding.bg.text = rh.gs(R.string.format_bg_isf, bgString, data.isf)
+ binding.bg.text = rh.gs(R.string.format_bg_isf, bgString, isf)
binding.bgInsulin.text = rh.gs(R.string.formatinsulinunits, data.glucoseInsulin)
binding.bgCheckbox.isChecked = data.wasGlucoseUsed
binding.ttCheckbox.isChecked = data.wasTempTargetUsed
// Trend
- binding.bgTrend.text = DecimalFormatter.to1Decimal(data.glucoseTrend)
+ binding.bgTrend.text = trend
binding.bgTrendInsulin.text = rh.gs(R.string.formatinsulinunits, data.trendInsulin)
binding.bgTrendCheckbox.isChecked = data.wasTrendUsed
// COB
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/bgQualityCheck/BgQualityCheckPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/bgQualityCheck/BgQualityCheckPlugin.kt
index 73e42b78d7..800994fe03 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/bgQualityCheck/BgQualityCheckPlugin.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/bgQualityCheck/BgQualityCheckPlugin.kt
@@ -102,4 +102,11 @@ class BgQualityCheckPlugin @Inject constructor(
State.RECALCULATED -> R.drawable.ic_baseline_warning_24_yellow
State.DOUBLED -> R.drawable.ic_baseline_warning_24_red
}
+
+ fun stateDescription(): String =
+ when (state) {
+ State.RECALCULATED -> rh.gs(R.string.a11y_bg_quality_recalculated)
+ State.DOUBLED -> rh.gs(R.string.a11y_bg_quality_doubles)
+ else -> ""
+ }
}
\ No newline at end of file
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 60434c77ae..dc5805cfd1 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/OverviewData.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewData.kt
index 8437c500fa..8eaf29a08c 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewData.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewData.kt
@@ -128,14 +128,29 @@ class OverviewData @Inject constructor(
var lastBg: GlucoseValue? = null
- val lastBgColor: Int
+ val isLow: Boolean
get() = lastBg?.let { lastBg ->
- when {
- lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine() -> rh.gc(R.color.low)
- lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine() -> rh.gc(R.color.high)
- else -> rh.gc(R.color.inrange)
- }
- } ?: rh.gc(R.color.inrange)
+ lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine()
+ } ?: false
+
+ val isHigh: Boolean
+ get() = lastBg?.let { lastBg ->
+ lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine()
+ } ?: false
+
+ val lastBgColor: Int
+ get() = when {
+ isLow -> rh.gc(R.color.low)
+ isHigh -> rh.gc(R.color.high)
+ else -> rh.gc(R.color.inrange)
+ }
+
+ val lastBgDescription: String
+ get() = when {
+ isLow -> rh.gs(R.string.a11y_low)
+ isHigh -> rh.gs(R.string.a11y_high)
+ else -> rh.gs(R.string.a11y_inrange)
+ }
val isActualBg: Boolean
get() =
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 5ec2a64b52..962f29d2e1 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
@@ -8,6 +8,7 @@ import android.content.Intent
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.AnimationDrawable
+import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
@@ -416,7 +417,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
OKDialog.showConfirmation(activity, rh.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned()
?: "".toSpanned(), {
uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview)
- (context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID)
+ (context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?)?.cancel(Constants.notificationID)
rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
Thread { loop.acceptChangeRequest() }.run()
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
@@ -597,24 +598,36 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// aps mode
val closedLoopEnabled = constraintChecker.isClosedLoopAllowed()
+
+ fun apsModeSetA11yLabel(stringRes: Int) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ binding.infoLayout.apsMode.stateDescription = rh.gs(stringRes)
+ } else {
+ binding.infoLayout.apsMode.contentDescription = rh.gs(R.string.apsmode_title) + " " + rh.gs(stringRes)
+ }
+ }
+
if (config.APS && pump.pumpDescription.isTempBasalCapable) {
binding.infoLayout.apsMode.visibility = View.VISIBLE
binding.infoLayout.timeLayout.visibility = View.GONE
when {
(loop as PluginBase).isEnabled() && loop.isSuperBolus -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_superbolus)
+ apsModeSetA11yLabel(R.string.superbolus)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
loop.isDisconnected -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disconnected)
+ apsModeSetA11yLabel(R.string.disconnected)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
(loop as PluginBase).isEnabled() && loop.isSuspended -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_paused)
+ apsModeSetA11yLabel(R.string.suspendloop_label)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
@@ -624,8 +637,10 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) {
// For Omnipod, indicate the pump as disconnected when it's suspended.
// The only way to 'reconnect' it, is through the Omnipod tab
+ apsModeSetA11yLabel(R.string.disconnected)
R.drawable.ic_loop_disconnected
} else {
+ apsModeSetA11yLabel(R.string.pump_paused)
R.drawable.ic_loop_paused
}
)
@@ -634,21 +649,25 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() && loop.isLGS -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_lgs)
+ apsModeSetA11yLabel(R.string.uel_lgs_loop_mode)
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_closed)
+ apsModeSetA11yLabel(R.string.closedloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && !closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_open)
+ apsModeSetA11yLabel(R.string.openloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
else -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disabled)
+ apsModeSetA11yLabel(R.string.disabledloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
}
@@ -732,6 +751,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
binding.infoLayout.bg.setTextColor(overviewData.lastBgColor)
binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor)
+ binding.infoLayout.arrow.contentDescription = overviewData.lastBgDescription + " " + rh.gs(R.string.and) + " " + trendCalculator.getTrendDescription(overviewData.lastBg)
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
if (glucoseStatus != null) {
@@ -751,13 +771,20 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
binding.infoLayout.bg.paintFlags =
if (!overviewData.isActualBg) binding.infoLayout.bg.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else binding.infoLayout.bg.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
+
+ val outDate = (if (!overviewData.isActualBg) rh.gs(R.string.a11y_bg_outdated) else "")
+ binding.infoLayout.bg.contentDescription =
+ rh.gs(R.string.a11y_blood_glucose) + " " + binding.infoLayout.bg.text.toString() + " " + overviewData.lastBgDescription + " " + outDate
+
binding.infoLayout.timeAgo.text = dateUtil.minAgo(rh, overviewData.lastBg?.timestamp)
+ binding.infoLayout.timeAgo.contentDescription = dateUtil.minAgoLong(rh, overviewData.lastBg?.timestamp)
binding.infoLayout.timeAgoShort.text = "(" + dateUtil.minAgoShort(overviewData.lastBg?.timestamp) + ")"
val qualityIcon = bgQualityCheckPlugin.icon()
if (qualityIcon != 0) {
binding.infoLayout.bgQuality.visibility = View.VISIBLE
binding.infoLayout.bgQuality.setImageResource(qualityIcon)
+ binding.infoLayout.bgQuality.contentDescription = rh.gs(R.string.a11y_bg_quality) + " " + bgQualityCheckPlugin.stateDescription()
binding.infoLayout.bgQuality.setOnClickListener {
context?.let { context -> OKDialog.show(context, rh.gs(R.string.data_status), bgQualityCheckPlugin.message) }
}
@@ -823,7 +850,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/general/overview/activities/QuickWizardListActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt
index 8a76c606bf..9c770263fb 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt
@@ -1,12 +1,18 @@
package info.nightscout.androidaps.plugins.general.overview.activities
+import android.annotation.SuppressLint
import android.os.Bundle
+import android.util.Log
import android.view.LayoutInflater
+import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.Button
+import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.FragmentManager
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.ItemTouchHelper.*
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import info.nightscout.androidaps.R
@@ -17,10 +23,12 @@ import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWiza
import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
+import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.wizard.QuickWizard
-import io.reactivex.rxjava3.disposables.CompositeDisposable
+import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
+import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject
class QuickWizardListActivity : NoSplashAppCompatActivity() {
@@ -30,20 +38,95 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var quickWizard: QuickWizard
@Inject lateinit var dateUtil: DateUtil
+ @Inject lateinit var sp: SP
private var disposable: CompositeDisposable = CompositeDisposable()
private lateinit var binding: OverviewQuickwizardlistActivityBinding
+ private val itemTouchHelper by lazy {
+ val simpleItemTouchCallback = object : ItemTouchHelper.SimpleCallback(UP or DOWN or START or END, 0) {
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean {
+ val adapter = recyclerView.adapter as RecyclerViewAdapter
+ val from = viewHolder.layoutPosition
+ val to = target.layoutPosition
+ adapter.moveItem(from, to)
+ adapter.notifyItemMoved(from, to)
+
+ return true
+ }
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ }
+
+ override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
+ super.onSelectedChanged(viewHolder, actionState)
+
+ if (actionState == ACTION_STATE_DRAG) {
+ viewHolder?.itemView?.alpha = 0.5f
+ }
+ }
+
+ override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
+ super.clearView(recyclerView, viewHolder)
+
+ viewHolder.itemView.alpha = 1.0f
+
+ val adapter = recyclerView.adapter as RecyclerViewAdapter
+ adapter.onDrop()
+ }
+ }
+
+ ItemTouchHelper(simpleItemTouchCallback)
+ }
+
+ fun startDragging(viewHolder: RecyclerView.ViewHolder) {
+ itemTouchHelper.startDrag(viewHolder)
+ }
+
private inner class RecyclerViewAdapter(var fragmentManager: FragmentManager) : RecyclerView.Adapter() {
+ @SuppressLint("ClickableViewAccessibility")
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickWizardEntryViewHolder {
- return QuickWizardEntryViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.overview_quickwizardlist_item, parent, false), fragmentManager)
+ val itemView = LayoutInflater.from(parent.context).inflate(R.layout.overview_quickwizardlist_item, parent, false)
+ val viewHolder = QuickWizardEntryViewHolder(itemView, fragmentManager)
+
+ viewHolder.handleView.setOnTouchListener { _, event ->
+ if (event.actionMasked == MotionEvent.ACTION_DOWN) {
+ startDragging(viewHolder)
+ }
+ return@setOnTouchListener true
+ }
+
+ return viewHolder
}
override fun onBindViewHolder(holder: QuickWizardEntryViewHolder, position: Int) {
holder.from.text = dateUtil.timeString(quickWizard[position].validFromDate())
holder.to.text = dateUtil.timeString(quickWizard[position].validToDate())
+ val wearControl = sp.getBoolean(R.string.key_wear_control, false)
+
+ if (wearControl) {
+ holder.handleView.visibility = View.VISIBLE
+ } else {
+ holder.handleView.visibility = View.GONE
+ }
+ if (quickWizard[position].device() == QuickWizardEntry.DEVICE_ALL) {
+ holder.device.visibility = View.GONE
+ } else {
+ holder.device.visibility = View.VISIBLE
+ holder.device.setImageResource(
+ when (quickWizard[position].device()) {
+ QuickWizardEntry.DEVICE_WATCH -> R.drawable.ic_watch
+ else -> R.drawable.ic_smartphone
+ }
+ )
+ }
holder.buttonText.text = quickWizard[position].buttonText()
holder.carbs.text = rh.gs(R.string.format_carbs, quickWizard[position].carbs())
}
@@ -55,6 +138,8 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
val buttonText: TextView = itemView.findViewById(R.id.overview_quickwizard_item_buttonText)
val carbs: TextView = itemView.findViewById(R.id.overview_quickwizard_item_carbs)
val from: TextView = itemView.findViewById(R.id.overview_quickwizard_item_from)
+ val handleView: ImageView = itemView.findViewById(R.id.handleView)
+ val device: ImageView = itemView.findViewById(R.id.overview_quickwizard_item_device)
val to: TextView = itemView.findViewById(R.id.overview_quickwizard_item_to)
private val editButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_edit_button)
private val removeButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_remove_button)
@@ -74,6 +159,16 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
}
}
}
+
+ fun moveItem(from: Int, to: Int) {
+ Log.i("QuickWizard", "moveItem")
+ quickWizard.move(from, to)
+ }
+
+ fun onDrop() {
+ Log.i("QuickWizard", "onDrop")
+ rxBus.send(EventQuickWizardChange())
+ }
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -84,6 +179,7 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(this)
binding.recyclerview.adapter = RecyclerViewAdapter(supportFragmentManager)
+ itemTouchHelper.attachToRecyclerView(binding.recyclerview)
binding.addButton.setOnClickListener {
val manager = supportFragmentManager
@@ -98,13 +194,13 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
.toObservable(EventQuickWizardChange::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({
- val adapter = RecyclerViewAdapter(supportFragmentManager)
- binding.recyclerview.swapAdapter(adapter, false)
- }, fabricPrivacy::logException)
+ val adapter = RecyclerViewAdapter(supportFragmentManager)
+ binding.recyclerview.swapAdapter(adapter, false)
+ }, fabricPrivacy::logException)
}
override fun onPause() {
disposable.clear()
super.onPause()
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt
index bfe47b2bdf..e7abb4690d 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt
@@ -9,6 +9,7 @@ import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import dagger.android.support.DaggerDialogFragment
+import info.nightscout.androidaps.R
import info.nightscout.androidaps.databinding.OverviewEditquickwizardDialogBinding
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBus
@@ -21,6 +22,7 @@ import info.nightscout.androidaps.utils.extensions.setEnableForChildren
import info.nightscout.androidaps.utils.extensions.setSelection
import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
+import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONException
import javax.inject.Inject
@@ -30,9 +32,9 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var quickWizard: QuickWizard
@Inject lateinit var dateUtil: DateUtil
+ @Inject lateinit var sp: SP
var position = -1
-
var fromSeconds: Int = 0
var toSeconds: Int = 0
@@ -42,8 +44,10 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
// onDestroyView.
private val binding get() = _binding!!
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?): View {
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = true
@@ -57,6 +61,14 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
position = bundle.getInt("position", -1)
}
val entry = if (position == -1) quickWizard.newEmptyItem() else quickWizard[position]
+ if (sp.getBoolean(R.string.key_wear_control, false)) {
+ binding.deviceLabel.visibility = View.VISIBLE
+ binding.device.visibility = View.VISIBLE
+ } else {
+ binding.deviceLabel.visibility = View.GONE
+ binding.device.visibility = View.GONE
+ }
+
binding.okcancel.ok.setOnClickListener {
try {
entry.storage.put("buttonText", binding.buttonEdit.text.toString())
@@ -66,10 +78,14 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
entry.storage.put("useBG", binding.useBg.selectedItemPosition)
entry.storage.put("useCOB", binding.useCob.selectedItemPosition)
entry.storage.put("useBolusIOB", binding.useBolusIob.selectedItemPosition)
+ entry.storage.put("device", binding.device.selectedItemPosition)
entry.storage.put("useBasalIOB", binding.useBasalIob.selectedItemPosition)
entry.storage.put("useTrend", binding.useTrend.selectedItemPosition)
entry.storage.put("useSuperBolus", binding.useSuperBolus.selectedItemPosition)
entry.storage.put("useTempTarget", binding.useTempTarget.selectedItemPosition)
+ entry.storage.put("usePercentage", binding.usePercentage.selectedItemPosition)
+ val percentage = SafeParse.stringToInt(binding.percentage.text.toString())
+ entry.storage.put("percentage", percentage)
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}
@@ -88,7 +104,8 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.from.setOnClickListener {
context?.let {
- TimePickerDialog(it, fromTimeSetListener,
+ TimePickerDialog(
+ it, fromTimeSetListener,
T.secs(fromSeconds.toLong()).hours().toInt(),
T.secs((fromSeconds % 3600).toLong()).mins().toInt(),
DateFormat.is24HourFormat(context)
@@ -105,13 +122,29 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.to.setOnClickListener {
context?.let {
- TimePickerDialog(it, toTimeSetListener,
+ TimePickerDialog(
+ it, toTimeSetListener,
T.secs(toSeconds.toLong()).hours().toInt(),
T.secs((toSeconds % 3600).toLong()).mins().toInt(),
DateFormat.is24HourFormat(context)
).show()
}
}
+
+ fun usePercentage(custom: Boolean) {
+ if (custom) {
+ binding.percentageLabel.visibility = View.VISIBLE
+ binding.percentage.visibility = View.VISIBLE
+ } else {
+ binding.percentageLabel.visibility = View.GONE
+ binding.percentage.visibility = View.GONE
+ }
+ }
+
+ binding.usePercentage.setOnCheckedChangeListener { _, checkedId ->
+ usePercentage(checkedId == R.id.use_percentage_custom)
+ }
+
toSeconds = entry.validTo()
binding.to.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(toSeconds))
@@ -122,10 +155,13 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.useCob.setSelection(entry.useCOB())
binding.useBolusIob.setSelection(entry.useBolusIOB())
binding.useBasalIob.setSelection(entry.useBasalIOB())
+ binding.device.setSelection(entry.device())
binding.useTrend.setSelection(entry.useTrend())
binding.useSuperBolus.setSelection(entry.useSuperBolus())
binding.useTempTarget.setSelection(entry.useTempTarget())
-
+ binding.usePercentage.setSelection(entry.usePercentage())
+ usePercentage(entry.usePercentage() == QuickWizardEntry.CUSTOM)
+ binding.percentage.setText(entry.percentage().toString())
binding.useCobYes.setOnClickListener(this)
binding.useCobNo.setOnClickListener(this)
processCob()
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt
index 3fc78dbf3d..481e904868 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt
@@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.general.wear
import android.app.NotificationManager
import android.content.Context
+import android.util.Log
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
@@ -39,11 +40,11 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.androidaps.utils.wizard.BolusWizard
+import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.shared.SafeParse
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DateFormat
-import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
@@ -71,6 +72,7 @@ class ActionStringHandler @Inject constructor(
private val activePlugin: ActivePlugin,
private val iobCobCalculator: IobCobCalculator,
private val localInsightPlugin: LocalInsightPlugin,
+ private val quickWizard: QuickWizard,
private val danaRPlugin: DanaRPlugin,
private val danaRKoreanPlugin: DanaRKoreanPlugin,
private val danaRv2Plugin: DanaRv2Plugin,
@@ -79,7 +81,8 @@ class ActionStringHandler @Inject constructor(
private val dateUtil: DateUtil,
private val config: Config,
private val repository: AppRepository,
- private val uel: UserEntryLogger
+ private val uel: UserEntryLogger,
+ private val defaultValueHelper: DefaultValueHelper
) {
private val timeout = 65 * 1000
@@ -107,9 +110,11 @@ class ActionStringHandler @Inject constructor(
@Synchronized
private fun handleInitiate(actionString: String) {
+ //TODO: i18n
+ Log.i("ActionStringHandler", "handleInitiate actionString=" + actionString)
if (!sp.getBoolean(R.string.key_wear_control, false)) return
lastBolusWizard = null
- var rTitle = "CONFIRM" //TODO: i18n
+ var rTitle = rh.gs(R.string.confirm).uppercase()
var rMessage = ""
var rAction = ""
// do the parsing and check constraints
@@ -136,6 +141,11 @@ class ActionStringHandler @Inject constructor(
val carbs = SafeParse.stringToInt(act[2])
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
+ val pump = activePlugin.activePump
+ if (insulinAfterConstraints > 0 && (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected)) {
+ sendError(rh.gs(R.string.wizard_pump_not_available))
+ return
+ }
rMessage += rh.gs(R.string.bolus) + ": " + insulinAfterConstraints + "U\n"
rMessage += rh.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"
if (insulinAfterConstraints - insulin != 0.0 || carbsAfterConstraints - carbs != 0) {
@@ -143,32 +153,72 @@ class ActionStringHandler @Inject constructor(
}
rAction += "bolus $insulinAfterConstraints $carbsAfterConstraints"
} else if ("temptarget" == act[0]) { ///////////////////////////////////////////////////////// TEMPTARGET
- val isMGDL = java.lang.Boolean.parseBoolean(act[1])
- if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) {
- sendError("Different units used on watch and phone!")
- return
- }
- val duration = SafeParse.stringToInt(act[2])
- if (duration == 0) {
- rMessage += "Zero-Temp-Target - cancelling running Temp-Targets?"
+ aapsLogger.info(LTag.WEAR, "temptarget received: $act")
+ if ("cancel" == act[1]) {
+ rMessage += rh.gs(R.string.wear_action_tempt_cancel_message)
rAction = "temptarget true 0 0 0"
+ } else if ("preset" == act[1]) {
+ val presetIsMGDL = profileFunction.getUnits() == GlucoseUnit.MGDL
+ val preset = act[2]
+ when (preset) {
+ "activity" -> {
+ val activityTTDuration = defaultValueHelper.determineActivityTTDuration()
+ val activityTT = defaultValueHelper.determineActivityTT()
+ val reason = rh.gs(R.string.activity)
+ rMessage += rh.gs(R.string.wear_action_tempt_preset_message, reason, activityTT, activityTTDuration)
+ rAction = "temptarget $presetIsMGDL $activityTTDuration $activityTT $activityTT"
+ }
+
+ "hypo" -> {
+ val hypoTTDuration = defaultValueHelper.determineHypoTTDuration()
+ val hypoTT = defaultValueHelper.determineHypoTT()
+ val reason = rh.gs(R.string.hypo)
+ rMessage += rh.gs(R.string.wear_action_tempt_preset_message, reason, hypoTT, hypoTTDuration)
+ rAction = "temptarget $presetIsMGDL $hypoTTDuration $hypoTT $hypoTT"
+ }
+
+ "eating" -> {
+ val eatingSoonTTDuration = defaultValueHelper.determineEatingSoonTTDuration()
+ val eatingSoonTT = defaultValueHelper.determineEatingSoonTT()
+ val reason = rh.gs(R.string.eatingsoon)
+ rMessage += rh.gs(R.string.wear_action_tempt_preset_message, reason, eatingSoonTT, eatingSoonTTDuration)
+ rAction = "temptarget $presetIsMGDL $eatingSoonTTDuration $eatingSoonTT $eatingSoonTT"
+ }
+
+ else -> {
+ sendError(rh.gs(R.string.wear_action_tempt_preset_error, preset))
+ return
+ }
+ }
} else {
- var low = SafeParse.stringToDouble(act[3])
- var high = SafeParse.stringToDouble(act[4])
- if (!isMGDL) {
- low *= Constants.MMOLL_TO_MGDL
- high *= Constants.MMOLL_TO_MGDL
- }
- if (low < HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0] || low > HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]) {
- sendError("Min-BG out of range!")
+ val isMGDL = java.lang.Boolean.parseBoolean(act[1])
+ if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) {
+ sendError(rh.gs(R.string.wear_action_tempt_unit_error))
return
}
- if (high < HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) {
- sendError("Max-BG out of range!")
- return
+ val duration = SafeParse.stringToInt(act[2])
+ if (duration == 0) {
+ rMessage += rh.gs(R.string.wear_action_tempt_zero_message)
+ rAction = "temptarget true 0 0 0"
+ } else {
+ var low = SafeParse.stringToDouble(act[3])
+ var high = SafeParse.stringToDouble(act[4])
+ if (!isMGDL) {
+ low *= Constants.MMOLL_TO_MGDL
+ high *= Constants.MMOLL_TO_MGDL
+ }
+ if (low < HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0] || low > HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]) {
+ sendError(rh.gs(R.string.wear_action_tempt_min_bg_error))
+ return
+ }
+ if (high < HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) {
+ sendError(rh.gs(R.string.wear_action_tempt_max_bg_error))
+ return
+ }
+ rMessage += if (act[3] === act[4]) rh.gs(R.string.wear_action_tempt_manual_message, act[3], act[2])
+ else rh.gs(R.string.wear_action_tempt_manual_range_message, act[3], act[4], act[2])
+ rAction = actionString
}
- rMessage += "Temptarget:\nMin: " + act[3] + "\nMax: " + act[4] + "\nDuration: " + act[2]
- rAction = actionString
}
} else if ("status" == act[0]) { ////////////////////////////////////////////// STATUS
rTitle = "STATUS"
@@ -186,10 +236,15 @@ class ActionStringHandler @Inject constructor(
sendError("Update APP on Watch!")
return
} else if ("wizard2" == act[0]) { ////////////////////////////////////////////// WIZARD
+ val pump = activePlugin.activePump
+ if (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected) {
+ sendError(rh.gs(R.string.wizard_pump_not_available))
+ return
+ }
val carbsBeforeConstraints = SafeParse.stringToInt(act[1])
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbsBeforeConstraints)).value()
if (carbsAfterConstraints - carbsBeforeConstraints != 0) {
- sendError("Carb constraint violation!")
+ sendError(rh.gs(R.string.wizard_carbs_constraint))
return
}
val useBG = sp.getBoolean(R.string.key_wearwizard_bg, true)
@@ -202,52 +257,94 @@ class ActionStringHandler @Inject constructor(
val profile = profileFunction.getProfile()
val profileName = profileFunction.getProfileName()
if (profile == null) {
- sendError("No profile found!")
+ sendError(rh.gs(R.string.wizard_no_active_profile))
return
}
val bgReading = iobCobCalculator.ads.actualBg()
if (bgReading == null) {
- sendError("No recent BG to base calculation on!")
+ sendError(rh.gs(R.string.wizard_no_actual_bg))
return
}
val cobInfo = iobCobCalculator.getCobInfo(false, "Wizard wear")
if (cobInfo.displayCob == null) {
- sendError("Unknown COB! BG reading missing or recent app restart?")
+ sendError(rh.gs(R.string.wizard_no_cob))
return
}
- val format = DecimalFormat("0.00")
- val formatInt = DecimalFormat("0")
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
val tempTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
- val bolusWizard = BolusWizard(injector).doCalc(profile, profileName, tempTarget,
- carbsAfterConstraints, if (cobInfo.displayCob != null) cobInfo.displayCob!! else 0.0, bgReading.valueToUnits(profileFunction.getUnits()),
- 0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false)
- if (abs(bolusWizard.insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) {
- sendError("Insulin constraint violation!" +
- "\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!")
+ val bolusWizard = BolusWizard(injector).doCalc(
+ profile, profileName, tempTarget,
+ carbsAfterConstraints, cobInfo.displayCob!!, bgReading.valueToUnits(profileFunction.getUnits()),
+ 0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false
+ )
+ val insulinAfterConstraints = bolusWizard.insulinAfterConstraints
+ val minStep = pump.pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)
+ if (abs(insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= minStep) {
+ sendError(rh.gs(R.string.wizard_constraint_bolus_size, bolusWizard.calculatedTotalInsulin))
return
}
if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) {
rAction = "info"
- rTitle = "INFO"
+ rTitle = rh.gs(R.string.info)
} else {
rAction = actionString
}
- rMessage += "Carbs: " + bolusWizard.carbs + "g"
- rMessage += "\nBolus: " + format.format(bolusWizard.calculatedTotalInsulin) + "U"
+ rMessage += rh.gs(R.string.wizard_result, bolusWizard.calculatedTotalInsulin, bolusWizard.carbs)
rMessage += "\n_____________"
- rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): "
- rMessage += "\nFrom Carbs: " + format.format(bolusWizard.insulinFromCarbs) + "U"
- if (useCOB) rMessage += "\nFrom" + formatInt.format(cobInfo.displayCob) + "g COB : " + format.format(bolusWizard.insulinFromCOB) + "U"
- if (useBG) rMessage += "\nFrom BG: " + format.format(bolusWizard.insulinFromBG) + "U"
- if (useBolusIOB) rMessage += "\nBolus IOB: " + format.format(bolusWizard.insulinFromBolusIOB) + "U"
- if (useBasalIOB) rMessage += "\nBasal IOB: " + format.format(bolusWizard.insulinFromBasalIOB) + "U"
- if (useTrend) rMessage += "\nFrom 15' trend: " + format.format(bolusWizard.insulinFromTrend) + "U"
- if (percentage != 100) {
- rMessage += "\nPercentage: " + format.format(bolusWizard.totalBeforePercentageAdjustment) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.calculatedTotalInsulin) + "U"
- }
+ rMessage += "\n" + bolusWizard.explainShort()
lastBolusWizard = bolusWizard
+ } else if ("quick_wizard" == act[0]) {
+ val guid = act[1]
+ val actualBg = iobCobCalculator.ads.actualBg()
+ val profile = profileFunction.getProfile()
+ val profileName = profileFunction.getProfileName()
+ val quickWizardEntry = quickWizard.get(guid)
+ Log.i("QuickWizard", "handleInitiate: quick_wizard " + quickWizardEntry?.buttonText() + " c " + quickWizardEntry?.carbs())
+ if (quickWizardEntry == null) {
+ sendError(rh.gs(R.string.quick_wizard_not_available))
+ return
+ }
+ if (actualBg == null) {
+ sendError(rh.gs(R.string.wizard_no_actual_bg))
+ return
+ }
+ if (profile == null) {
+ sendError(rh.gs(R.string.wizard_no_active_profile))
+ return
+ }
+ val cobInfo = iobCobCalculator.getCobInfo(false, "QuickWizard wear")
+ if (cobInfo.displayCob == null) {
+ sendError(rh.gs(R.string.wizard_no_cob))
+ return
+ }
+ val pump = activePlugin.activePump
+ if (!pump.isInitialized() || pump.isSuspended() || loop.isDisconnected) {
+ sendError(rh.gs(R.string.wizard_pump_not_available))
+ return
+ }
+
+ val wizard = quickWizardEntry.doCalc(profile, profileName, actualBg, true)
+
+ val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(quickWizardEntry.carbs())).value()
+ if (carbsAfterConstraints != quickWizardEntry.carbs()) {
+ sendError(rh.gs(R.string.wizard_carbs_constraint))
+ return
+ }
+ val insulinAfterConstraints = wizard.insulinAfterConstraints
+ val minStep = pump.pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)
+ if (abs(insulinAfterConstraints - wizard.calculatedTotalInsulin) >= minStep) {
+ sendError(rh.gs(R.string.wizard_constraint_bolus_size, wizard.calculatedTotalInsulin))
+ return
+ }
+
+ rMessage = rh.gs(R.string.quick_wizard_message, quickWizardEntry.buttonText(), wizard.calculatedTotalInsulin, quickWizardEntry.carbs())
+ rAction = "bolus $insulinAfterConstraints $carbsAfterConstraints"
+ Log.i("QuickWizard", "handleInitiate: quick_wizard action=$rAction")
+
+ rMessage += "\n_____________"
+ rMessage += "\n" + wizard.explainShort()
+
} else if ("opencpp" == act[0]) {
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values
@@ -331,7 +428,10 @@ class ActionStringHandler @Inject constructor(
rAction = "cancelChangeRequest"
wearPlugin.requestNotificationCancel(rAction)
return
- } else return
+ } else {
+ sendError(rh.gs(R.string.wear_unknown_action_string) + act[0])
+ return
+ }
// send result
wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction)
lastSentTimestamp = System.currentTimeMillis()
@@ -560,39 +660,45 @@ class ActionStringHandler @Inject constructor(
}
//send profile to pump
uel.log(Action.PROFILE_SWITCH, Sources.Wear,
- ValueWithUnit.Percent(percentage),
- ValueWithUnit.Hour(timeshift).takeIf { timeshift != 0 })
+ ValueWithUnit.Percent(percentage),
+ ValueWithUnit.Hour(timeshift).takeIf { timeshift != 0 })
profileFunction.createProfileSwitch(0, percentage, timeshift)
}
private fun generateTempTarget(duration: Int, low: Double, high: Double) {
if (duration != 0) {
- disposable += repository.runTransactionForResult(InsertAndCancelCurrentTemporaryTargetTransaction(
- timestamp = System.currentTimeMillis(),
- duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
- reason = TemporaryTarget.Reason.WEAR,
- lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
- highTarget = Profile.toMgdl(high, profileFunction.getUnits())
- )).subscribe({ result ->
- result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
- result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
- }, {
- aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
- })
- uel.log(Action.TT, Sources.Wear,
+ disposable += repository.runTransactionForResult(
+ InsertAndCancelCurrentTemporaryTargetTransaction(
+ timestamp = System.currentTimeMillis(),
+ duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
+ reason = TemporaryTarget.Reason.WEAR,
+ lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
+ highTarget = Profile.toMgdl(high, profileFunction.getUnits())
+ )
+ ).subscribe({ result ->
+ result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
+ result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
+ }, {
+ aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
+ })
+ uel.log(
+ Action.TT, Sources.Wear,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR),
ValueWithUnit.fromGlucoseUnit(low, profileFunction.getUnits().asText),
ValueWithUnit.fromGlucoseUnit(high, profileFunction.getUnits().asText).takeIf { low != high },
- ValueWithUnit.Minute(duration))
+ ValueWithUnit.Minute(duration)
+ )
} else {
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(System.currentTimeMillis()))
.subscribe({ result ->
- result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
- }, {
- aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
- })
- uel.log(Action.CANCEL_TT, Sources.Wear,
- ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR))
+ result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
+ }, {
+ aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
+ })
+ uel.log(
+ Action.CANCEL_TT, Sources.Wear,
+ ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR)
+ )
}
}
@@ -601,13 +707,15 @@ class ActionStringHandler @Inject constructor(
detailedBolusInfo.insulin = amount
detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING
uel.log(Action.PRIME_BOLUS, Sources.Wear,
- ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 })
+ ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 })
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
- sendError(rh.gs(R.string.treatmentdeliveryerror) +
- "\n" +
- result.comment)
+ sendError(
+ rh.gs(R.string.treatmentdeliveryerror) +
+ "\n" +
+ result.comment
+ )
}
}
})
@@ -615,9 +723,9 @@ class ActionStringHandler @Inject constructor(
private fun doECarbs(carbs: Int, time: Long, duration: Int) {
uel.log(if (duration == 0) Action.CARBS else Action.EXTENDED_CARBS, Sources.Wear,
- ValueWithUnit.Timestamp(time),
- ValueWithUnit.Gram(carbs),
- ValueWithUnit.Hour(duration).takeIf { duration != 0 })
+ ValueWithUnit.Timestamp(time),
+ ValueWithUnit.Gram(carbs),
+ ValueWithUnit.Hour(duration).takeIf { duration != 0 })
doBolus(0.0, carbs, time, duration)
}
@@ -636,15 +744,17 @@ class ActionStringHandler @Inject constructor(
else -> Action.TREATMENT
}
uel.log(action, Sources.Wear,
- ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 },
- ValueWithUnit.Gram(carbs).takeIf { carbs != 0 },
- ValueWithUnit.Hour(carbsDuration).takeIf { carbsDuration != 0 })
+ ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 },
+ ValueWithUnit.Gram(carbs).takeIf { carbs != 0 },
+ ValueWithUnit.Hour(carbsDuration).takeIf { carbsDuration != 0 })
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
- sendError(rh.gs(R.string.treatmentdeliveryerror) +
- "\n" +
- result.comment)
+ sendError(
+ rh.gs(R.string.treatmentdeliveryerror) +
+ "\n" +
+ result.comment
+ )
}
}
})
@@ -665,4 +775,4 @@ class ActionStringHandler @Inject constructor(
lastConfirmActionString = null
lastBolusWizard = null
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java
index 1ce5c509bb..95cf6128a2 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java
@@ -46,6 +46,7 @@ import info.nightscout.androidaps.interfaces.Loop;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.Profile;
import info.nightscout.androidaps.interfaces.ProfileFunction;
+import info.nightscout.androidaps.utils.wizard.QuickWizardEntry;
import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
@@ -62,6 +63,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.DefaultValueHelper;
import info.nightscout.androidaps.utils.TrendCalculator;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
+import info.nightscout.androidaps.utils.wizard.QuickWizard;
import info.nightscout.shared.sharedPreferences.SP;
public class WatchUpdaterService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
@@ -81,6 +83,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
@Inject ReceiverStatusStore receiverStatusStore;
@Inject Config config;
@Inject public TrendCalculator trendCalculator;
+ @Inject public QuickWizard quickWizard;
public static final String ACTION_RESEND = WatchUpdaterService.class.getName().concat(".Resend");
public static final String ACTION_OPEN_SETTINGS = WatchUpdaterService.class.getName().concat(".OpenSettings");
@@ -101,12 +104,14 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
private static final String OPEN_SETTINGS_PATH = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear";
private static final String NEW_PREFERENCES_PATH = "/sendpreferencestowear";
+ private static final String QUICK_WIZARD_PATH = "/send_quick_wizard";
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress";
public static final String ACTION_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
public static final String ACTION_CHANGECONFIRMATION_REQUEST_PATH = "/nightscout_watch_changeconfirmationrequest";
public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest";
+ String TAG = "WatchUpdateService";
private static boolean lastLoopStatus;
@@ -156,7 +161,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent != null ? intent.getAction() : null;
- // Log.d(TAG, logPrefix + "onStartCommand: " + action);
+ // Log.d(TAG, "onStartCommand: " + action);
if (wearIntegration()) {
handler.post(() -> {
@@ -235,7 +240,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
super.onPeerConnected(peer);
String id = peer.getId();
String name = peer.getDisplayName();
- // Log.d(TAG, logPrefix + "onPeerConnected peer name & ID: " + name + "|" + id);
+ Log.d(TAG, "onPeerConnected peer name & ID: " + name + "|" + id);
}
@@ -244,14 +249,14 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
super.onPeerDisconnected(peer);
String id = peer.getId();
String name = peer.getDisplayName();
- // Log.d(TAG, logPrefix + "onPeerDisconnected peer name & ID: " + name + "|" + id);
+ Log.d(TAG, "onPeerDisconnected peer name & ID: " + name + "|" + id);
}
@Override
public void onMessageReceived(MessageEvent event) {
- // Log.d(TAG, logPrefix + "onMessageRecieved: " + event);
+ // Log.d(TAG, "onMessageRecieved: " + event);
if (wearIntegration()) {
if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH)) {
@@ -283,7 +288,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
private void sendData() {
GlucoseValue lastBG = iobCobCalculator.getAds().lastBg();
- // Log.d(TAG, logPrefix + "LastBg=" + lastBG);
+ // Log.d(TAG, "LastBg=" + lastBG);
if (lastBG != null) {
GlucoseStatus glucoseStatus = glucoseStatusProvider.getGlucoseStatusData();
@@ -364,6 +369,10 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
googleApiConnect();
}
+
+ sendPreferences();
+ sendQuickWizard();
+
long startTime = System.currentTimeMillis() - (long) (60000 * 60 * 5.5);
GlucoseValue last_bg = iobCobCalculator.getAds().lastBg();
@@ -382,7 +391,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
entries.putDataMapArrayList("entries", dataMaps);
(new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, entries);
}
- sendPreferences();
sendBasals();
sendStatus();
}
@@ -720,19 +728,62 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
private void sendPreferences() {
if (googleApiClient != null && googleApiClient.isConnected()) {
+ GlucoseUnit units = profileFunction.getUnits();
boolean wearcontrol = sp.getBoolean(R.string.key_wear_control, false);
-
+ boolean mgdl = units.equals(GlucoseUnit.MGDL);
+ int percentage = sp.getInt(R.string.key_boluswizard_percentage, 100);
+ int maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
+ double maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0);
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_PREFERENCES_PATH);
//unique content
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_wear_control), wearcontrol);
+ dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_units_mgdl), mgdl);
+ dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_boluswizard_percentage), percentage);
+ dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_treatmentssafety_maxcarbs), maxCarbs);
+ dataMapRequest.getDataMap().putDouble(rh.gs(R.string.key_treatmentssafety_maxbolus),maxBolus);
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
} else {
- Log.e("SendStatus", "No connection to wearable available!");
+ Log.e("SendPreferences", "No connection to wearable available!");
}
}
+ private void sendQuickWizard() {
+ if (googleApiClient != null && googleApiClient.isConnected()) {
+ int size = quickWizard.size();
+ ArrayList entities = new ArrayList<>();
+ for(int i=0; i < size; i++) {
+ QuickWizardEntry q = quickWizard.get(i);
+ if (q.forDevice(QuickWizardEntry.DEVICE_WATCH)) {
+ entities.add(quickMap(q));
+ }
+ }
+
+ PutDataMapRequest dataMapRequest = PutDataMapRequest.create(QUICK_WIZARD_PATH);
+
+ DataMap dm = dataMapRequest.getDataMap();
+ dm.putLong("timestamp", System.currentTimeMillis());
+ dm.putDataMapArrayList("quick_wizard", entities);
+
+ PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
+ Log.i(TAG, "sendQuickWizard: " + putDataRequest);
+ Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
+ } else {
+ Log.e("sendQuickWizard", "No connection to wearable available!");
+ }
+ }
+
+ private DataMap quickMap(QuickWizardEntry q) {
+ DataMap dm = new DataMap();
+ dm.putString("guid", q.guid());
+ dm.putString("button_text", q.buttonText());
+ dm.putInt("carbs", q.carbs());
+ dm.putInt("from", q.validFrom());
+ dm.putInt("to", q.validTo());
+ return dm;
+ }
+
@NonNull
private String generateStatusString(Profile profile, String currentBasal, String iobSum, String iobDetail, String bgiString) {
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 0d37bb7c83..0b52087e66 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
@@ -33,6 +33,8 @@ import info.nightscout.androidaps.utils.ui.TimeListEdit
import info.nightscout.shared.SafeParse
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
+import info.nightscout.shared.logging.AAPSLogger
+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))
}
}
@@ -117,6 +121,7 @@ class LocalProfileFragment : DaggerFragment() {
processVisibilityOnClick(it)
binding.target.visibility = View.VISIBLE
}
+ binding.dia.editText?.id?.let { binding.diaLabel.labelFor = it }
}
fun build() {
@@ -130,14 +135,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 +188,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 +280,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 7920902eda..d285db5f0a 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/utils/TrendCalculator.kt b/app/src/main/java/info/nightscout/androidaps/utils/TrendCalculator.kt
index a5f2dc2dcb..869feb2fe8 100644
--- a/app/src/main/java/info/nightscout/androidaps/utils/TrendCalculator.kt
+++ b/app/src/main/java/info/nightscout/androidaps/utils/TrendCalculator.kt
@@ -1,20 +1,37 @@
package info.nightscout.androidaps.utils
+import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue
+import info.nightscout.androidaps.database.entities.GlucoseValue.TrendArrow.*
+import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TrendCalculator @Inject constructor(
- private val repository: AppRepository
+ private val repository: AppRepository,
+ private val rh: ResourceHelper
) {
fun getTrendArrow(glucoseValue: GlucoseValue?): GlucoseValue.TrendArrow =
when {
- glucoseValue?.trendArrow == null -> GlucoseValue.TrendArrow.NONE
- glucoseValue.trendArrow != GlucoseValue.TrendArrow.NONE -> glucoseValue.trendArrow
- else -> calculateDirection(glucoseValue)
+ glucoseValue?.trendArrow == null -> NONE
+ glucoseValue.trendArrow != NONE -> glucoseValue.trendArrow
+ else -> calculateDirection(glucoseValue)
+ }
+
+ fun getTrendDescription(glucoseValue: GlucoseValue?): String =
+ when (getTrendArrow(glucoseValue)) {
+ DOUBLE_DOWN -> rh.gs(R.string.a11y_arrow_double_down)
+ SINGLE_DOWN -> rh.gs(R.string.a11y_arrow_single_down)
+ FORTY_FIVE_DOWN -> rh.gs(R.string.a11y_arrow_forty_five_down)
+ FLAT -> rh.gs(R.string.a11y_arrow_flat)
+ FORTY_FIVE_UP -> rh.gs(R.string.a11y_arrow_forty_five_up)
+ SINGLE_UP -> rh.gs(R.string.a11y_arrow_single_up)
+ DOUBLE_UP -> rh.gs(R.string.a11y_arrow_double_up)
+ NONE -> rh.gs(R.string.a11y_arrow_none)
+ else -> rh.gs(R.string.a11y_arrow_unknown)
}
private fun calculateDirection(glucoseValue: GlucoseValue): GlucoseValue.TrendArrow {
@@ -23,7 +40,7 @@ class TrendCalculator @Inject constructor(
val readings = repository.compatGetBgReadingsDataFromTime(toTime - T.mins(10).msecs(), toTime, false).blockingGet()
if (readings.size < 2)
- return GlucoseValue.TrendArrow.NONE
+ return NONE
val current = readings[0]
val previous = readings[1]
@@ -35,14 +52,14 @@ class TrendCalculator @Inject constructor(
val slopeByMinute = slope * 60000
return when {
- slopeByMinute <= -3.5 -> GlucoseValue.TrendArrow.DOUBLE_DOWN
- slopeByMinute <= -2 -> GlucoseValue.TrendArrow.SINGLE_DOWN
- slopeByMinute <= -1 -> GlucoseValue.TrendArrow.FORTY_FIVE_DOWN
- slopeByMinute <= 1 -> GlucoseValue.TrendArrow.FLAT
- slopeByMinute <= 2 -> GlucoseValue.TrendArrow.FORTY_FIVE_UP
- slopeByMinute <= 3.5 -> GlucoseValue.TrendArrow.SINGLE_UP
- slopeByMinute <= 40 -> GlucoseValue.TrendArrow.DOUBLE_UP
- else -> GlucoseValue.TrendArrow.NONE
+ slopeByMinute <= -3.5 -> DOUBLE_DOWN
+ slopeByMinute <= -2 -> SINGLE_DOWN
+ slopeByMinute <= -1 -> FORTY_FIVE_DOWN
+ slopeByMinute <= 1 -> FLAT
+ slopeByMinute <= 2 -> FORTY_FIVE_UP
+ slopeByMinute <= 3.5 -> SINGLE_UP
+ slopeByMinute <= 40 -> DOUBLE_UP
+ else -> NONE
}
}
-}
\ No newline at end of file
+}
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..1d79a9205e 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();
@@ -108,6 +112,7 @@ public class TimeListEdit {
float factor = layout.getContext().getResources().getDisplayMetrics().density;
finalAdd = new ImageView(context);
finalAdd.setImageResource(R.drawable.ic_add);
+ finalAdd.setContentDescription(layout.getContext().getResources().getString(R.string.a11y_add_new_to_list));
LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams((int) (35d * factor), (int) (35 * factor));
illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom);
illp.gravity = Gravity.CENTER;
@@ -177,7 +182,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 +208,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 +263,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 7dd5687e92..dca32f246a 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
@@ -18,6 +18,8 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertOrUpdateBolusCalculatorResultTransaction
import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.extensions.formatColor
+import info.nightscout.androidaps.extensions.highValueToUnitsToString
+import info.nightscout.androidaps.extensions.lowValueToUnitsToString
import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
@@ -135,27 +137,28 @@ class BolusWizard @Inject constructor(
private var quickWizard: Boolean = true
var usePercentage: Boolean = false
- fun doCalc(profile: Profile,
- profileName: String,
- tempTarget: TemporaryTarget?,
- carbs: Int,
- cob: Double,
- bg: Double,
- correction: Double,
- percentageCorrection: Int = 100,
- useBg: Boolean,
- useCob: Boolean,
- includeBolusIOB: Boolean,
- includeBasalIOB: Boolean,
- useSuperBolus: Boolean,
- useTT: Boolean,
- useTrend: Boolean,
- useAlarm: Boolean,
- notes: String = "",
- carbTime: Int = 0,
- usePercentage: Boolean = false,
- totalPercentage: Double = 100.0,
- quickWizard: Boolean = false
+ fun doCalc(
+ profile: Profile,
+ profileName: String,
+ tempTarget: TemporaryTarget?,
+ carbs: Int,
+ cob: Double,
+ bg: Double,
+ correction: Double,
+ percentageCorrection: Int = 100,
+ useBg: Boolean,
+ useCob: Boolean,
+ includeBolusIOB: Boolean,
+ includeBasalIOB: Boolean,
+ useSuperBolus: Boolean,
+ useTT: Boolean,
+ useTrend: Boolean,
+ useAlarm: Boolean,
+ notes: String = "",
+ carbTime: Int = 0,
+ usePercentage: Boolean = false,
+ totalPercentage: Double = 100.0,
+ quickWizard: Boolean = false
): BolusWizard {
this.profile = profile
@@ -261,22 +264,23 @@ class BolusWizard @Inject constructor(
return this
}
- private fun createBolusCalculatorResult(): BolusCalculatorResult =
- BolusCalculatorResult(
+ private fun createBolusCalculatorResult(): BolusCalculatorResult {
+ val unit = profileFunction.getUnits()
+ return BolusCalculatorResult(
timestamp = dateUtil.now(),
- targetBGLow = targetBGLow,
- targetBGHigh = targetBGHigh,
- isf = sens,
+ targetBGLow = Profile.toMgdl(targetBGLow, unit),
+ targetBGHigh = Profile.toMgdl(targetBGHigh, unit),
+ isf = Profile.toMgdl(sens, unit),
ic = ic,
bolusIOB = insulinFromBolusIOB,
wasBolusIOBUsed = includeBolusIOB,
basalIOB = insulinFromBasalIOB,
wasBasalIOBUsed = includeBasalIOB,
- glucoseValue = bg,
+ glucoseValue = Profile.toMgdl(bg, unit),
wasGlucoseUsed = useBg && bg > 0,
glucoseDifference = bgDiff,
glucoseInsulin = insulinFromBG,
- glucoseTrend = trend,
+ glucoseTrend = Profile.fromMgdlToUnits(trend, unit),
wasTrendUsed = useTrend,
trendInsulin = insulinFromTrend,
cob = cob,
@@ -294,6 +298,7 @@ class BolusWizard @Inject constructor(
profileName = profileName,
note = notes
)
+ }
private fun confirmMessageAfterConstraints(advisor: Boolean): Spanned {
@@ -312,7 +317,9 @@ class BolusWizard @Inject constructor(
actions.add(rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs).formatColor(rh, R.color.carbs) + timeShift)
}
if (insulinFromCOB > 0) {
- actions.add(rh.gs(R.string.cobvsiob) + ": " + rh.gs(R.string.formatsignedinsulinunits, insulinFromBolusIOB + insulinFromBasalIOB + insulinFromCOB + insulinFromBG).formatColor(rh, R.color.cobAlert))
+ actions.add(
+ rh.gs(R.string.cobvsiob) + ": " + rh.gs(R.string.formatsignedinsulinunits, insulinFromBolusIOB + insulinFromBasalIOB + insulinFromCOB + insulinFromBG).formatColor(rh, R.color.cobAlert)
+ )
val absorptionRate = iobCobCalculator.ads.slowAbsorptionPercentage(60)
if (absorptionRate > .25)
actions.add(rh.gs(R.string.slowabsorptiondetected, rh.gc(R.color.cobAlert), (absorptionRate * 100).toInt()))
@@ -342,11 +349,13 @@ class BolusWizard @Inject constructor(
carbTimer.removeEatReminder()
if (sp.getBoolean(R.string.key_usebolusadvisor, false) && Profile.toMgdl(bg, profile.units) > 180 && carbs > 0 && carbTime >= 0)
OKDialog.showYesNoCancel(ctx, rh.gs(R.string.bolusadvisor), rh.gs(R.string.bolusadvisormessage),
- { bolusAdvisorProcessing(ctx) },
- { commonProcessing(ctx) }
+ { bolusAdvisorProcessing(ctx) },
+ { commonProcessing(ctx) }
)
else
commonProcessing(ctx)
+ } else {
+ OKDialog.show(ctx, rh.gs(R.string.boluswizard), rh.gs(R.string.no_action_selected))
}
}
@@ -363,10 +372,13 @@ class BolusWizard @Inject constructor(
carbTime = 0
bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes
- uel.log(Action.BOLUS_ADVISOR, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
+ uel.log(
+ Action.BOLUS_ADVISOR,
+ if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
notes,
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
- ValueWithUnit.Insulin(insulinAfterConstraints))
+ ValueWithUnit.Insulin(insulinAfterConstraints)
+ )
if (insulin > 0) {
commandQueue.bolus(this, object : Callback() {
override fun run() {
@@ -381,6 +393,26 @@ class BolusWizard @Inject constructor(
})
}
+ fun explainShort(): String {
+ var message = rh.gs(R.string.wizard_explain_calc, ic, sens)
+ message += "\n" + rh.gs(R.string.wizard_explain_carbs, insulinFromCarbs)
+ if (useTT && tempTarget != null) {
+ val tt = if (tempTarget?.lowTarget == tempTarget?.highTarget) tempTarget?.lowValueToUnitsToString(profile.units)
+ else rh.gs(R.string.wizard_explain_tt_to, tempTarget?.lowValueToUnitsToString(profile.units), tempTarget?.highValueToUnitsToString(profile.units))
+ message += "\n" + rh.gs(R.string.wizard_explain_tt, tt)
+ }
+ if (useCob) message += "\n" + rh.gs(R.string.wizard_explain_cob, cob, insulinFromCOB)
+ if (useBg) message += "\n" + rh.gs(R.string.wizard_explain_bg, insulinFromBG)
+ if (includeBolusIOB) message += "\n" + rh.gs(R.string.wizard_explain_bolus_iob, insulinFromBolusIOB)
+ if (includeBasalIOB) message += "\n" + rh.gs(R.string.wizard_explain_basal_iob, insulinFromBasalIOB)
+ if (useTrend) message += "\n" + rh.gs(R.string.wizard_explain_trend, insulinFromTrend)
+ if (useSuperBolus) message += "\n" + rh.gs(R.string.wizard_explain_superbolus, insulinFromSuperBolus)
+ if (percentageCorrection != 100) {
+ message += "\n" + rh.gs(R.string.wizard_explain_percent, totalBeforePercentageAdjustment, percentageCorrection, calculatedTotalInsulin)
+ }
+ return message
+ }
+
private fun commonProcessing(ctx: Context) {
val profile = profileFunction.getProfile() ?: return
val pump = activePlugin.activePump
@@ -429,17 +461,17 @@ class BolusWizard @Inject constructor(
bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes
if (insulin > 0 || carbs > 0) {
- val action = when {
+ val action = when {
insulinAfterConstraints.equals(0.0) -> Action.CARBS
carbs.equals(0.0) -> Action.BOLUS
else -> Action.TREATMENT
}
uel.log(action, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
- notes,
- ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
- ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
- ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 },
- ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 })
+ notes,
+ ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
+ ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
+ ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 },
+ ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 })
commandQueue.bolus(this, object : Callback() {
override fun run() {
if (!result.success) {
@@ -465,9 +497,9 @@ class BolusWizard @Inject constructor(
private fun calcPercentageWithConstraints() {
calculatedPercentage = 100.0
if (totalBeforePercentageAdjustment != insulinFromCorrection)
- calculatedPercentage = calculatedTotalInsulin/(totalBeforePercentageAdjustment-insulinFromCorrection) * 100
+ calculatedPercentage = calculatedTotalInsulin / (totalBeforePercentageAdjustment - insulinFromCorrection) * 100
calculatedPercentage = max(calculatedPercentage, 10.0)
- calculatedPercentage = min(calculatedPercentage,250.0)
+ calculatedPercentage = min(calculatedPercentage, 250.0)
}
private fun calcCorrectionWithConstraints() {
@@ -477,4 +509,4 @@ class BolusWizard @Inject constructor(
calculatedCorrection = max(-constraintChecker.getMaxBolusAllowed().value(), calculatedCorrection)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizard.kt
index a254831690..b48d44c9cc 100644
--- a/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizard.kt
+++ b/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizard.kt
@@ -1,10 +1,12 @@
package info.nightscout.androidaps.utils.wizard
+import android.util.Log
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONObject
+import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@@ -18,6 +20,18 @@ class QuickWizard @Inject constructor(
init {
setData(JSONArray(sp.getString(R.string.key_quickwizard, "[]")))
+ setGuidsForOldEntries()
+ }
+
+ private fun setGuidsForOldEntries() {
+ // for migration purposes; guid is a new required property
+ for (i in 0 until storage.length()) {
+ val entry = QuickWizardEntry(injector).from(storage.get(i) as JSONObject, i)
+ if (entry.guid() == "") {
+ val guid = UUID.randomUUID().toString()
+ entry.storage.put("guid", guid)
+ }
+ }
}
fun getActive(): QuickWizardEntry? {
@@ -41,6 +55,38 @@ class QuickWizard @Inject constructor(
operator fun get(position: Int): QuickWizardEntry =
QuickWizardEntry(injector).from(storage.get(position) as JSONObject, position)
+ fun get(guid: String): QuickWizardEntry? {
+ for (i in 0 until storage.length()) {
+ val entry = QuickWizardEntry(injector).from(storage.get(i) as JSONObject, i)
+ if (entry.guid() == guid) {
+ return entry
+ }
+ }
+ return null
+ }
+
+ fun move(from: Int, to: Int) {
+ Log.i("QuickWizard", "moveItem: $from $to")
+ val fromEntry = storage[from] as JSONObject
+ storage.remove(from)
+ addToPos(to, fromEntry, storage)
+ save()
+ }
+
+ fun removePos(pos: Int, jsonObj: JSONObject?, jsonArr: JSONArray) {
+ for (i in jsonArr.length() downTo pos + 1) {
+ jsonArr.put(i, jsonArr[i - 1])
+ }
+ jsonArr.put(pos, jsonObj)
+ }
+
+ private fun addToPos(pos: Int, jsonObj: JSONObject?, jsonArr: JSONArray) {
+ for (i in jsonArr.length() downTo pos + 1) {
+ jsonArr.put(i, jsonArr[i - 1])
+ }
+ jsonArr.put(pos, jsonObj)
+ }
+
fun newEmptyItem(): QuickWizardEntry {
return QuickWizardEntry(injector)
}
@@ -57,4 +103,5 @@ class QuickWizard @Inject constructor(
storage.remove(position)
save()
}
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt b/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt
index 79ff43bf66..c6dee8a660 100644
--- a/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt
+++ b/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt
@@ -19,6 +19,7 @@ import info.nightscout.androidaps.utils.JsonHelper.safeGetString
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONException
import org.json.JSONObject
+import java.util.*
import javax.inject.Inject
class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjector) {
@@ -41,11 +42,26 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
const val NO = 1
private const val POSITIVE_ONLY = 2
private const val NEGATIVE_ONLY = 3
+ const val DEVICE_ALL = 0
+ const val DEVICE_PHONE = 1
+ const val DEVICE_WATCH = 2
+ const val DEFAULT = 0
+ const val CUSTOM = 1
}
init {
injector.androidInjector().inject(this)
- val emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}"
+ val guid = UUID.randomUUID().toString()
+ val emptyData = """{
+ "guid": "$guid",
+ "buttonText": "",
+ "carbs": 0,
+ "validFrom": 0,
+ "validTo": 86340,
+ "device": "all",
+ "usePercentage": "default",
+ "percentage": 100
+ }""".trimMargin()
try {
storage = JSONObject(emptyData)
} catch (e: JSONException) {
@@ -55,6 +71,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
/*
{
+ guid: string,
+ device: string, // (phone, watch, all)
buttonText: "Meal",
carbs: 36,
validFrom: 8 * 60 * 60, // seconds from midnight
@@ -66,15 +84,18 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
useTrend: 0,
useSuperBolus: 0,
useTemptarget: 0
+ usePercentage: string, // default, custom
+ percentage: int,
}
*/
fun from(entry: JSONObject, position: Int): QuickWizardEntry {
+ // TODO set guid if missing for migration
storage = entry
this.position = position
return this
}
- fun isActive(): Boolean = profileFunction.secondsFromMidnight() >= validFrom() && profileFunction.secondsFromMidnight() <= validTo()
+ fun isActive(): Boolean = profileFunction.secondsFromMidnight() >= validFrom() && profileFunction.secondsFromMidnight() <= validTo() && forDevice(DEVICE_PHONE)
fun doCalc(profile: Profile, profileName: String, lastBG: GlucoseValue, _synchronized: Boolean): BolusWizard {
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
@@ -119,10 +140,16 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
} else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.shortAvgDelta < 0) {
trend = true
}
- val percentage = sp.getInt(R.string.key_boluswizard_percentage, 100)
+ val percentage = if (usePercentage() == DEFAULT) sp.getInt(R.string.key_boluswizard_percentage, 100) else percentage()
return BolusWizard(injector).doCalc(profile, profileName, tempTarget, carbs(), cob, bg, 0.0, percentage, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, false, buttonText(), quickWizard = true) //tbc, ok if only quickwizard, but if other sources elsewhere use Sources.QuickWizard
}
+ fun guid(): String = safeGetString(storage, "guid", "")
+
+ fun device(): Int = safeGetInt(storage, "device", DEVICE_ALL)
+
+ fun forDevice(device: Int) = device() == device || device() == DEVICE_ALL
+
fun buttonText(): String = safeGetString(storage, "buttonText", "")
fun carbs(): Int = safeGetInt(storage, "carbs")
@@ -148,4 +175,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
fun useSuperBolus(): Int = safeGetInt(storage, "useSuperBolus", NO)
fun useTempTarget(): Int = safeGetInt(storage, "useTempTarget", NO)
-}
\ No newline at end of file
+
+ fun usePercentage(): Int = safeGetInt(storage, "usePercentage", DEFAULT)
+
+ fun percentage(): Int = safeGetInt(storage, "percentage", 100)
+}
diff --git a/app/src/main/res/drawable/cb_background_bg.xml b/app/src/main/res/drawable/cb_background_bg.xml
new file mode 100644
index 0000000000..cf493051a9
--- /dev/null
+++ b/app/src/main/res/drawable/cb_background_bg.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/cb_background_cob.xml b/app/src/main/res/drawable/cb_background_cob.xml
new file mode 100644
index 0000000000..b73f1f3b39
--- /dev/null
+++ b/app/src/main/res/drawable/cb_background_cob.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/cb_background_iob.xml b/app/src/main/res/drawable/cb_background_iob.xml
new file mode 100644
index 0000000000..bce5594f2a
--- /dev/null
+++ b/app/src/main/res/drawable/cb_background_iob.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/cb_background_trend.xml b/app/src/main/res/drawable/cb_background_trend.xml
new file mode 100644
index 0000000000..74e90acb2f
--- /dev/null
+++ b/app/src/main/res/drawable/cb_background_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..f22b42b4d9
--- /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..391e1bf226
--- /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..f9bcb46d52
--- /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..025544c3fd
--- /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 @@
+ android:layout_height="40dp"
+ app:customContentDescription="@string/age" />
@@ -105,14 +105,14 @@
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
- android:labelFor="@+id/weight"
android:text="@string/tdd_total"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/tdd_total" />
@@ -123,18 +123,18 @@
android:gravity="center_vertical">
+ android:layout_height="40dp"
+ app:customContentDescription="@string/weight_label" />
@@ -149,14 +149,14 @@
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
- android:labelFor="@+id/basalpctfromtdd"
android:text="@string/basalpctfromtdd_label"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/basalpctfromtdd_label" />
diff --git a/app/src/main/res/layout/activity_stats.xml b/app/src/main/res/layout/activity_stats.xml
index 6335214899..cbadce20e9 100644
--- a/app/src/main/res/layout/activity_stats.xml
+++ b/app/src/main/res/layout/activity_stats.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/treatments_wizard_bg_label" />
-
-
+ android:padding="2dp"
+ android:layoutDirection="rtl"
+ android:contentDescription="@string/a11y_carb_reminder"
+ android:drawableEnd="@drawable/ic_access_alarm_24dp" />
+
+ android:layout_height="40dp"
+ app:customContentDescription="@string/time_offset" />
+ android:layout_gravity="center_horizontal"
+ app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/treatments_wizard_carbs_label" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/treatments_wizard_bg_label" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/overview_insulin_label" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
+ android:paddingRight="5dp"
+ app:customContentDescription="@string/overview_insulin_label" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/time_offset"/>
+ android:layout_height="40dp"
+ app:customContentDescription="@string/overview_insulin_label"/>
+ android:layout_height="40dp"
+ app:customContentDescription="@string/careportal_newnstreatment_duration_label"/>
+ android:layout_height="40dp"
+ app:customContentDescription="@string/careportal_newnstreatment_percentage_label"/>
+ android:layout_height="40dp"
+ app:customContentDescription="@string/careportal_newnstreatment_timeshift_label"/>
+ android:layout_height="40dp"
+ app:customContentDescription="@string/basal_rate" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/basal_rate" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
+ android:layout_gravity="center_vertical"
+ app:customContentDescription="@string/target_label" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
diff --git a/app/src/main/res/layout/dialog_treatment.xml b/app/src/main/res/layout/dialog_treatment.xml
index 2927d9a040..ff4d473cf0 100644
--- a/app/src/main/res/layout/dialog_treatment.xml
+++ b/app/src/main/res/layout/dialog_treatment.xml
@@ -25,30 +25,21 @@
-
-
-
-
-
+
+
+ android:layout_height="40dp"
+ app:customContentDescription="@string/overview_insulin_label" />
+ android:layout_height="40dp"
+ app:customContentDescription="@string/treatments_wizard_carbs_label" />
+ 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" />
-
+
-
-
-
-
+ android:layout_gravity="center"
+ app:contentDescription="carb time" />
-
-
-
-
+ android:checked="true"
+ android:text="@string/treatments_wizard_bg_label" />
-
-
+ android:checked="false"
+ android:text="@string/treatments_wizard_tt_label" />
@@ -506,15 +459,9 @@
android:id="@+id/bg_trend_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:width="32dp"
- android:checked="false" />
+ android:checked="false"
+ android:text="@string/bg_trend_label" />
-
-
-
+ android:checked="true"
+ android:text="@string/iob" />
-
-
+ android:checked="false"
+ android:text="@string/treatments_wizard_cob_label" />
+ android:layout_height="match_parent"
+ android:focusable="true">
-
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
-
+
+
+
+
+
+ android:layout_height="match_parent"
+ android:focusable="true">
-
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
-
+
+
+
+
+
+ android:layout_height="match_parent"
+ android:focusable="true">
-
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
-
+
+
+
+
+
+
@@ -712,4 +671,4 @@
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/dialog_wizardinfo.xml b/app/src/main/res/layout/dialog_wizardinfo.xml
index d83c7f7d4e..771af78e82 100644
--- a/app/src/main/res/layout/dialog_wizardinfo.xml
+++ b/app/src/main/res/layout/dialog_wizardinfo.xml
@@ -25,7 +25,7 @@
@@ -35,6 +36,40 @@
+
+
+
+
+
+
+
+
+
+
@@ -152,32 +187,13 @@
android:layout_height="wrap_content"
android:orientation="vertical">
-
-
-
-
-
-
-
+ android:gravity="center_horizontal"
+ android:text="@string/dia_long_label"
+ android:textColor="@android:color/white"
+ android:textSize="20sp" />
+ android:layout_marginBottom="10dp"
+ app:customContentDescription="@string/dia" />
+
+
+
+
+
+