Merge branch 'dev' into rxjava3

This commit is contained in:
Milos Kozak 2022-02-17 21:45:20 +01:00
commit e27bb2d04c
209 changed files with 5717 additions and 1549 deletions

View file

@ -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) [![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) [![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) [![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) [![codecov](https://codecov.io/gh/nightscout/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)
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 <img src="https://cdn.iconscout.com/icon/free/png-256/bitcoin-384-920569.png" srcset="https://cdn.iconscout.com/icon/free/png-512/bitcoin-384-920569.png 2x" alt="Bitcoin Icon" width="100">
3KawK8aQe48478s6fxJ8Ms6VTWkwjgr9f2

File diff suppressed because it is too large Load diff

View file

@ -239,6 +239,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
} }
ToastUtils.showToastInUiThread(this, R.string.invalidinput) 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) switchTab(0, typeSelected[0], false)
} }

View file

@ -271,6 +271,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
_binding = null _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<MealLink>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() { inner class RecyclerViewAdapter internal constructor(var mealLinks: List<MealLink>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder = override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder =
@ -280,16 +282,20 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
val profile = profileFunction.getProfile() ?: return val profile = profileFunction.getProfile() ?: return
val ml = mealLinks[position] 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 // Metadata
holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || binding.showInvalidated.isChecked)).toVisibility() holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || binding.showInvalidated.isChecked)).toVisibility()
ml.bolusCalculatorResult?.let { bolusCalculatorResult -> ml.bolusCalculatorResult?.let { bolusCalculatorResult ->
holder.binding.date.text = dateUtil.dateAndTimeString(bolusCalculatorResult.timestamp) holder.binding.calcTime.text = dateUtil.timeString(bolusCalculatorResult.timestamp)
} }
// Bolus // Bolus
holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus.isValid || binding.showInvalidated.isChecked)).toVisibility() holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus.isValid || binding.showInvalidated.isChecked)).toVisibility()
ml.bolus?.let { bolus -> 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.insulin.text = rh.gs(R.string.formatinsulinunits, bolus.amount)
holder.binding.bolusNs.visibility = (bolus.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.bolusNs.visibility = (bolus.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.bolusPump.visibility = (bolus.interfaceIDs.pumpId != null).toVisibility() holder.binding.bolusPump.visibility = (bolus.interfaceIDs.pumpId != null).toVisibility()
@ -317,7 +323,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
// Carbs // Carbs
holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || binding.showInvalidated.isChecked)).toVisibility() holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || binding.showInvalidated.isChecked)).toVisibility()
ml.carbs?.let { carbs -> 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.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.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() holder.binding.carbsNs.visibility = (carbs.interfaceIDs.nightscoutId != null).toVisibility()
@ -330,6 +336,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
holder.binding.bolusRemove.tag = ml holder.binding.bolusRemove.tag = ml
holder.binding.carbsRemove.tag = ml holder.binding.carbsRemove.tag = ml
holder.binding.calculation.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 { override fun getItemCount(): Int {

View file

@ -152,7 +152,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
_binding = null _binding = null
} }
inner class RecyclerViewAdapter internal constructor(private var list: List<TherapyEvent>) : RecyclerView.Adapter<TherapyEventsViewHolder>() { inner class RecyclerViewAdapter internal constructor(private var therapyList: List<TherapyEvent>) : RecyclerView.Adapter<TherapyEventsViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TherapyEventsViewHolder { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TherapyEventsViewHolder {
val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_careportal_item, viewGroup, false) 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) { 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.ns.visibility = (therapyEvent.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = therapyEvent.isValid.not().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.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh)
holder.binding.note.text = therapyEvent.note holder.binding.note.text = therapyEvent.note
holder.binding.type.text = translator.translate(therapyEvent.type) holder.binding.type.text = translator.translate(therapyEvent.type)
holder.binding.remove.tag = therapyEvent 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 { override fun getItemCount(): Int {
return list.size return therapyList.size
} }
inner class TherapyEventsViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class TherapyEventsViewHolder(view: View) : RecyclerView.ViewHolder(view) {

View file

@ -125,13 +125,16 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility() holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility()
holder.binding.invalid.visibility = extendedBolus.isValid.not().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") @SuppressLint("SetTextI18n")
if (extendedBolus.isInProgress(dateUtil)) { if (extendedBolus.isInProgress(dateUtil)) {
holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.timestamp) holder.binding.time.text = dateUtil.timeString(extendedBolus.timestamp)
holder.binding.date.setTextColor(rh.gc(R.color.colorActive)) holder.binding.time.setTextColor(rh.gc(R.color.colorActive))
} else { } else {
holder.binding.date.text = dateUtil.dateAndTimeString(extendedBolus.timestamp) + " - " + dateUtil.timeString(extendedBolus.end) holder.binding.time.text = dateUtil.timeRangeString(extendedBolus.timestamp, extendedBolus.end)
holder.binding.date.setTextColor(holder.binding.insulin.currentTextColor) holder.binding.time.setTextColor(holder.binding.insulin.currentTextColor)
} }
val profile = profileFunction.getProfile(extendedBolus.timestamp) ?: return val profile = profileFunction.getProfile(extendedBolus.timestamp) ?: return
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(extendedBolus.duration).mins()) 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) 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) 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 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 override fun getItemCount(): Int = extendedBolusList.size

View file

@ -181,7 +181,10 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
val profileSwitch = profileSwitchList[position] val profileSwitch = profileSwitchList[position]
holder.binding.ph.visibility = (profileSwitch is ProfileSealed.EPS).toVisibility() holder.binding.ph.visibility = (profileSwitch is ProfileSealed.EPS).toVisibility()
holder.binding.ns.visibility = (profileSwitch.interfaceIDs_backing?.nightscoutId != null).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.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 "" 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)) 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.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
holder.binding.spacer.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)) 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 { override fun getItemCount(): Int {

View file

@ -164,18 +164,23 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility() holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
holder.binding.remove.visibility = tempTarget.isValid.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.duration.text = rh.gs(R.string.format_mins, T.msecs(tempTarget.duration).mins())
holder.binding.low.text = tempTarget.lowValueToUnitsToString(units) holder.binding.low.text = tempTarget.lowValueToUnitsToString(units)
holder.binding.high.text = tempTarget.highValueToUnitsToString(units) holder.binding.high.text = tempTarget.highValueToUnitsToString(units)
holder.binding.reason.text = translator.translate(tempTarget.reason) holder.binding.reason.text = translator.translate(tempTarget.reason)
holder.binding.date.setTextColor( holder.binding.time.setTextColor(
when { when {
tempTarget.id == currentlyActiveTarget?.id -> rh.gc(R.color.colorActive) tempTarget.id == currentlyActiveTarget?.id -> rh.gc(R.color.colorActive)
tempTarget.timestamp > dateUtil.now() -> rh.gc(R.color.colorScheduled) tempTarget.timestamp > dateUtil.now() -> rh.gc(R.color.colorScheduled)
else -> holder.binding.reasonColon.currentTextColor else -> holder.binding.reasonColon.currentTextColor
}) })
holder.binding.remove.tag = tempTarget 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 override fun getItemCount(): Int = tempTargetList.size

View file

@ -15,7 +15,6 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.ExtendedBolus import info.nightscout.androidaps.database.entities.ExtendedBolus
import info.nightscout.androidaps.database.entities.TemporaryBasal 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.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit 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.ns.visibility = (tempBasal.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = tempBasal.isValid.not().toVisibility() holder.binding.invalid.visibility = tempBasal.isValid.not().toVisibility()
holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).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) { if (tempBasal.isInProgress) {
holder.binding.date.text = dateUtil.dateAndTimeString(tempBasal.timestamp) holder.binding.time.text = dateUtil.timeString(tempBasal.timestamp)
holder.binding.date.setTextColor(rh.gc(R.color.colorActive)) holder.binding.time.setTextColor(rh.gc(R.color.colorActive))
} else { } else {
holder.binding.date.text = dateUtil.dateAndTimeRangeString(tempBasal.timestamp, tempBasal.end) holder.binding.time.text = dateUtil.timeRangeString(tempBasal.timestamp, tempBasal.end)
holder.binding.date.setTextColor(holder.binding.duration.currentTextColor) holder.binding.time.setTextColor(holder.binding.duration.currentTextColor)
} }
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(tempBasal.duration).mins()) 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) 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() 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) 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 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 override fun getItemCount(): Int = tempBasalList.size

View file

@ -20,6 +20,7 @@ import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.events.EventTreatmentUpdateGui import info.nightscout.androidaps.events.EventTreatmentUpdateGui
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
@ -131,14 +132,19 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) { override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) {
val current = entries[position] 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.action.text = userEntryPresentationHelper.actionToColoredString(current.action)
holder.binding.s.text = current.note holder.binding.notes.text = current.note
holder.binding.s.visibility = if (current.note != "") View.VISIBLE else View.GONE holder.binding.notes.visibility = if (current.note != "") View.VISIBLE else View.GONE
holder.binding.iconSource.setImageResource(userEntryPresentationHelper.iconId(current.source)) holder.binding.iconSource.setImageResource(userEntryPresentationHelper.iconId(current.source))
holder.binding.iconSource.visibility = View.VISIBLE holder.binding.iconSource.visibility = View.VISIBLE
holder.binding.values.text = userEntryPresentationHelper.listToPresentationString(current.values) holder.binding.values.text = userEntryPresentationHelper.listToPresentationString(current.values)
holder.binding.values.visibility = if (holder.binding.values.text != "") View.VISIBLE else View.GONE 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) { inner class UserEntryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

View file

@ -7,6 +7,7 @@ import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalAdapterAM
import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.DetermineBasalAdapterSMBDynamicISFJS
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
@ -19,6 +20,7 @@ abstract class APSModule {
@ContributesAndroidInjector abstract fun determineBasalResultAMAInjector(): DetermineBasalResultAMA @ContributesAndroidInjector abstract fun determineBasalResultAMAInjector(): DetermineBasalResultAMA
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS @ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS @ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBDynamicISFJS
@ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread @ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread
@ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread @ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread
} }

View file

@ -14,6 +14,7 @@ import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploader
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.OpenAPSSMBDynamicISFPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin
@ -212,6 +213,12 @@ abstract class PluginsModule {
@IntKey(220) @IntKey(220)
abstract fun bindOpenAPSSMBPlugin(plugin: OpenAPSSMBPlugin): PluginBase abstract fun bindOpenAPSSMBPlugin(plugin: OpenAPSSMBPlugin): PluginBase
@Binds
@APS
@IntoMap
@IntKey(222)
abstract fun bindOpenAPSSMBAutoISFPlugin(plugin: OpenAPSSMBDynamicISFPlugin): PluginBase
@Binds @Binds
@AllConfigs @AllConfigs
@IntoMap @IntoMap

View file

@ -64,6 +64,7 @@ class CalibrationDialog : DialogFragmentWithDate() {
binding.bg.setParams(savedInstanceState?.getDouble("bg") binding.bg.setParams(savedInstanceState?.getDouble("bg")
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok) ?: 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.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() { override fun onDestroyView() {

View file

@ -137,32 +137,39 @@ class CarbsDialog : DialogFragmentWithDate() {
savedInstanceState?.getDouble("carbs") savedInstanceState?.getDouble("carbs")
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher ?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher
) )
val plus1text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
binding.plus1.text = 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.plus1.setOnClickListener {
binding.carbs.value = max( binding.carbs.value = max(
0.0, binding.carbs.value 0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT) + sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)
) )
validateInputs() 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.plus2.setOnClickListener {
binding.carbs.value = max( binding.carbs.value = max(
0.0, binding.carbs.value 0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT) + sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)
) )
validateInputs() validateInputs()
binding.carbs.announceValue()
} }
val plus3text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
binding.plus3.text = 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.plus3.setOnClickListener {
binding.carbs.value = max( binding.carbs.value = max(
0.0, binding.carbs.value 0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT) + sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)
) )
validateInputs() validateInputs()
binding.carbs.announceValue()
} }
setOnValueChangedListener { eventTime: Long -> setOnValueChangedListener { eventTime: Long ->
@ -188,6 +195,9 @@ class CarbsDialog : DialogFragmentWithDate() {
binding.hypoTt.isChecked = false binding.hypoTt.isChecked = false
binding.activityTt.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() { override fun onDestroyView() {

View file

@ -165,6 +165,8 @@ class CareDialog : DialogFragmentWithDate() {
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, binding.okcancel.ok) ?: 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) if (options == EventType.NOTE || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT || options == EventType.EXERCISE)
binding.notesLayout.root.visibility = View.VISIBLE // independent to preferences 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() { override fun onDestroyView() {

View file

@ -70,6 +70,8 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
binding.duration.setParams(savedInstanceState?.getDouble("duration") binding.duration.setParams(savedInstanceState?.getDouble("duration")
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, binding.okcancel.ok) ?: 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() { override fun onDestroyView() {

View file

@ -96,7 +96,7 @@ class FillDialog : DialogFragmentWithDate() {
} else { } else {
binding.fillPresetButton3.visibility = View.GONE binding.fillPresetButton3.visibility = View.GONE
} }
binding.fillInsulinamount.editText?.id?.let { binding.fillLabel.labelFor = it }
} }
override fun onDestroyView() { override fun onDestroyView() {

View file

@ -116,29 +116,40 @@ class InsulinDialog : DialogFragmentWithDate() {
binding.amount.setParams(savedInstanceState?.getDouble("amount") binding.amount.setParams(savedInstanceState?.getDouble("amount")
?: 0.0, 0.0, maxInsulin, activePlugin.activePump.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher) ?: 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.plus05.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT)) + sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
validateInputs() 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.plus10.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT)) + sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
validateInputs() 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.plus20.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT)) + sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
validateInputs() validateInputs()
binding.amount.announceValue()
} }
binding.timeLayout.visibility = View.GONE binding.timeLayout.visibility = View.GONE
binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean -> binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean ->
binding.timeLayout.visibility = isChecked.toVisibility() 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() { override fun onDestroyView() {

View file

@ -148,6 +148,9 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
} }
} }
binding.ttLayout.visibility = View.GONE 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() { override fun onDestroyView() {

View file

@ -86,6 +86,9 @@ class TempBasalDialog : DialogFragmentWithDate() {
binding.percentLayout.visibility = View.GONE binding.percentLayout.visibility = View.GONE
binding.absoluteLayout.visibility = View.VISIBLE 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() { override fun onDestroyView() {

View file

@ -120,6 +120,8 @@ class TempTargetDialog : DialogFragmentWithDate() {
longClick(it) longClick(it)
return@setOnLongClickListener true return@setOnLongClickListener true
} }
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
binding.temptarget.editText?.id?.let { binding.temptargetLabel.labelFor = it }
} }
} }

View file

@ -106,6 +106,8 @@ class TreatmentDialog : DialogFragmentWithDate() {
binding.insulin.setParams(savedInstanceState?.getDouble("insulin") binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher) ?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
binding.recordOnlyLayout.visibility = View.GONE 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() { override fun onDestroyView() {

View file

@ -4,11 +4,7 @@ import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.view.LayoutInflater import android.view.*
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener import android.widget.AdapterView.OnItemSelectedListener
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
@ -136,33 +132,36 @@ class WizardDialog : DaggerDialogFragment() {
val maxCorrection = constraintChecker.getMaxBolusAllowed().value() val maxCorrection = constraintChecker.getMaxBolusAllowed().value()
bolusStep = activePlugin.activePump.pumpDescription.bolusStep bolusStep = activePlugin.activePump.pumpDescription.bolusStep
if (profileFunction.getUnits() == GlucoseUnit.MGDL) if (profileFunction.getUnits() == GlucoseUnit.MGDL) {
binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input") binding.bgInput.setParams(
?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher) savedInstanceState?.getDouble("bg_input")
else ?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher)
binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input") } else {
?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.ok, textWatcher) 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") 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) { if (correctionPercent) {
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble() 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.correctionInput.value = calculatedPercentage
binding.correctionUnit.text = "%" binding.correctionUnit.text = "%"
} else { } else {
binding.correctionInput.setParams( binding.correctionInput.setParams(
savedInstanceState?.getDouble("correction_input") 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.correctionUnit.text = rh.gs(R.string.insulin_unit_shortname)
} }
binding.carbTimeInput.setParams(savedInstanceState?.getDouble("carb_time_input") 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() initDialog()
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble() 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)) binding.percentUsed.text = rh.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100))
// ok button // ok button
binding.ok.setOnClickListener { binding.okcancel.ok.setOnClickListener {
if (okClicked) { if (okClicked) {
aapsLogger.debug(LTag.UI, "guarding: ok already clicked") aapsLogger.debug(LTag.UI, "guarding: ok already clicked")
} else { } else {
@ -175,12 +174,12 @@ class WizardDialog : DaggerDialogFragment() {
} }
dismiss() dismiss()
} }
binding.bgEnabledIcon.setOnClickListener { binding.bgCheckbox.isChecked = !binding.bgCheckbox.isChecked } binding.bgCheckboxIcon.setOnClickListener { binding.bgCheckbox.isChecked = !binding.bgCheckbox.isChecked }
binding.trendEnabledIcon.setOnClickListener { binding.bgTrendCheckbox.isChecked = !binding.bgTrendCheckbox.isChecked } binding.trendCheckboxIcon.setOnClickListener { binding.bgTrendCheckbox.isChecked = !binding.bgTrendCheckbox.isChecked }
binding.cobEnabledIcon.setOnClickListener { binding.cobCheckbox.isChecked = !binding.cobCheckbox.isChecked; processCobCheckBox(); } binding.cobCheckboxIcon.setOnClickListener { binding.cobCheckbox.isChecked = !binding.cobCheckbox.isChecked; processCobCheckBox(); }
binding.iobEnabledIcon.setOnClickListener { if (!binding.cobCheckbox.isChecked) binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked } binding.iobCheckboxIcon.setOnClickListener { if (!binding.cobCheckbox.isChecked) binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked }
// cancel button // cancel button
binding.cancel.setOnClickListener { binding.okcancel.cancel.setOnClickListener {
aapsLogger.debug(LTag.APS, "Dialog canceled: ${this.javaClass.name}") aapsLogger.debug(LTag.APS, "Dialog canceled: ${this.javaClass.name}")
dismiss() dismiss()
} }
@ -212,11 +211,17 @@ class WizardDialog : DaggerDialogFragment() {
sp.putBoolean(rh.gs(R.string.key_wizard_correction_percent), isChecked) sp.putBoolean(rh.gs(R.string.key_wizard_correction_percent), isChecked)
binding.correctionUnit.text = if (isChecked) "%" else rh.gs(R.string.insulin_unit_shortname) binding.correctionUnit.text = if (isChecked) "%" else rh.gs(R.string.insulin_unit_shortname)
correctionPercent = binding.correctionPercent.isChecked correctionPercent = binding.correctionPercent.isChecked
if (correctionPercent) if (correctionPercent) {
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)
else binding.correctionInput.customContentDescription = rh.gs(R.string.a11_correction_percentage)
binding.correctionInput.setParams(savedInstanceState?.getDouble("correction_input") } else {
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.ok, textWatcher) 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) binding.correctionInput.value = if (correctionPercent) calculatedPercentage else Round.roundTo(calculatedCorrection, bolusStep)
} }
} }
@ -224,12 +229,12 @@ class WizardDialog : DaggerDialogFragment() {
binding.profile.onItemSelectedListener = object : OnItemSelectedListener { binding.profile.onItemSelectedListener = object : OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) { override fun onNothingSelected(parent: AdapterView<*>?) {
ToastUtils.showToastInUiThread(ctx, rh.gs(R.string.noprofileset)) 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) { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
calculateInsulin() calculateInsulin()
binding.ok.visibility = View.VISIBLE binding.okcancel.ok.visibility = View.VISIBLE
} }
} }
// bus // bus
@ -241,6 +246,14 @@ class WizardDialog : DaggerDialogFragment() {
}, fabricPrivacy::logException) }, 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() { override fun onDestroyView() {
@ -261,21 +274,29 @@ class WizardDialog : DaggerDialogFragment() {
private fun processCobCheckBox() { private fun processCobCheckBox() {
if (binding.cobCheckbox.isChecked) { if (binding.cobCheckbox.isChecked) {
binding.iobCheckbox.isEnabled = false binding.iobCheckbox.isEnabled = false
binding.iobCheckboxIcon.isEnabled = false
binding.iobCheckbox.isChecked = true binding.iobCheckbox.isChecked = true
} else { } else {
binding.iobCheckbox.isEnabled = true binding.iobCheckbox.isEnabled = true
binding.iobCheckboxIcon.isEnabled = true
} }
} }
private fun processEnabledIcons() { private fun processEnabledIcons() {
binding.bgEnabledIcon.alpha = if (binding.bgCheckbox.isChecked) 1.0f else 0.2f binding.bgCheckboxIcon.isChecked = binding.bgCheckbox.isChecked
binding.trendEnabledIcon.alpha = if (binding.bgTrendCheckbox.isChecked) 1.0f else 0.2f binding.trendCheckboxIcon.isChecked = binding.bgTrendCheckbox.isChecked
binding.iobEnabledIcon.alpha = if (binding.iobCheckbox.isChecked) 1.0f else 0.2f binding.iobCheckboxIcon.isChecked = binding.iobCheckbox.isChecked
binding.cobEnabledIcon.alpha = if (binding.cobCheckbox.isChecked) 1.0f else 0.2f binding.cobCheckboxIcon.isChecked = binding.cobCheckbox.isChecked
binding.bgEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.trendEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() binding.bgCheckboxIcon.alpha = if (binding.bgCheckbox.isChecked) 1.0f else 0.2f
binding.iobEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() binding.trendCheckboxIcon.alpha = if (binding.bgTrendCheckbox.isChecked) 1.0f else 0.2f
binding.cobEnabledIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() 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() { 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 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 "" 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.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 { } else {
binding.total.text = HtmlHelper.fromHtml(rh.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt()).formatColor(rh, R.color.carbs)) 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) binding.percentUsed.text = rh.gs(R.string.format_percent, wizard.percentageCorrection)
calculatedPercentage = wizard.calculatedPercentage calculatedPercentage = wizard.calculatedPercentage

View file

@ -69,13 +69,15 @@ class WizardInfoDialog : DaggerDialogFragment() {
binding.close.setOnClickListener { dismiss() } binding.close.setOnClickListener { dismiss() }
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
val bgString = Profile.toUnitsString(data.glucoseValue, data.glucoseValue * Constants.MGDL_TO_MMOLL, units) 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 // 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.bgInsulin.text = rh.gs(R.string.formatinsulinunits, data.glucoseInsulin)
binding.bgCheckbox.isChecked = data.wasGlucoseUsed binding.bgCheckbox.isChecked = data.wasGlucoseUsed
binding.ttCheckbox.isChecked = data.wasTempTargetUsed binding.ttCheckbox.isChecked = data.wasTempTargetUsed
// Trend // Trend
binding.bgTrend.text = DecimalFormatter.to1Decimal(data.glucoseTrend) binding.bgTrend.text = trend
binding.bgTrendInsulin.text = rh.gs(R.string.formatinsulinunits, data.trendInsulin) binding.bgTrendInsulin.text = rh.gs(R.string.formatinsulinunits, data.trendInsulin)
binding.bgTrendCheckbox.isChecked = data.wasTrendUsed binding.bgTrendCheckbox.isChecked = data.wasTrendUsed
// COB // COB

View file

@ -7,6 +7,7 @@ import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.extensions.convertedToAbsolute import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
import info.nightscout.androidaps.interfaces.GlucoseUnit import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.interfaces.Profile
@ -14,6 +15,7 @@ import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
@ -30,7 +32,7 @@ import java.nio.charset.StandardCharsets
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.min import kotlin.math.min
class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader, injector: HasAndroidInjector) { class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader, injector: HasAndroidInjector) : DetermineBasalAdapterInterface {
private val injector: HasAndroidInjector private val injector: HasAndroidInjector
@ -48,21 +50,15 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
private var currentTemp = JSONObject() private var currentTemp = JSONObject()
private var autosensData = JSONObject() private var autosensData = JSONObject()
var currentTempParam: String? = null override var currentTempParam: String? = null
private set override var iobDataParam: String? = null
var iobDataParam: String? = null override var glucoseStatusParam: String? = null
private set override var profileParam: String? = null
var glucoseStatusParam: String? = null override var mealDataParam: String? = null
private set override var scriptDebug = ""
var profileParam: String? = null
private set
var mealDataParam: String? = null
private set
var scriptDebug = ""
private set
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
operator fun invoke(): DetermineBasalResultAMA? { override operator fun invoke(): APSResult? {
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<") aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
aapsLogger.debug(LTag.APS, "Glucose status: " + glucoseStatus.toString().also { glucoseStatusParam = it }) aapsLogger.debug(LTag.APS, "Glucose status: " + glucoseStatus.toString().also { glucoseStatusParam = it })
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it }) aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
@ -143,18 +139,25 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
} }
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
@Throws(JSONException::class) fun setData(profile: Profile, @Throws(JSONException::class)
maxIob: Double, override fun setData(
maxBasal: Double, profile: Profile,
minBg: Double, maxIob: Double,
maxBg: Double, maxBasal: Double,
targetBg: Double, minBg: Double,
basalRate: Double, maxBg: Double,
iobArray: Array<IobTotal>, targetBg: Double,
glucoseStatus: GlucoseStatus, basalRate: Double,
mealData: MealData, iobArray: Array<IobTotal>,
autosensDataRatio: Double, glucoseStatus: GlucoseStatus,
tempTargetSet: Boolean) { mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
) {
this.profile = JSONObject() this.profile = JSONObject()
this.profile.put("max_iob", maxIob) this.profile.put("max_iob", maxIob)
this.profile.put("dia", min(profile.dia, 3.0)) this.profile.put("dia", min(profile.dia, 3.0))

View file

@ -96,7 +96,7 @@ class OpenAPSAMAFragment : DaggerFragment() {
binding.result.text = jsonFormatter.format(lastAPSResult.json) binding.result.text = jsonFormatter.format(lastAPSResult.json)
binding.request.text = lastAPSResult.toSpanned() binding.request.text = lastAPSResult.toSpanned()
} }
openAPSAMAPlugin.lastDetermineBasalAdapterAMAJS?.let { determineBasalAdapterAMAJS -> openAPSAMAPlugin.lastDetermineBasalAdapter?.let { determineBasalAdapterAMAJS ->
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam) binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam)
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterAMAJS.currentTempParam) binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterAMAJS.currentTempParam)
try { try {

View file

@ -60,8 +60,8 @@ class OpenAPSAMAPlugin @Inject constructor(
// last values // last values
override var lastAPSRun: Long = 0 override var lastAPSRun: Long = 0
override var lastAPSResult: DetermineBasalResultAMA? = null override var lastAPSResult: DetermineBasalResultAMA? = null
var lastDetermineBasalAdapterAMAJS: DetermineBasalAdapterAMAJS? = null override var lastDetermineBasalAdapter: DetermineBasalAdapterInterface? = null
var lastAutosensResult: AutosensResult = AutosensResult() override var lastAutosensResult: AutosensResult = AutosensResult()
override fun specialEnableCondition(): Boolean { override fun specialEnableCondition(): Boolean {
return try { return try {
@ -158,7 +158,7 @@ class OpenAPSAMAPlugin @Inject constructor(
// Fix bug determine basal // Fix bug determine basal
if (determineBasalResultAMA == null) { if (determineBasalResultAMA == null) {
aapsLogger.error(LTag.APS, "SMB calculation returned null") aapsLogger.error(LTag.APS, "SMB calculation returned null")
lastDetermineBasalAdapterAMAJS = null lastDetermineBasalAdapter = null
lastAPSResult = null lastAPSResult = null
lastAPSRun = 0 lastAPSRun = 0
} else { } else {
@ -167,8 +167,8 @@ class OpenAPSAMAPlugin @Inject constructor(
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
determineBasalResultAMA.json?.put("timestamp", dateUtil.toISOString(now)) determineBasalResultAMA.json?.put("timestamp", dateUtil.toISOString(now))
determineBasalResultAMA.inputConstraints = inputConstraints determineBasalResultAMA.inputConstraints = inputConstraints
lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS lastDetermineBasalAdapter = determineBasalAdapterAMAJS
lastAPSResult = determineBasalResultAMA lastAPSResult = determineBasalResultAMA as DetermineBasalResultAMA
lastAPSRun = now lastAPSRun = now
} }
rxBus.send(EventOpenAPSUpdateGui()) rxBus.send(EventOpenAPSUpdateGui())

View file

@ -7,14 +7,11 @@ import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.extensions.convertedToAbsolute import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
@ -31,7 +28,7 @@ import java.lang.reflect.InvocationTargetException
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import javax.inject.Inject import javax.inject.Inject
class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) { class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) : DetermineBasalAdapterInterface {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@ -51,21 +48,16 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
private var smbAlwaysAllowed = false private var smbAlwaysAllowed = false
private var currentTime: Long = 0 private var currentTime: Long = 0
private var saveCgmSource = false private var saveCgmSource = false
var currentTempParam: String? = null
private set override var currentTempParam: String? = null
var iobDataParam: String? = null override var iobDataParam: String? = null
private set override var glucoseStatusParam: String? = null
var glucoseStatusParam: String? = null override var profileParam: String? = null
private set override var mealDataParam: String? = null
var profileParam: String? = null override var scriptDebug = ""
private set
var mealDataParam: String? = null
private set
var scriptDebug = ""
private set
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
operator fun invoke(): DetermineBasalResultSMB? { override operator fun invoke(): APSResult? {
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<") aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it }) aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it })
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it }) aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
@ -155,22 +147,24 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
return determineBasalResultSMB return determineBasalResultSMB
} }
@Suppress("SpellCheckingInspection") fun setData(profile: Profile, @Suppress("SpellCheckingInspection")
maxIob: Double, override fun setData(
maxBasal: Double, profile: Profile,
minBg: Double, maxIob: Double,
maxBg: Double, maxBasal: Double,
targetBg: Double, minBg: Double,
basalRate: Double, maxBg: Double,
iobArray: Array<IobTotal>, targetBg: Double,
glucoseStatus: GlucoseStatus, basalRate: Double,
mealData: MealData, iobArray: Array<IobTotal>,
autosensDataRatio: Double, glucoseStatus: GlucoseStatus,
tempTargetSet: Boolean, mealData: MealData,
microBolusAllowed: Boolean, autosensDataRatio: Double,
uamAllowed: Boolean, tempTargetSet: Boolean,
advancedFiltering: Boolean, microBolusAllowed: Boolean,
isSaveCgmSource: Boolean uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
) { ) {
val pump = activePlugin.activePump val pump = activePlugin.activePump
val pumpBolusStep = pump.pumpDescription.bolusStep val pumpBolusStep = pump.pumpDescription.bolusStep

View file

@ -10,6 +10,7 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector)
private var eventualBG = 0.0 private var eventualBG = 0.0
private var snoozeBG = 0.0 private var snoozeBG = 0.0
var variableSens: Double? = null
internal constructor(injector: HasAndroidInjector, result: JSONObject) : this(injector) { internal constructor(injector: HasAndroidInjector, result: JSONObject) : this(injector) {
date = dateUtil.now() date = dateUtil.now()
@ -50,6 +51,7 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector)
aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e) aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e)
} }
} }
if (result.has("variable_sens")) variableSens = result.getDouble("variable_sens");
} catch (e: JSONException) { } catch (e: JSONException) {
aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e) aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e)
} }

View file

@ -9,8 +9,7 @@ import android.view.ViewGroup
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.databinding.OpenapsamaFragmentBinding import info.nightscout.androidaps.databinding.OpenapsamaFragmentBinding
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
@ -19,6 +18,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.JSONFormatter import info.nightscout.androidaps.utils.JSONFormatter
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONArray import org.json.JSONArray
@ -34,7 +35,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
@Inject lateinit var rxBus: RxBus @Inject lateinit var rxBus: RxBus
@Inject lateinit var rh: ResourceHelper @Inject lateinit var rh: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var jsonFormatter: JSONFormatter @Inject lateinit var jsonFormatter: JSONFormatter
@ -44,8 +45,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
// onDestroyView. // onDestroyView.
private val binding get() = _binding!! private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
savedInstanceState: Bundle?): View {
_binding = OpenapsamaFragmentBinding.inflate(inflater, container, false) _binding = OpenapsamaFragmentBinding.inflate(inflater, container, false)
return binding.root return binding.root
} }
@ -54,7 +54,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.run.setOnClickListener { binding.run.setOnClickListener {
openAPSSMBPlugin.invoke("OpenAPSSMB button", false) activePlugin.activeAPS.invoke("OpenAPSSMB button", false)
} }
} }
@ -92,11 +92,12 @@ class OpenAPSSMBFragment : DaggerFragment() {
@Synchronized @Synchronized
fun updateGUI() { fun updateGUI() {
if (_binding == null) return if (_binding == null) return
val openAPSSMBPlugin = activePlugin.activeAPS
openAPSSMBPlugin.lastAPSResult?.let { lastAPSResult -> openAPSSMBPlugin.lastAPSResult?.let { lastAPSResult ->
binding.result.text = jsonFormatter.format(lastAPSResult.json) binding.result.text = jsonFormatter.format(lastAPSResult.json)
binding.request.text = lastAPSResult.toSpanned() binding.request.text = lastAPSResult.toSpanned()
} }
openAPSSMBPlugin.lastDetermineBasalAdapterSMBJS?.let { determineBasalAdapterSMBJS -> openAPSSMBPlugin.lastDetermineBasalAdapter?.let { determineBasalAdapterSMBJS ->
binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam) binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam)
binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterSMBJS.currentTempParam) binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterSMBJS.currentTempParam)
try { try {

View file

@ -10,8 +10,6 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.extensions.target import info.nightscout.androidaps.extensions.target
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
@ -24,6 +22,8 @@ import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -37,7 +37,7 @@ class OpenAPSSMBPlugin @Inject constructor(
private val constraintChecker: ConstraintChecker, private val constraintChecker: ConstraintChecker,
rh: ResourceHelper, rh: ResourceHelper,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val context: Context, val context: Context,
private val activePlugin: ActivePlugin, private val activePlugin: ActivePlugin,
private val iobCobCalculator: IobCobCalculator, private val iobCobCalculator: IobCobCalculator,
private val hardLimits: HardLimits, private val hardLimits: HardLimits,
@ -46,23 +46,24 @@ class OpenAPSSMBPlugin @Inject constructor(
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val repository: AppRepository, private val repository: AppRepository,
private val glucoseStatusProvider: GlucoseStatusProvider private val glucoseStatusProvider: GlucoseStatusProvider
) : PluginBase(PluginDescription() ) : PluginBase(
.mainType(PluginType.APS) PluginDescription()
.fragmentClass(OpenAPSSMBFragment::class.java.name) .mainType(PluginType.APS)
.pluginIcon(R.drawable.ic_generic_icon) .fragmentClass(OpenAPSSMBFragment::class.java.name)
.pluginName(R.string.openapssmb) .pluginIcon(R.drawable.ic_generic_icon)
.shortName(R.string.smb_shortname) .pluginName(R.string.openapssmb)
.preferencesId(R.xml.pref_openapssmb) .shortName(R.string.smb_shortname)
.description(R.string.description_smb) .preferencesId(R.xml.pref_openapssmb)
.setDefault(), .description(R.string.description_smb)
.setDefault(),
aapsLogger, rh, injector aapsLogger, rh, injector
), APS, Constraints { ), APS, Constraints {
// last values // last values
override var lastAPSRun: Long = 0 override var lastAPSRun: Long = 0
override var lastAPSResult: DetermineBasalResultSMB? = null override var lastAPSResult: DetermineBasalResultSMB? = null
var lastDetermineBasalAdapterSMBJS: DetermineBasalAdapterSMBJS? = null override var lastDetermineBasalAdapter: DetermineBasalAdapterInterface? = null
var lastAutosensResult = AutosensResult() override var lastAutosensResult = AutosensResult()
override fun specialEnableCondition(): Boolean { override fun specialEnableCondition(): Boolean {
return try { return try {
@ -120,15 +121,34 @@ class OpenAPSSMBPlugin @Inject constructor(
}.value() }.value()
var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetLowMgdl(), 0.1), R.string.profile_low_target, HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]) var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetLowMgdl(), 0.1), R.string.profile_low_target, HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1])
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetHighMgdl(), 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]) var maxBg =
hardLimits.verifyHardLimits(Round.roundTo(profile.getTargetHighMgdl(), 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1])
var targetBg = hardLimits.verifyHardLimits(profile.getTargetMgdl(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1]) var targetBg = hardLimits.verifyHardLimits(profile.getTargetMgdl(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1])
var isTempTarget = false var isTempTarget = false
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) { if (tempTarget is ValueWrapper.Existing) {
isTempTarget = true isTempTarget = true
minBg = hardLimits.verifyHardLimits(tempTarget.value.lowTarget, R.string.temp_target_low_target, HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble()) minBg =
maxBg = hardLimits.verifyHardLimits(tempTarget.value.highTarget, R.string.temp_target_high_target, HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble()) hardLimits.verifyHardLimits(
targetBg = hardLimits.verifyHardLimits(tempTarget.value.target(), R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble()) tempTarget.value.lowTarget,
R.string.temp_target_low_target,
HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(),
HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble()
)
maxBg =
hardLimits.verifyHardLimits(
tempTarget.value.highTarget,
R.string.temp_target_high_target,
HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(),
HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble()
)
targetBg =
hardLimits.verifyHardLimits(
tempTarget.value.target(),
R.string.temp_target_value,
HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(),
HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble()
)
} }
if (!hardLimits.checkHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return if (!hardLimits.checkHardLimits(profile.dia, R.string.profile_dia, hardLimits.minDia(), hardLimits.maxDia())) return
if (!hardLimits.checkHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return if (!hardLimits.checkHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), R.string.profile_carbs_ratio_value, hardLimits.minIC(), hardLimits.maxIC())) return
@ -165,8 +185,9 @@ class OpenAPSSMBPlugin @Inject constructor(
profiler.log(LTag.APS, "SMB data gathering", start) profiler.log(LTag.APS, "SMB data gathering", start)
start = System.currentTimeMillis() start = System.currentTimeMillis()
DetermineBasalAdapterSMBJS(ScriptReader(context), injector).also { determineBasalAdapterSMBJS -> provideDetermineBasalAdapter().also { determineBasalAdapterSMBJS ->
determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, determineBasalAdapterSMBJS.setData(
profile, maxIob, maxBasal, minBg, maxBg, targetBg,
activePlugin.activePump.baseBasalRate, activePlugin.activePump.baseBasalRate,
iobArray, iobArray,
glucoseStatus, glucoseStatus,
@ -176,24 +197,26 @@ class OpenAPSSMBPlugin @Inject constructor(
smbAllowed.value(), smbAllowed.value(),
uam.value(), uam.value(),
advancedFiltering.value(), advancedFiltering.value(),
activePlugin.activeBgSource.javaClass.simpleName == "DexcomPlugin") activePlugin.activeBgSource.javaClass.simpleName == "DexcomPlugin"
)
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
val determineBasalResultSMB = determineBasalAdapterSMBJS.invoke() val determineBasalResultSMB = determineBasalAdapterSMBJS.invoke()
profiler.log(LTag.APS, "SMB calculation", start) profiler.log(LTag.APS, "SMB calculation", start)
if (determineBasalResultSMB == null) { if (determineBasalResultSMB == null) {
aapsLogger.error(LTag.APS, "SMB calculation returned null") aapsLogger.error(LTag.APS, "SMB calculation returned null")
lastDetermineBasalAdapterSMBJS = null lastDetermineBasalAdapter = null
lastAPSResult = null lastAPSResult = null
lastAPSRun = 0 lastAPSRun = 0
} else { } else {
// TODO still needed with oref1? // TODO still needed with oref1?
// Fix bug determine basal // Fix bug determine basal
if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) == null) determineBasalResultSMB.tempBasalRequested = false if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) == null) determineBasalResultSMB.tempBasalRequested =
false
determineBasalResultSMB.iob = iobArray[0] determineBasalResultSMB.iob = iobArray[0]
determineBasalResultSMB.json?.put("timestamp", dateUtil.toISOString(now)) determineBasalResultSMB.json?.put("timestamp", dateUtil.toISOString(now))
determineBasalResultSMB.inputConstraints = inputConstraints determineBasalResultSMB.inputConstraints = inputConstraints
lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS lastDetermineBasalAdapter = determineBasalAdapterSMBJS
lastAPSResult = determineBasalResultSMB lastAPSResult = determineBasalResultSMB as DetermineBasalResultSMB
lastAPSRun = now lastAPSRun = now
} }
} }
@ -204,4 +227,6 @@ class OpenAPSSMBPlugin @Inject constructor(
value.set(aapsLogger, false) value.set(aapsLogger, false)
return value return value
} }
fun provideDetermineBasalAdapter(): DetermineBasalAdapterInterface = DetermineBasalAdapterSMBJS(ScriptReader(context), injector)
} }

View file

@ -0,0 +1,296 @@
package info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.shared.SafeParse
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import org.mozilla.javascript.*
import org.mozilla.javascript.Function
import java.io.IOException
import java.lang.reflect.InvocationTargetException
import java.nio.charset.StandardCharsets
import javax.inject.Inject
class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) : DetermineBasalAdapterInterface {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var sp: SP
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var tddCalculator: TddCalculator
private var profile = JSONObject()
private var mGlucoseStatus = JSONObject()
private var iobData: JSONArray? = null
private var mealData = JSONObject()
private var currentTemp = JSONObject()
private var autosensData = JSONObject()
private var microBolusAllowed = false
private var smbAlwaysAllowed = false
private var currentTime: Long = 0
private var saveCgmSource = false
override var currentTempParam: String? = null
override var iobDataParam: String? = null
override var glucoseStatusParam: String? = null
override var profileParam: String? = null
override var mealDataParam: String? = null
override var scriptDebug = ""
@Suppress("SpellCheckingInspection")
override operator fun invoke(): DetermineBasalResultSMB? {
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it })
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
aapsLogger.debug(LTag.APS, "Current temp: " + currentTemp.toString().also { currentTempParam = it })
aapsLogger.debug(LTag.APS, "Profile: " + profile.toString().also { profileParam = it })
aapsLogger.debug(LTag.APS, "Meal data: " + mealData.toString().also { mealDataParam = it })
aapsLogger.debug(LTag.APS, "Autosens data: $autosensData")
aapsLogger.debug(LTag.APS, "Reservoir data: " + "undefined")
aapsLogger.debug(LTag.APS, "MicroBolusAllowed: $microBolusAllowed")
aapsLogger.debug(LTag.APS, "SMBAlwaysAllowed: $smbAlwaysAllowed")
aapsLogger.debug(LTag.APS, "CurrentTime: $currentTime")
aapsLogger.debug(LTag.APS, "isSaveCgmSource: $saveCgmSource")
var determineBasalResultSMB: DetermineBasalResultSMB? = null
val rhino = Context.enter()
val scope: Scriptable = rhino.initStandardObjects()
// Turn off optimization to make Rhino Android compatible
rhino.optimizationLevel = -1
try {
//register logger callback for console.log and console.error
ScriptableObject.defineClass(scope, LoggerCallback::class.java)
val myLogger = rhino.newObject(scope, "LoggerCallback", null)
scope.put("console2", scope, myLogger)
rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null)
//set module parent
rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null)
rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null)
rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null)
//generate functions "determine_basal" and "setTempBasal"
rhino.evaluateString(scope, readFile("OpenAPSSMBDynamicISF/determine-basal.js"), "JavaScript", 0, null)
rhino.evaluateString(scope, readFile("OpenAPSSMB/basal-set-temp.js"), "setTempBasal.js", 0, null)
val determineBasalObj = scope["determine_basal", scope]
val setTempBasalFunctionsObj = scope["tempBasalFunctions", scope]
//call determine-basal
if (determineBasalObj is Function && setTempBasalFunctionsObj is NativeObject) {
//prepare parameters
val params = arrayOf(
makeParam(mGlucoseStatus, rhino, scope),
makeParam(currentTemp, rhino, scope),
makeParamArray(iobData, rhino, scope),
makeParam(profile, rhino, scope),
makeParam(autosensData, rhino, scope),
makeParam(mealData, rhino, scope),
setTempBasalFunctionsObj,
java.lang.Boolean.valueOf(microBolusAllowed),
makeParam(null, rhino, scope), // reservoir data as undefined
java.lang.Long.valueOf(currentTime),
java.lang.Boolean.valueOf(saveCgmSource)
)
val jsResult = determineBasalObj.call(rhino, scope, scope, params) as NativeObject
scriptDebug = LoggerCallback.scriptDebug
// Parse the jsResult object to a JSON-String
val result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString()
aapsLogger.debug(LTag.APS, "Result: $result")
try {
val resultJson = JSONObject(result)
determineBasalResultSMB = DetermineBasalResultSMB(injector, resultJson)
} catch (e: JSONException) {
aapsLogger.error(LTag.APS, "Unhandled exception", e)
}
} else {
aapsLogger.error(LTag.APS, "Problem loading JS Functions")
}
} catch (e: IOException) {
aapsLogger.error(LTag.APS, "IOException")
} catch (e: RhinoException) {
aapsLogger.error(LTag.APS, "RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString())
} catch (e: IllegalAccessException) {
aapsLogger.error(LTag.APS, e.toString())
} catch (e: InstantiationException) {
aapsLogger.error(LTag.APS, e.toString())
} catch (e: InvocationTargetException) {
aapsLogger.error(LTag.APS, e.toString())
} finally {
Context.exit()
}
glucoseStatusParam = mGlucoseStatus.toString()
iobDataParam = iobData.toString()
currentTempParam = currentTemp.toString()
profileParam = profile.toString()
mealDataParam = mealData.toString()
return determineBasalResultSMB
}
@Suppress("SpellCheckingInspection")
override fun setData(
profile: Profile,
maxIob: Double,
maxBasal: Double,
minBg: Double,
maxBg: Double,
targetBg: Double,
basalRate: Double,
iobArray: Array<IobTotal>,
glucoseStatus: GlucoseStatus,
mealData: MealData,
autosensDataRatio: Double,
tempTargetSet: Boolean,
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
isSaveCgmSource: Boolean
) {
val pump = activePlugin.activePump
val pumpBolusStep = pump.pumpDescription.bolusStep
this.profile.put("max_iob", maxIob)
//mProfile.put("dia", profile.getDia());
this.profile.put("type", "current")
this.profile.put("max_daily_basal", profile.getMaxDailyBasal())
this.profile.put("max_basal", maxBasal)
this.profile.put("min_bg", minBg)
this.profile.put("max_bg", maxBg)
this.profile.put("target_bg", targetBg)
this.profile.put("carb_ratio", profile.getIc())
this.profile.put("sens", profile.getIsfMgdl())
this.profile.put("max_daily_safety_multiplier", sp.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3))
this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0))
//mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
this.profile.put("high_temptarget_raises_sensitivity", false)
//mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
this.profile.put("low_temptarget_lowers_sensitivity", false)
this.profile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target, SMBDefaults.sensitivity_raises_target))
this.profile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target, SMBDefaults.resistance_lowers_target))
this.profile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments)
this.profile.put("exercise_mode", SMBDefaults.exercise_mode)
this.profile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target)
this.profile.put("maxCOB", SMBDefaults.maxCOB)
this.profile.put("skip_neutral_temps", pump.setNeutralTempAtFullHour())
// min_5m_carbimpact is not used within SMB determinebasal
//if (mealData.usedMinCarbsImpact > 0) {
// mProfile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact);
//} else {
// mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
//}
this.profile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap)
this.profile.put("enableUAM", uamAllowed)
this.profile.put("A52_risk_enable", SMBDefaults.A52_risk_enable)
val smbEnabled = sp.getBoolean(R.string.key_use_smb, false)
this.profile.put("SMBInterval", sp.getInt(R.string.key_smbinterval, SMBDefaults.SMBInterval))
this.profile.put("enableSMB_with_COB", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_COB, false))
this.profile.put("enableSMB_with_temptarget", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_temptarget, false))
this.profile.put("allowSMB_with_high_temptarget", smbEnabled && sp.getBoolean(R.string.key_allowSMB_with_high_temptarget, false))
this.profile.put("enableSMB_always", smbEnabled && sp.getBoolean(R.string.key_enableSMB_always, false) && advancedFiltering)
this.profile.put("enableSMB_after_carbs", smbEnabled && sp.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering)
this.profile.put("maxSMBBasalMinutes", sp.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes))
this.profile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes))
//set the min SMB amount to be the amount set by the pump.
this.profile.put("bolus_increment", pumpBolusStep)
this.profile.put("carbsReqThreshold", sp.getInt(R.string.key_carbsReqThreshold, SMBDefaults.carbsReqThreshold))
this.profile.put("current_basal", basalRate)
this.profile.put("temptargetSet", tempTargetSet)
this.profile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2")))
if (profileFunction.getUnits() == GlucoseUnit.MMOL) {
this.profile.put("out_units", "mmol/L")
}
val now = System.currentTimeMillis()
val tb = iobCobCalculator.getTempBasalIncludingConvertedExtended(now)
currentTemp.put("temp", "absolute")
currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0)
currentTemp.put("rate", tb?.convertedToAbsolute(now, profile) ?: 0.0)
// as we have non default temps longer than 30 mintues
if (tb != null) currentTemp.put("minutesrunning", tb.getPassedDurationToTimeInMinutes(now))
iobData = iobCobCalculator.convertToJSONArray(iobArray)
mGlucoseStatus.put("glucose", glucoseStatus.glucose)
mGlucoseStatus.put("noise", glucoseStatus.noise)
if (sp.getBoolean(R.string.key_always_use_shortavg, false)) {
mGlucoseStatus.put("delta", glucoseStatus.shortAvgDelta)
} else {
mGlucoseStatus.put("delta", glucoseStatus.delta)
}
mGlucoseStatus.put("short_avgdelta", glucoseStatus.shortAvgDelta)
mGlucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta)
mGlucoseStatus.put("date", glucoseStatus.date)
this.mealData.put("carbs", mealData.carbs)
this.mealData.put("mealCOB", mealData.mealCOB)
this.mealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation)
this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation)
this.mealData.put("lastBolusTime", mealData.lastBolusTime)
this.mealData.put("lastCarbTime", mealData.lastCarbTime)
this.mealData.put("TDDAIMI7", tddCalculator.averageTDD(tddCalculator.calculate(7)).totalAmount)
this.mealData.put("TDDPUMP", tddCalculator.calculateDaily().totalAmount)
if (constraintChecker.isAutosensModeEnabled().value()) {
autosensData.put("ratio", autosensDataRatio)
} else {
autosensData.put("ratio", 1.0)
}
this.microBolusAllowed = microBolusAllowed
smbAlwaysAllowed = advancedFiltering
currentTime = now
saveCgmSource = isSaveCgmSource
}
private fun makeParam(jsonObject: JSONObject?, rhino: Context, scope: Scriptable): Any {
return if (jsonObject == null) Undefined.instance
else NativeJSON.parse(rhino, scope, jsonObject.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
}
private fun makeParamArray(jsonArray: JSONArray?, rhino: Context, scope: Scriptable): Any {
return NativeJSON.parse(rhino, scope, jsonArray.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
}
@Throws(IOException::class) private fun readFile(filename: String): String {
val bytes = scriptReader.readFile(filename)
var string = String(bytes, StandardCharsets.UTF_8)
if (string.startsWith("#!/usr/bin/env node")) {
string = string.substring(20)
}
return string
}
init {
injector.androidInjector().inject(this)
}
}

View file

@ -0,0 +1,74 @@
package info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF
import android.content.Context
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.annotations.OpenForTesting
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.interfaces.DetermineBasalAdapterInterface
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject
import javax.inject.Singleton
@OpenForTesting
@Singleton
class OpenAPSSMBDynamicISFPlugin @Inject constructor(
injector: HasAndroidInjector,
aapsLogger: AAPSLogger,
rxBus: RxBus,
constraintChecker: ConstraintChecker,
rh: ResourceHelper,
profileFunction: ProfileFunction,
context: Context,
activePlugin: ActivePlugin,
iobCobCalculator: IobCobCalculator,
hardLimits: HardLimits,
profiler: Profiler,
sp: SP,
dateUtil: DateUtil,
repository: AppRepository,
glucoseStatusProvider: GlucoseStatusProvider,
private val buildHelper: BuildHelper
) : OpenAPSSMBPlugin(
injector,
aapsLogger,
rxBus,
constraintChecker,
rh,
profileFunction,
context,
activePlugin,
iobCobCalculator,
hardLimits,
profiler,
sp,
dateUtil,
repository,
glucoseStatusProvider
) {
init {
pluginDescription
.pluginName(R.string.openaps_smb_dynamic_isf)
.description(R.string.description_smb_dynamic_isf)
.setDefault(false)
}
override fun specialEnableCondition(): Boolean = buildHelper.isEngineeringMode() && buildHelper.isDev()
override fun provideDetermineBasalAdapter(): DetermineBasalAdapterInterface = DetermineBasalAdapterSMBDynamicISFJS(ScriptReader(context), injector)
}

View file

@ -102,4 +102,11 @@ class BgQualityCheckPlugin @Inject constructor(
State.RECALCULATED -> R.drawable.ic_baseline_warning_24_yellow State.RECALCULATED -> R.drawable.ic_baseline_warning_24_yellow
State.DOUBLED -> R.drawable.ic_baseline_warning_24_red 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 -> ""
}
} }

View file

@ -107,6 +107,7 @@ class ActionsFragment : DaggerFragment() {
private var sensorLevelLabel: TextView? = null private var sensorLevelLabel: TextView? = null
private var insulinLevelLabel: TextView? = null private var insulinLevelLabel: TextView? = null
private var pbLevelLabel: TextView? = null private var pbLevelLabel: TextView? = null
private var cannulaOrPatch: TextView? = null
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
@ -153,6 +154,7 @@ class ActionsFragment : DaggerFragment() {
sensorLevelLabel = view.findViewById(R.id.sensor_level_label) sensorLevelLabel = view.findViewById(R.id.sensor_level_label)
insulinLevelLabel = view.findViewById(R.id.insulin_level_label) insulinLevelLabel = view.findViewById(R.id.insulin_level_label)
pbLevelLabel = view.findViewById(R.id.pb_level_label) pbLevelLabel = view.findViewById(R.id.pb_level_label)
cannulaOrPatch = view.findViewById(R.id.cannula_or_patch)
profileSwitch?.setOnClickListener { profileSwitch?.setOnClickListener {
ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog") ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog")
@ -319,6 +321,10 @@ class ActionsFragment : DaggerFragment() {
tempTarget?.visibility = (profile != null && !loop.isDisconnected).toVisibility() tempTarget?.visibility = (profile != null && !loop.isDisconnected).toVisibility()
tddStats?.visibility = pump.pumpDescription.supportsTDDs.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) { if (!config.NSCLIENT) {
statusLightHandler.updateStatusLights(cannulaAge, insulinAge, reservoirLevel, sensorAge, sensorLevel, pbAge, batteryLevel) statusLightHandler.updateStatusLights(cannulaAge, insulinAge, reservoirLevel, sensorAge, sensorLevel, pbAge, batteryLevel)
sensorLevelLabel?.text = if (activeBgSource.sensorBatteryLevel == -1) "" else rh.gs(R.string.careportal_level_label) sensorLevelLabel?.text = if (activeBgSource.sensorBatteryLevel == -1) "" else rh.gs(R.string.careportal_level_label)

View file

@ -128,14 +128,29 @@ class OverviewData @Inject constructor(
var lastBg: GlucoseValue? = null var lastBg: GlucoseValue? = null
val lastBgColor: Int val isLow: Boolean
get() = lastBg?.let { lastBg -> get() = lastBg?.let { lastBg ->
when { lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine()
lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine() -> rh.gc(R.color.low) } ?: false
lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine() -> rh.gc(R.color.high)
else -> rh.gc(R.color.inrange) val isHigh: Boolean
} get() = lastBg?.let { lastBg ->
} ?: rh.gc(R.color.inrange) 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 val isActualBg: Boolean
get() = get() =

View file

@ -8,6 +8,7 @@ import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.graphics.Paint import android.graphics.Paint
import android.graphics.drawable.AnimationDrawable import android.graphics.drawable.AnimationDrawable
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.HandlerThread import android.os.HandlerThread
@ -47,6 +48,7 @@ import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin import info.nightscout.androidaps.plugins.constraints.bgQualityCheck.BgQualityCheckPlugin
@ -416,7 +418,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
OKDialog.showConfirmation(activity, rh.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned() OKDialog.showConfirmation(activity, rh.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned()
?: "".toSpanned(), { ?: "".toSpanned(), {
uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview) 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")) rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
Thread { loop.acceptChangeRequest() }.run() Thread { loop.acceptChangeRequest() }.run()
binding.buttonsLayout.acceptTempButton.visibility = View.GONE binding.buttonsLayout.acceptTempButton.visibility = View.GONE
@ -597,24 +599,36 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// aps mode // aps mode
val closedLoopEnabled = constraintChecker.isClosedLoopAllowed() 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) { if (config.APS && pump.pumpDescription.isTempBasalCapable) {
binding.infoLayout.apsMode.visibility = View.VISIBLE binding.infoLayout.apsMode.visibility = View.VISIBLE
binding.infoLayout.timeLayout.visibility = View.GONE binding.infoLayout.timeLayout.visibility = View.GONE
when { when {
(loop as PluginBase).isEnabled() && loop.isSuperBolus -> { (loop as PluginBase).isEnabled() && loop.isSuperBolus -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_superbolus) 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.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE binding.infoLayout.apsModeText.visibility = View.VISIBLE
} }
loop.isDisconnected -> { loop.isDisconnected -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disconnected) 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.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE binding.infoLayout.apsModeText.visibility = View.VISIBLE
} }
(loop as PluginBase).isEnabled() && loop.isSuspended -> { (loop as PluginBase).isEnabled() && loop.isSuspended -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_paused) 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.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE binding.infoLayout.apsModeText.visibility = View.VISIBLE
} }
@ -624,8 +638,10 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) { if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) {
// For Omnipod, indicate the pump as disconnected when it's suspended. // For Omnipod, indicate the pump as disconnected when it's suspended.
// The only way to 'reconnect' it, is through the Omnipod tab // The only way to 'reconnect' it, is through the Omnipod tab
apsModeSetA11yLabel(R.string.disconnected)
R.drawable.ic_loop_disconnected R.drawable.ic_loop_disconnected
} else { } else {
apsModeSetA11yLabel(R.string.pump_paused)
R.drawable.ic_loop_paused R.drawable.ic_loop_paused
} }
) )
@ -634,24 +650,43 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() && loop.isLGS -> { (loop as PluginBase).isEnabled() && closedLoopEnabled.value() && loop.isLGS -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_lgs) binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_lgs)
apsModeSetA11yLabel(R.string.uel_lgs_loop_mode)
binding.infoLayout.apsModeText.visibility = View.GONE binding.infoLayout.apsModeText.visibility = View.GONE
} }
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() -> { (loop as PluginBase).isEnabled() && closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_closed) binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_closed)
apsModeSetA11yLabel(R.string.closedloop)
binding.infoLayout.apsModeText.visibility = View.GONE binding.infoLayout.apsModeText.visibility = View.GONE
} }
(loop as PluginBase).isEnabled() && !closedLoopEnabled.value() -> { (loop as PluginBase).isEnabled() && !closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_open) binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_open)
apsModeSetA11yLabel(R.string.openloop)
binding.infoLayout.apsModeText.visibility = View.GONE binding.infoLayout.apsModeText.visibility = View.GONE
} }
else -> { else -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disabled) binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disabled)
apsModeSetA11yLabel(R.string.disabledloop)
binding.infoLayout.apsModeText.visibility = View.GONE binding.infoLayout.apsModeText.visibility = View.GONE
} }
} }
// Show variable sensitivity
val request = loop.lastRun?.request
if (request is DetermineBasalResultSMB) {
val isfMgdl = profileFunction.getProfile()?.getIsfMgdl()
val variableSens = request.variableSens
if (variableSens != isfMgdl && variableSens != null && isfMgdl != null) {
binding.infoLayout.variableSensitivity.text =
String.format(
Locale.getDefault(), "%1$.1f→%2$.1f",
Profile.toUnits(isfMgdl, isfMgdl * Constants.MGDL_TO_MMOLL, profileFunction.getUnits()),
Profile.toUnits(variableSens, variableSens * Constants.MGDL_TO_MMOLL, profileFunction.getUnits())
)
binding.infoLayout.variableSensitivity.visibility = View.VISIBLE
} else binding.infoLayout.variableSensitivity.visibility = View.GONE
} else binding.infoLayout.variableSensitivity.visibility = View.GONE
} else { } else {
//nsclient //nsclient
binding.infoLayout.apsMode.visibility = View.GONE binding.infoLayout.apsMode.visibility = View.GONE
@ -732,6 +767,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
binding.infoLayout.bg.setTextColor(overviewData.lastBgColor) binding.infoLayout.bg.setTextColor(overviewData.lastBgColor)
binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon()) binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor) 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 val glucoseStatus = glucoseStatusProvider.glucoseStatusData
if (glucoseStatus != null) { if (glucoseStatus != null) {
@ -751,13 +787,20 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
binding.infoLayout.bg.paintFlags = binding.infoLayout.bg.paintFlags =
if (!overviewData.isActualBg) binding.infoLayout.bg.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG 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() 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.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) + ")" binding.infoLayout.timeAgoShort.text = "(" + dateUtil.minAgoShort(overviewData.lastBg?.timestamp) + ")"
val qualityIcon = bgQualityCheckPlugin.icon() val qualityIcon = bgQualityCheckPlugin.icon()
if (qualityIcon != 0) { if (qualityIcon != 0) {
binding.infoLayout.bgQuality.visibility = View.VISIBLE binding.infoLayout.bgQuality.visibility = View.VISIBLE
binding.infoLayout.bgQuality.setImageResource(qualityIcon) binding.infoLayout.bgQuality.setImageResource(qualityIcon)
binding.infoLayout.bgQuality.contentDescription = rh.gs(R.string.a11y_bg_quality) + " " + bgQualityCheckPlugin.stateDescription()
binding.infoLayout.bgQuality.setOnClickListener { binding.infoLayout.bgQuality.setOnClickListener {
context?.let { context -> OKDialog.show(context, rh.gs(R.string.data_status), bgQualityCheckPlugin.message) } context?.let { context -> OKDialog.show(context, rh.gs(R.string.data_status), bgQualityCheckPlugin.message) }
} }
@ -823,7 +866,15 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
fun updateTime(from: String) { fun updateTime(from: String) {
binding.infoLayout.time.text = dateUtil.timeString(dateUtil.now()) binding.infoLayout.time.text = dateUtil.timeString(dateUtil.now())
// Status lights // 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( statusLightHandler.updateStatusLights(
binding.statusLightsLayout.cannulaAge, binding.statusLightsLayout.cannulaAge,
binding.statusLightsLayout.insulinAge, binding.statusLightsLayout.insulinAge,

View file

@ -40,12 +40,7 @@ class StatusLightHandler @Inject constructor(
val pump = activePlugin.activePump val pump = activePlugin.activePump
val bgSource = activePlugin.activeBgSource 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) 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) { handleAge(careportal_insulin_age, TherapyEvent.Type.INSULIN_CHANGE, R.string.key_statuslights_iage_warning, 72.0, R.string.key_statuslights_iage_critical, 144.0)
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_sensor_age, TherapyEvent.Type.SENSOR_CHANGE, R.string.key_statuslights_sage_warning, 216.0, R.string.key_statuslights_sage_critical, 240.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)) { 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) 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)

View file

@ -1,12 +1,18 @@
package info.nightscout.androidaps.plugins.general.overview.activities package info.nightscout.androidaps.plugins.general.overview.activities
import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.ItemTouchHelper.*
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import info.nightscout.androidaps.R 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.plugins.general.overview.events.EventQuickWizardChange
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.rxjava3.kotlin.plusAssign
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.wizard.QuickWizard import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject import javax.inject.Inject
class QuickWizardListActivity : NoSplashAppCompatActivity() { class QuickWizardListActivity : NoSplashAppCompatActivity() {
@ -30,20 +38,95 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var quickWizard: QuickWizard @Inject lateinit var quickWizard: QuickWizard
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var sp: SP
private var disposable: CompositeDisposable = CompositeDisposable() private var disposable: CompositeDisposable = CompositeDisposable()
private lateinit var binding: OverviewQuickwizardlistActivityBinding 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<RecyclerViewAdapter.QuickWizardEntryViewHolder>() { private inner class RecyclerViewAdapter(var fragmentManager: FragmentManager) : RecyclerView.Adapter<RecyclerViewAdapter.QuickWizardEntryViewHolder>() {
@SuppressLint("ClickableViewAccessibility")
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickWizardEntryViewHolder { 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) { override fun onBindViewHolder(holder: QuickWizardEntryViewHolder, position: Int) {
holder.from.text = dateUtil.timeString(quickWizard[position].validFromDate()) holder.from.text = dateUtil.timeString(quickWizard[position].validFromDate())
holder.to.text = dateUtil.timeString(quickWizard[position].validToDate()) 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.buttonText.text = quickWizard[position].buttonText()
holder.carbs.text = rh.gs(R.string.format_carbs, quickWizard[position].carbs()) 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 buttonText: TextView = itemView.findViewById(R.id.overview_quickwizard_item_buttonText)
val carbs: TextView = itemView.findViewById(R.id.overview_quickwizard_item_carbs) val carbs: TextView = itemView.findViewById(R.id.overview_quickwizard_item_carbs)
val from: TextView = itemView.findViewById(R.id.overview_quickwizard_item_from) 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) 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 editButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_edit_button)
private val removeButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_remove_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?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -84,6 +179,7 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
binding.recyclerview.setHasFixedSize(true) binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(this) binding.recyclerview.layoutManager = LinearLayoutManager(this)
binding.recyclerview.adapter = RecyclerViewAdapter(supportFragmentManager) binding.recyclerview.adapter = RecyclerViewAdapter(supportFragmentManager)
itemTouchHelper.attachToRecyclerView(binding.recyclerview)
binding.addButton.setOnClickListener { binding.addButton.setOnClickListener {
val manager = supportFragmentManager val manager = supportFragmentManager
@ -98,13 +194,13 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
.toObservable(EventQuickWizardChange::class.java) .toObservable(EventQuickWizardChange::class.java)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
.subscribe({ .subscribe({
val adapter = RecyclerViewAdapter(supportFragmentManager) val adapter = RecyclerViewAdapter(supportFragmentManager)
binding.recyclerview.swapAdapter(adapter, false) binding.recyclerview.swapAdapter(adapter, false)
}, fabricPrivacy::logException) }, fabricPrivacy::logException)
} }
override fun onPause() { override fun onPause() {
disposable.clear() disposable.clear()
super.onPause() super.onPause()
} }
} }

View file

@ -9,6 +9,7 @@ import android.view.ViewGroup
import android.view.Window import android.view.Window
import android.view.WindowManager import android.view.WindowManager
import dagger.android.support.DaggerDialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.databinding.OverviewEditquickwizardDialogBinding import info.nightscout.androidaps.databinding.OverviewEditquickwizardDialogBinding
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBus 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.extensions.setSelection
import info.nightscout.androidaps.utils.wizard.QuickWizard import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONException import org.json.JSONException
import javax.inject.Inject import javax.inject.Inject
@ -30,9 +32,9 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var quickWizard: QuickWizard @Inject lateinit var quickWizard: QuickWizard
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var sp: SP
var position = -1 var position = -1
var fromSeconds: Int = 0 var fromSeconds: Int = 0
var toSeconds: Int = 0 var toSeconds: Int = 0
@ -42,8 +44,10 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
// onDestroyView. // onDestroyView.
private val binding get() = _binding!! private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, override fun onCreateView(
savedInstanceState: Bundle?): View { inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE) dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = true isCancelable = true
@ -57,6 +61,14 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
position = bundle.getInt("position", -1) position = bundle.getInt("position", -1)
} }
val entry = if (position == -1) quickWizard.newEmptyItem() else quickWizard[position] 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 { binding.okcancel.ok.setOnClickListener {
try { try {
entry.storage.put("buttonText", binding.buttonEdit.text.toString()) 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("useBG", binding.useBg.selectedItemPosition)
entry.storage.put("useCOB", binding.useCob.selectedItemPosition) entry.storage.put("useCOB", binding.useCob.selectedItemPosition)
entry.storage.put("useBolusIOB", binding.useBolusIob.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("useBasalIOB", binding.useBasalIob.selectedItemPosition)
entry.storage.put("useTrend", binding.useTrend.selectedItemPosition) entry.storage.put("useTrend", binding.useTrend.selectedItemPosition)
entry.storage.put("useSuperBolus", binding.useSuperBolus.selectedItemPosition) entry.storage.put("useSuperBolus", binding.useSuperBolus.selectedItemPosition)
entry.storage.put("useTempTarget", binding.useTempTarget.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) { } catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e) aapsLogger.error("Unhandled exception", e)
} }
@ -88,7 +104,8 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.from.setOnClickListener { binding.from.setOnClickListener {
context?.let { context?.let {
TimePickerDialog(it, fromTimeSetListener, TimePickerDialog(
it, fromTimeSetListener,
T.secs(fromSeconds.toLong()).hours().toInt(), T.secs(fromSeconds.toLong()).hours().toInt(),
T.secs((fromSeconds % 3600).toLong()).mins().toInt(), T.secs((fromSeconds % 3600).toLong()).mins().toInt(),
DateFormat.is24HourFormat(context) DateFormat.is24HourFormat(context)
@ -105,13 +122,29 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.to.setOnClickListener { binding.to.setOnClickListener {
context?.let { context?.let {
TimePickerDialog(it, toTimeSetListener, TimePickerDialog(
it, toTimeSetListener,
T.secs(toSeconds.toLong()).hours().toInt(), T.secs(toSeconds.toLong()).hours().toInt(),
T.secs((toSeconds % 3600).toLong()).mins().toInt(), T.secs((toSeconds % 3600).toLong()).mins().toInt(),
DateFormat.is24HourFormat(context) DateFormat.is24HourFormat(context)
).show() ).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() toSeconds = entry.validTo()
binding.to.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(toSeconds)) binding.to.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(toSeconds))
@ -122,10 +155,13 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.useCob.setSelection(entry.useCOB()) binding.useCob.setSelection(entry.useCOB())
binding.useBolusIob.setSelection(entry.useBolusIOB()) binding.useBolusIob.setSelection(entry.useBolusIOB())
binding.useBasalIob.setSelection(entry.useBasalIOB()) binding.useBasalIob.setSelection(entry.useBasalIOB())
binding.device.setSelection(entry.device())
binding.useTrend.setSelection(entry.useTrend()) binding.useTrend.setSelection(entry.useTrend())
binding.useSuperBolus.setSelection(entry.useSuperBolus()) binding.useSuperBolus.setSelection(entry.useSuperBolus())
binding.useTempTarget.setSelection(entry.useTempTarget()) 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.useCobYes.setOnClickListener(this)
binding.useCobNo.setOnClickListener(this) binding.useCobNo.setOnClickListener(this)
processCob() processCob()

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.general.wear
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.util.Log
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R 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.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.androidaps.utils.wizard.BolusWizard import info.nightscout.androidaps.utils.wizard.BolusWizard
import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.shared.SafeParse import info.nightscout.shared.SafeParse
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DateFormat import java.text.DateFormat
import java.text.DecimalFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -71,6 +72,7 @@ class ActionStringHandler @Inject constructor(
private val activePlugin: ActivePlugin, private val activePlugin: ActivePlugin,
private val iobCobCalculator: IobCobCalculator, private val iobCobCalculator: IobCobCalculator,
private val localInsightPlugin: LocalInsightPlugin, private val localInsightPlugin: LocalInsightPlugin,
private val quickWizard: QuickWizard,
private val danaRPlugin: DanaRPlugin, private val danaRPlugin: DanaRPlugin,
private val danaRKoreanPlugin: DanaRKoreanPlugin, private val danaRKoreanPlugin: DanaRKoreanPlugin,
private val danaRv2Plugin: DanaRv2Plugin, private val danaRv2Plugin: DanaRv2Plugin,
@ -79,7 +81,8 @@ class ActionStringHandler @Inject constructor(
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val config: Config, private val config: Config,
private val repository: AppRepository, private val repository: AppRepository,
private val uel: UserEntryLogger private val uel: UserEntryLogger,
private val defaultValueHelper: DefaultValueHelper
) { ) {
private val timeout = 65 * 1000 private val timeout = 65 * 1000
@ -107,9 +110,11 @@ class ActionStringHandler @Inject constructor(
@Synchronized @Synchronized
private fun handleInitiate(actionString: String) { private fun handleInitiate(actionString: String) {
//TODO: i18n
Log.i("ActionStringHandler", "handleInitiate actionString=" + actionString)
if (!sp.getBoolean(R.string.key_wear_control, false)) return if (!sp.getBoolean(R.string.key_wear_control, false)) return
lastBolusWizard = null lastBolusWizard = null
var rTitle = "CONFIRM" //TODO: i18n var rTitle = rh.gs(R.string.confirm).uppercase()
var rMessage = "" var rMessage = ""
var rAction = "" var rAction = ""
// do the parsing and check constraints // do the parsing and check constraints
@ -136,6 +141,11 @@ class ActionStringHandler @Inject constructor(
val carbs = SafeParse.stringToInt(act[2]) val carbs = SafeParse.stringToInt(act[2])
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value() val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).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.bolus) + ": " + insulinAfterConstraints + "U\n"
rMessage += rh.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g" rMessage += rh.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"
if (insulinAfterConstraints - insulin != 0.0 || carbsAfterConstraints - carbs != 0) { if (insulinAfterConstraints - insulin != 0.0 || carbsAfterConstraints - carbs != 0) {
@ -143,32 +153,72 @@ class ActionStringHandler @Inject constructor(
} }
rAction += "bolus $insulinAfterConstraints $carbsAfterConstraints" rAction += "bolus $insulinAfterConstraints $carbsAfterConstraints"
} else if ("temptarget" == act[0]) { ///////////////////////////////////////////////////////// TEMPTARGET } else if ("temptarget" == act[0]) { ///////////////////////////////////////////////////////// TEMPTARGET
val isMGDL = java.lang.Boolean.parseBoolean(act[1]) aapsLogger.info(LTag.WEAR, "temptarget received: $act")
if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) { if ("cancel" == act[1]) {
sendError("Different units used on watch and phone!") rMessage += rh.gs(R.string.wear_action_tempt_cancel_message)
return
}
val duration = SafeParse.stringToInt(act[2])
if (duration == 0) {
rMessage += "Zero-Temp-Target - cancelling running Temp-Targets?"
rAction = "temptarget true 0 0 0" 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 { } else {
var low = SafeParse.stringToDouble(act[3]) val isMGDL = java.lang.Boolean.parseBoolean(act[1])
var high = SafeParse.stringToDouble(act[4]) if (profileFunction.getUnits() == GlucoseUnit.MGDL != isMGDL) {
if (!isMGDL) { sendError(rh.gs(R.string.wear_action_tempt_unit_error))
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!")
return return
} }
if (high < HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) { val duration = SafeParse.stringToInt(act[2])
sendError("Max-BG out of range!") if (duration == 0) {
return 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 } else if ("status" == act[0]) { ////////////////////////////////////////////// STATUS
rTitle = "STATUS" rTitle = "STATUS"
@ -186,10 +236,15 @@ class ActionStringHandler @Inject constructor(
sendError("Update APP on Watch!") sendError("Update APP on Watch!")
return return
} else if ("wizard2" == act[0]) { ////////////////////////////////////////////// WIZARD } 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 carbsBeforeConstraints = SafeParse.stringToInt(act[1])
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbsBeforeConstraints)).value() val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbsBeforeConstraints)).value()
if (carbsAfterConstraints - carbsBeforeConstraints != 0) { if (carbsAfterConstraints - carbsBeforeConstraints != 0) {
sendError("Carb constraint violation!") sendError(rh.gs(R.string.wizard_carbs_constraint))
return return
} }
val useBG = sp.getBoolean(R.string.key_wearwizard_bg, true) val useBG = sp.getBoolean(R.string.key_wearwizard_bg, true)
@ -202,52 +257,94 @@ class ActionStringHandler @Inject constructor(
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile()
val profileName = profileFunction.getProfileName() val profileName = profileFunction.getProfileName()
if (profile == null) { if (profile == null) {
sendError("No profile found!") sendError(rh.gs(R.string.wizard_no_active_profile))
return return
} }
val bgReading = iobCobCalculator.ads.actualBg() val bgReading = iobCobCalculator.ads.actualBg()
if (bgReading == null) { if (bgReading == null) {
sendError("No recent BG to base calculation on!") sendError(rh.gs(R.string.wizard_no_actual_bg))
return return
} }
val cobInfo = iobCobCalculator.getCobInfo(false, "Wizard wear") val cobInfo = iobCobCalculator.getCobInfo(false, "Wizard wear")
if (cobInfo.displayCob == null) { if (cobInfo.displayCob == null) {
sendError("Unknown COB! BG reading missing or recent app restart?") sendError(rh.gs(R.string.wizard_no_cob))
return return
} }
val format = DecimalFormat("0.00")
val formatInt = DecimalFormat("0")
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
val tempTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null val tempTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null
val bolusWizard = BolusWizard(injector).doCalc(profile, profileName, tempTarget, val bolusWizard = BolusWizard(injector).doCalc(
carbsAfterConstraints, if (cobInfo.displayCob != null) cobInfo.displayCob!! else 0.0, bgReading.valueToUnits(profileFunction.getUnits()), profile, profileName, tempTarget,
0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false) carbsAfterConstraints, cobInfo.displayCob!!, bgReading.valueToUnits(profileFunction.getUnits()),
if (abs(bolusWizard.insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) { 0.0, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend, false
sendError("Insulin constraint violation!" + )
"\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!") 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 return
} }
if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) { if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) {
rAction = "info" rAction = "info"
rTitle = "INFO" rTitle = rh.gs(R.string.info)
} else { } else {
rAction = actionString rAction = actionString
} }
rMessage += "Carbs: " + bolusWizard.carbs + "g" rMessage += rh.gs(R.string.wizard_result, bolusWizard.calculatedTotalInsulin, bolusWizard.carbs)
rMessage += "\nBolus: " + format.format(bolusWizard.calculatedTotalInsulin) + "U"
rMessage += "\n_____________" rMessage += "\n_____________"
rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): " rMessage += "\n" + bolusWizard.explainShort()
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"
}
lastBolusWizard = bolusWizard 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]) { } else if ("opencpp" == act[0]) {
val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet() val activeProfileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values if (activeProfileSwitch is ValueWrapper.Existing) { // read CPP values
@ -331,7 +428,10 @@ class ActionStringHandler @Inject constructor(
rAction = "cancelChangeRequest" rAction = "cancelChangeRequest"
wearPlugin.requestNotificationCancel(rAction) wearPlugin.requestNotificationCancel(rAction)
return return
} else return } else {
sendError(rh.gs(R.string.wear_unknown_action_string) + act[0])
return
}
// send result // send result
wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction) wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction)
lastSentTimestamp = System.currentTimeMillis() lastSentTimestamp = System.currentTimeMillis()
@ -560,39 +660,45 @@ class ActionStringHandler @Inject constructor(
} }
//send profile to pump //send profile to pump
uel.log(Action.PROFILE_SWITCH, Sources.Wear, uel.log(Action.PROFILE_SWITCH, Sources.Wear,
ValueWithUnit.Percent(percentage), ValueWithUnit.Percent(percentage),
ValueWithUnit.Hour(timeshift).takeIf { timeshift != 0 }) ValueWithUnit.Hour(timeshift).takeIf { timeshift != 0 })
profileFunction.createProfileSwitch(0, percentage, timeshift) profileFunction.createProfileSwitch(0, percentage, timeshift)
} }
private fun generateTempTarget(duration: Int, low: Double, high: Double) { private fun generateTempTarget(duration: Int, low: Double, high: Double) {
if (duration != 0) { if (duration != 0) {
disposable += repository.runTransactionForResult(InsertAndCancelCurrentTemporaryTargetTransaction( disposable += repository.runTransactionForResult(
timestamp = System.currentTimeMillis(), InsertAndCancelCurrentTemporaryTargetTransaction(
duration = TimeUnit.MINUTES.toMillis(duration.toLong()), timestamp = System.currentTimeMillis(),
reason = TemporaryTarget.Reason.WEAR, duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
lowTarget = Profile.toMgdl(low, profileFunction.getUnits()), reason = TemporaryTarget.Reason.WEAR,
highTarget = Profile.toMgdl(high, profileFunction.getUnits()) lowTarget = Profile.toMgdl(low, profileFunction.getUnits()),
)).subscribe({ result -> highTarget = Profile.toMgdl(high, profileFunction.getUnits())
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") } )
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") } ).subscribe({ result ->
}, { result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}) }, {
uel.log(Action.TT, Sources.Wear, aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
})
uel.log(
Action.TT, Sources.Wear,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR), ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR),
ValueWithUnit.fromGlucoseUnit(low, profileFunction.getUnits().asText), ValueWithUnit.fromGlucoseUnit(low, profileFunction.getUnits().asText),
ValueWithUnit.fromGlucoseUnit(high, profileFunction.getUnits().asText).takeIf { low != high }, ValueWithUnit.fromGlucoseUnit(high, profileFunction.getUnits().asText).takeIf { low != high },
ValueWithUnit.Minute(duration)) ValueWithUnit.Minute(duration)
)
} else { } else {
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(System.currentTimeMillis())) disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(System.currentTimeMillis()))
.subscribe({ result -> .subscribe({ result ->
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, { }, {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
uel.log(Action.CANCEL_TT, Sources.Wear, uel.log(
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR)) Action.CANCEL_TT, Sources.Wear,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.WEAR)
)
} }
} }
@ -601,13 +707,15 @@ class ActionStringHandler @Inject constructor(
detailedBolusInfo.insulin = amount detailedBolusInfo.insulin = amount
detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING
uel.log(Action.PRIME_BOLUS, Sources.Wear, 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() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
sendError(rh.gs(R.string.treatmentdeliveryerror) + sendError(
"\n" + rh.gs(R.string.treatmentdeliveryerror) +
result.comment) "\n" +
result.comment
)
} }
} }
}) })
@ -615,9 +723,9 @@ class ActionStringHandler @Inject constructor(
private fun doECarbs(carbs: Int, time: Long, duration: Int) { private fun doECarbs(carbs: Int, time: Long, duration: Int) {
uel.log(if (duration == 0) Action.CARBS else Action.EXTENDED_CARBS, Sources.Wear, uel.log(if (duration == 0) Action.CARBS else Action.EXTENDED_CARBS, Sources.Wear,
ValueWithUnit.Timestamp(time), ValueWithUnit.Timestamp(time),
ValueWithUnit.Gram(carbs), ValueWithUnit.Gram(carbs),
ValueWithUnit.Hour(duration).takeIf { duration != 0 }) ValueWithUnit.Hour(duration).takeIf { duration != 0 })
doBolus(0.0, carbs, time, duration) doBolus(0.0, carbs, time, duration)
} }
@ -636,15 +744,17 @@ class ActionStringHandler @Inject constructor(
else -> Action.TREATMENT else -> Action.TREATMENT
} }
uel.log(action, Sources.Wear, uel.log(action, Sources.Wear,
ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 }, ValueWithUnit.Insulin(amount).takeIf { amount != 0.0 },
ValueWithUnit.Gram(carbs).takeIf { carbs != 0 }, ValueWithUnit.Gram(carbs).takeIf { carbs != 0 },
ValueWithUnit.Hour(carbsDuration).takeIf { carbsDuration != 0 }) ValueWithUnit.Hour(carbsDuration).takeIf { carbsDuration != 0 })
commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
sendError(rh.gs(R.string.treatmentdeliveryerror) + sendError(
"\n" + rh.gs(R.string.treatmentdeliveryerror) +
result.comment) "\n" +
result.comment
)
} }
} }
}) })
@ -665,4 +775,4 @@ class ActionStringHandler @Inject constructor(
lastConfirmActionString = null lastConfirmActionString = null
lastBolusWizard = null lastBolusWizard = null
} }
} }

View file

@ -46,6 +46,7 @@ import info.nightscout.androidaps.interfaces.Loop;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.Profile; import info.nightscout.androidaps.interfaces.Profile;
import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.ProfileFunction;
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry;
import info.nightscout.shared.logging.AAPSLogger; import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag; import info.nightscout.shared.logging.LTag;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; 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.DefaultValueHelper;
import info.nightscout.androidaps.utils.TrendCalculator; import info.nightscout.androidaps.utils.TrendCalculator;
import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.wizard.QuickWizard;
import info.nightscout.shared.sharedPreferences.SP; import info.nightscout.shared.sharedPreferences.SP;
public class WatchUpdaterService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { 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 ReceiverStatusStore receiverStatusStore;
@Inject Config config; @Inject Config config;
@Inject public TrendCalculator trendCalculator; @Inject public TrendCalculator trendCalculator;
@Inject public QuickWizard quickWizard;
public static final String ACTION_RESEND = WatchUpdaterService.class.getName().concat(".Resend"); public static final String ACTION_RESEND = WatchUpdaterService.class.getName().concat(".Resend");
public static final String ACTION_OPEN_SETTINGS = WatchUpdaterService.class.getName().concat(".OpenSettings"); 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 OPEN_SETTINGS_PATH = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear"; private static final String NEW_STATUS_PATH = "/sendstatustowear";
private static final String NEW_PREFERENCES_PATH = "/sendpreferencestowear"; 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 BASAL_DATA_PATH = "/nightscout_watch_basal";
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress"; 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_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
public static final String ACTION_CHANGECONFIRMATION_REQUEST_PATH = "/nightscout_watch_changeconfirmationrequest"; public static final String ACTION_CHANGECONFIRMATION_REQUEST_PATH = "/nightscout_watch_changeconfirmationrequest";
public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest"; public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest";
String TAG = "WatchUpdateService";
private static boolean lastLoopStatus; private static boolean lastLoopStatus;
@ -156,7 +161,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent != null ? intent.getAction() : null; String action = intent != null ? intent.getAction() : null;
// Log.d(TAG, logPrefix + "onStartCommand: " + action); // Log.d(TAG, "onStartCommand: " + action);
if (wearIntegration()) { if (wearIntegration()) {
handler.post(() -> { handler.post(() -> {
@ -235,7 +240,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
super.onPeerConnected(peer); super.onPeerConnected(peer);
String id = peer.getId(); String id = peer.getId();
String name = peer.getDisplayName(); 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); super.onPeerDisconnected(peer);
String id = peer.getId(); String id = peer.getId();
String name = peer.getDisplayName(); String name = peer.getDisplayName();
// Log.d(TAG, logPrefix + "onPeerDisconnected peer name & ID: " + name + "|" + id); Log.d(TAG, "onPeerDisconnected peer name & ID: " + name + "|" + id);
} }
@Override @Override
public void onMessageReceived(MessageEvent event) { public void onMessageReceived(MessageEvent event) {
// Log.d(TAG, logPrefix + "onMessageRecieved: " + event); // Log.d(TAG, "onMessageRecieved: " + event);
if (wearIntegration()) { if (wearIntegration()) {
if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH)) { if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH)) {
@ -283,7 +288,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
private void sendData() { private void sendData() {
GlucoseValue lastBG = iobCobCalculator.getAds().lastBg(); GlucoseValue lastBG = iobCobCalculator.getAds().lastBg();
// Log.d(TAG, logPrefix + "LastBg=" + lastBG); // Log.d(TAG, "LastBg=" + lastBG);
if (lastBG != null) { if (lastBG != null) {
GlucoseStatus glucoseStatus = glucoseStatusProvider.getGlucoseStatusData(); GlucoseStatus glucoseStatus = glucoseStatusProvider.getGlucoseStatusData();
@ -364,6 +369,10 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
googleApiConnect(); googleApiConnect();
} }
sendPreferences();
sendQuickWizard();
long startTime = System.currentTimeMillis() - (long) (60000 * 60 * 5.5); long startTime = System.currentTimeMillis() - (long) (60000 * 60 * 5.5);
GlucoseValue last_bg = iobCobCalculator.getAds().lastBg(); GlucoseValue last_bg = iobCobCalculator.getAds().lastBg();
@ -382,7 +391,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
entries.putDataMapArrayList("entries", dataMaps); entries.putDataMapArrayList("entries", dataMaps);
(new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, entries); (new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, entries);
} }
sendPreferences();
sendBasals(); sendBasals();
sendStatus(); sendStatus();
} }
@ -720,19 +728,62 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
private void sendPreferences() { private void sendPreferences() {
if (googleApiClient != null && googleApiClient.isConnected()) { if (googleApiClient != null && googleApiClient.isConnected()) {
GlucoseUnit units = profileFunction.getUnits();
boolean wearcontrol = sp.getBoolean(R.string.key_wear_control, false); 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); PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_PREFERENCES_PATH);
//unique content //unique content
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis()); 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_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(); PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest); Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
} else { } 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<DataMap> 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 @NonNull
private String generateStatusString(Profile profile, String currentBasal, String iobSum, String iobDetail, String bgiString) { private String generateStatusString(Profile profile, String currentBasal, String iobSum, String iobDetail, String bgiString) {

View file

@ -18,10 +18,11 @@ class ActivityGraph : GraphView {
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
fun show(insulin: Insulin) { fun show(insulin: Insulin, diaSample: Double? = null) {
removeAllSeries() removeAllSeries()
val dia = diaSample ?: insulin.dia
mSecondScale = null mSecondScale = null
val hours = floor(insulin.dia + 1).toLong() val hours = floor(dia + 1).toLong()
val bolus = Bolus( val bolus = Bolus(
timestamp = 0, timestamp = 0,
amount = 1.0, amount = 1.0,
@ -31,7 +32,7 @@ class ActivityGraph : GraphView {
val iobArray: MutableList<DataPoint> = ArrayList() val iobArray: MutableList<DataPoint> = ArrayList()
var time: Long = 0 var time: Long = 0
while (time <= T.hours(hours).msecs()) { 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)) activityArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.activityContrib))
iobArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.iobContrib)) iobArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.iobContrib))
time += T.mins(5).msecs() time += T.mins(5).msecs()

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.profile.local
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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.ActivePlugin
import info.nightscout.androidaps.interfaces.GlucoseUnit import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
@ -31,8 +31,10 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.ui.SpinnerHelper import info.nightscout.androidaps.utils.ui.SpinnerHelper
import info.nightscout.androidaps.utils.ui.TimeListEdit import info.nightscout.androidaps.utils.ui.TimeListEdit
import info.nightscout.shared.SafeParse import info.nightscout.shared.SafeParse
import info.nightscout.shared.logging.AAPSLogger
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
import java.math.RoundingMode
import java.text.DecimalFormat import java.text.DecimalFormat
import javax.inject.Inject import javax.inject.Inject
@ -61,6 +63,8 @@ class LocalProfileFragment : DaggerFragment() {
binding.basalGraph.show(ProfileSealed.Pure(it)) binding.basalGraph.show(ProfileSealed.Pure(it))
binding.icGraph.show(ProfileSealed.Pure(it)) binding.icGraph.show(ProfileSealed.Pure(it))
binding.isfGraph.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) processVisibilityOnClick(it)
binding.target.visibility = View.VISIBLE binding.target.visibility = View.VISIBLE
} }
binding.dia.editText?.id?.let { binding.diaLabel.labelFor = it }
} }
fun build() { fun build() {
@ -130,14 +135,22 @@ class LocalProfileFragment : DaggerFragment() {
binding.name.addTextChangedListener(textWatch) binding.name.addTextChangedListener(textWatch)
binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch) binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch)
binding.dia.tag = "LP_DIA" 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) 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_label) + ": " + sumLabel(), currentProfile.basal, null, pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate, 0.01, DecimalFormat("0.00"), 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) { 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) val isfRange = doubleArrayOf(HardLimits.MIN_ISF, HardLimits.MAX_ISF)
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) 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 { } 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) val isfRange = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL)),
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) 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 // Spinner
@ -175,6 +188,8 @@ class LocalProfileFragment : DaggerFragment() {
binding.basalGraph.show(ProfileSealed.Pure(it)) binding.basalGraph.show(ProfileSealed.Pure(it))
binding.icGraph.show(ProfileSealed.Pure(it)) binding.icGraph.show(ProfileSealed.Pure(it))
binding.isfGraph.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 { binding.profileAdd.setOnClickListener {
@ -265,6 +280,14 @@ class LocalProfileFragment : DaggerFragment() {
updateGUI() 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() { private fun updateGUI() {
if (_binding == null) return if (_binding == null) return
val isValid = localProfilePlugin.isValidEditState(activity) val isValid = localProfilePlugin.isValidEditState(activity)

View file

@ -7,8 +7,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.work.ListenableWorker
import androidx.work.workDataOf
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
@ -118,7 +116,10 @@ class BGSourceFragment : DaggerFragment() {
val glucoseValue = glucoseValues[position] val glucoseValue = glucoseValues[position]
holder.binding.ns.visibility = (glucoseValue.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.ns.visibility = (glucoseValue.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = (!glucoseValue.isValid).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.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits())
holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon()) holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon())
holder.binding.remove.tag = glucoseValue holder.binding.remove.tag = glucoseValue

View file

@ -1,20 +1,37 @@
package info.nightscout.androidaps.utils package info.nightscout.androidaps.utils
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue 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.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class TrendCalculator @Inject constructor( class TrendCalculator @Inject constructor(
private val repository: AppRepository private val repository: AppRepository,
private val rh: ResourceHelper
) { ) {
fun getTrendArrow(glucoseValue: GlucoseValue?): GlucoseValue.TrendArrow = fun getTrendArrow(glucoseValue: GlucoseValue?): GlucoseValue.TrendArrow =
when { when {
glucoseValue?.trendArrow == null -> GlucoseValue.TrendArrow.NONE glucoseValue?.trendArrow == null -> NONE
glucoseValue.trendArrow != GlucoseValue.TrendArrow.NONE -> glucoseValue.trendArrow glucoseValue.trendArrow != NONE -> glucoseValue.trendArrow
else -> calculateDirection(glucoseValue) 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 { 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() val readings = repository.compatGetBgReadingsDataFromTime(toTime - T.mins(10).msecs(), toTime, false).blockingGet()
if (readings.size < 2) if (readings.size < 2)
return GlucoseValue.TrendArrow.NONE return NONE
val current = readings[0] val current = readings[0]
val previous = readings[1] val previous = readings[1]
@ -35,14 +52,14 @@ class TrendCalculator @Inject constructor(
val slopeByMinute = slope * 60000 val slopeByMinute = slope * 60000
return when { return when {
slopeByMinute <= -3.5 -> GlucoseValue.TrendArrow.DOUBLE_DOWN slopeByMinute <= -3.5 -> DOUBLE_DOWN
slopeByMinute <= -2 -> GlucoseValue.TrendArrow.SINGLE_DOWN slopeByMinute <= -2 -> SINGLE_DOWN
slopeByMinute <= -1 -> GlucoseValue.TrendArrow.FORTY_FIVE_DOWN slopeByMinute <= -1 -> FORTY_FIVE_DOWN
slopeByMinute <= 1 -> GlucoseValue.TrendArrow.FLAT slopeByMinute <= 1 -> FLAT
slopeByMinute <= 2 -> GlucoseValue.TrendArrow.FORTY_FIVE_UP slopeByMinute <= 2 -> FORTY_FIVE_UP
slopeByMinute <= 3.5 -> GlucoseValue.TrendArrow.SINGLE_UP slopeByMinute <= 3.5 -> SINGLE_UP
slopeByMinute <= 40 -> GlucoseValue.TrendArrow.DOUBLE_UP slopeByMinute <= 40 -> DOUBLE_UP
else -> GlucoseValue.TrendArrow.NONE else -> NONE
} }
} }
} }

View file

@ -58,13 +58,13 @@ class TddCalculator @Inject constructor(
val tbr = tempBasals[t] val tbr = tempBasals[t]
val profile = profileFunction.getProfile(t) ?: continue val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t) val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
tdd.basalAmount += absoluteRate / 60.0 * 5.0 tdd.basalAmount += absoluteRate / T.mins(60).msecs().toDouble() * calculationStep.toDouble()
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) { if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
// they are not included in TBRs // they are not included in TBRs
val eb = iobCobCalculator.getExtendedBolus(t) val eb = iobCobCalculator.getExtendedBolus(t)
val absoluteEbRate = eb?.rate ?: 0.0 val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolusAmount += absoluteEbRate / 60.0 * 5.0 tdd.bolusAmount += absoluteEbRate / T.mins(60).msecs().toDouble() * calculationStep.toDouble()
} }
result.put(midnight, tdd) result.put(midnight, tdd)
} }
@ -76,7 +76,54 @@ class TddCalculator @Inject constructor(
return result return result
} }
private fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose { fun calculateDaily():TotalDailyDose {
val startTime = MidnightTime.calc(dateUtil.now() )
val endTime = dateUtil.now()
val tdd = TotalDailyDose(timestamp = startTime)
//val result = TotalDailyDose()
repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet()
.filter { it.type != Bolus.Type.PRIMING }
.forEach { t ->
//val midnight = MidnightTime.calc(t.timestamp)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.bolusAmount += t.amount
//result.put(midnight, tdd)
}
repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t ->
//val midnight = MidnightTime.calc(t.timestamp)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.carbs += t.amount
//result.put(midnight, tdd)
}
val calculationStep = T.mins(5).msecs()
for (t in startTime until endTime step calculationStep) {
//val midnight = MidnightTime.calc(t)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t)
val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
tdd.basalAmount += absoluteRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble()
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
// they are not included in TBRs
val eb = iobCobCalculator.getExtendedBolus(t)
val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolusAmount += absoluteEbRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble()
}
//result.put(midnight, tdd)
}
//for (i in 0 until tdd.size()) {
//val tdd = result.valueAt(i)
tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount
//}
aapsLogger.debug(LTag.CORE, tdd.toString())
return tdd
}
fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose {
val totalTdd = TotalDailyDose(timestamp = dateUtil.now()) val totalTdd = TotalDailyDose(timestamp = dateUtil.now())
for (i in 0 until tdds.size()) { for (i in 0 until tdds.size()) {
val tdd = tdds.valueAt(i) val tdd = tdds.valueAt(i)

View file

@ -57,6 +57,8 @@ public class TimeListEdit {
private final double step; private final double step;
private final double min; private final double min;
private final double max; private final double max;
private final double min2;
private final double max2;
private final NumberFormat formatter; private final NumberFormat formatter;
private final Runnable save; private final Runnable save;
private LinearLayout layout; private LinearLayout layout;
@ -68,7 +70,7 @@ public class TimeListEdit {
Context context, Context context,
AAPSLogger aapsLogger, AAPSLogger aapsLogger,
DateUtil dateUtil, 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.context = context;
this.aapsLogger = aapsLogger; this.aapsLogger = aapsLogger;
this.dateUtil = dateUtil; this.dateUtil = dateUtil;
@ -79,8 +81,10 @@ public class TimeListEdit {
this.data1 = data1; this.data1 = data1;
this.data2 = data2; this.data2 = data2;
this.step = step; this.step = step;
this.min = min; this.min = range1[0];
this.max = max; this.max = range1[1];
this.min2 = range2 != null ? range2[0] : 0;
this.max2 = range2 != null ? range2[1] : 0;
this.formatter = formatter; this.formatter = formatter;
this.save = save; this.save = save;
buildView(); buildView();
@ -108,6 +112,7 @@ public class TimeListEdit {
float factor = layout.getContext().getResources().getDisplayMetrics().density; float factor = layout.getContext().getResources().getDisplayMetrics().density;
finalAdd = new ImageView(context); finalAdd = new ImageView(context);
finalAdd.setImageResource(R.drawable.ic_add); 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)); 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.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom);
illp.gravity = Gravity.CENTER; illp.gravity = Gravity.CENTER;
@ -177,7 +182,13 @@ public class TimeListEdit {
numberPickers1[position].setTextWatcher(new TextWatcher() { numberPickers1[position].setTextWatcher(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { 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(); callSave();
log(); log();
} }
@ -197,7 +208,13 @@ public class TimeListEdit {
numberPickers2[position].setTextWatcher(new TextWatcher() { numberPickers2[position].setTextWatcher(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { 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(); callSave();
log(); log();
} }
@ -246,7 +263,7 @@ public class TimeListEdit {
fillSpinner(timeSpinner, secondFromMidnight(i), previous, next); fillSpinner(timeSpinner, secondFromMidnight(i), previous, next);
editText1.setParams(value1(i), min, max, step, formatter, false, null); 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) { if (data2 == null) {
editText2.setVisibility(View.GONE); editText2.setVisibility(View.GONE);

View file

@ -18,6 +18,8 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertOrUpdateBolusCalculatorResultTransaction import info.nightscout.androidaps.database.transactions.InsertOrUpdateBolusCalculatorResultTransaction
import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.extensions.formatColor 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.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag import info.nightscout.shared.logging.LTag
@ -135,27 +137,28 @@ class BolusWizard @Inject constructor(
private var quickWizard: Boolean = true private var quickWizard: Boolean = true
var usePercentage: Boolean = false var usePercentage: Boolean = false
fun doCalc(profile: Profile, fun doCalc(
profileName: String, profile: Profile,
tempTarget: TemporaryTarget?, profileName: String,
carbs: Int, tempTarget: TemporaryTarget?,
cob: Double, carbs: Int,
bg: Double, cob: Double,
correction: Double, bg: Double,
percentageCorrection: Int = 100, correction: Double,
useBg: Boolean, percentageCorrection: Int = 100,
useCob: Boolean, useBg: Boolean,
includeBolusIOB: Boolean, useCob: Boolean,
includeBasalIOB: Boolean, includeBolusIOB: Boolean,
useSuperBolus: Boolean, includeBasalIOB: Boolean,
useTT: Boolean, useSuperBolus: Boolean,
useTrend: Boolean, useTT: Boolean,
useAlarm: Boolean, useTrend: Boolean,
notes: String = "", useAlarm: Boolean,
carbTime: Int = 0, notes: String = "",
usePercentage: Boolean = false, carbTime: Int = 0,
totalPercentage: Double = 100.0, usePercentage: Boolean = false,
quickWizard: Boolean = false totalPercentage: Double = 100.0,
quickWizard: Boolean = false
): BolusWizard { ): BolusWizard {
this.profile = profile this.profile = profile
@ -261,22 +264,23 @@ class BolusWizard @Inject constructor(
return this return this
} }
private fun createBolusCalculatorResult(): BolusCalculatorResult = private fun createBolusCalculatorResult(): BolusCalculatorResult {
BolusCalculatorResult( val unit = profileFunction.getUnits()
return BolusCalculatorResult(
timestamp = dateUtil.now(), timestamp = dateUtil.now(),
targetBGLow = targetBGLow, targetBGLow = Profile.toMgdl(targetBGLow, unit),
targetBGHigh = targetBGHigh, targetBGHigh = Profile.toMgdl(targetBGHigh, unit),
isf = sens, isf = Profile.toMgdl(sens, unit),
ic = ic, ic = ic,
bolusIOB = insulinFromBolusIOB, bolusIOB = insulinFromBolusIOB,
wasBolusIOBUsed = includeBolusIOB, wasBolusIOBUsed = includeBolusIOB,
basalIOB = insulinFromBasalIOB, basalIOB = insulinFromBasalIOB,
wasBasalIOBUsed = includeBasalIOB, wasBasalIOBUsed = includeBasalIOB,
glucoseValue = bg, glucoseValue = Profile.toMgdl(bg, unit),
wasGlucoseUsed = useBg && bg > 0, wasGlucoseUsed = useBg && bg > 0,
glucoseDifference = bgDiff, glucoseDifference = bgDiff,
glucoseInsulin = insulinFromBG, glucoseInsulin = insulinFromBG,
glucoseTrend = trend, glucoseTrend = Profile.fromMgdlToUnits(trend, unit),
wasTrendUsed = useTrend, wasTrendUsed = useTrend,
trendInsulin = insulinFromTrend, trendInsulin = insulinFromTrend,
cob = cob, cob = cob,
@ -294,6 +298,7 @@ class BolusWizard @Inject constructor(
profileName = profileName, profileName = profileName,
note = notes note = notes
) )
}
private fun confirmMessageAfterConstraints(advisor: Boolean): Spanned { 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) actions.add(rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs).formatColor(rh, R.color.carbs) + timeShift)
} }
if (insulinFromCOB > 0) { 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) val absorptionRate = iobCobCalculator.ads.slowAbsorptionPercentage(60)
if (absorptionRate > .25) if (absorptionRate > .25)
actions.add(rh.gs(R.string.slowabsorptiondetected, rh.gc(R.color.cobAlert), (absorptionRate * 100).toInt())) 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() carbTimer.removeEatReminder()
if (sp.getBoolean(R.string.key_usebolusadvisor, false) && Profile.toMgdl(bg, profile.units) > 180 && carbs > 0 && carbTime >= 0) 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), OKDialog.showYesNoCancel(ctx, rh.gs(R.string.bolusadvisor), rh.gs(R.string.bolusadvisormessage),
{ bolusAdvisorProcessing(ctx) }, { bolusAdvisorProcessing(ctx) },
{ commonProcessing(ctx) } { commonProcessing(ctx) }
) )
else else
commonProcessing(ctx) 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 carbTime = 0
bolusCalculatorResult = createBolusCalculatorResult() bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes 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, notes,
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()), ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
ValueWithUnit.Insulin(insulinAfterConstraints)) ValueWithUnit.Insulin(insulinAfterConstraints)
)
if (insulin > 0) { if (insulin > 0) {
commandQueue.bolus(this, object : Callback() { commandQueue.bolus(this, object : Callback() {
override fun run() { 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) { private fun commonProcessing(ctx: Context) {
val profile = profileFunction.getProfile() ?: return val profile = profileFunction.getProfile() ?: return
val pump = activePlugin.activePump val pump = activePlugin.activePump
@ -429,17 +461,17 @@ class BolusWizard @Inject constructor(
bolusCalculatorResult = createBolusCalculatorResult() bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes notes = this@BolusWizard.notes
if (insulin > 0 || carbs > 0) { if (insulin > 0 || carbs > 0) {
val action = when { val action = when {
insulinAfterConstraints.equals(0.0) -> Action.CARBS insulinAfterConstraints.equals(0.0) -> Action.CARBS
carbs.equals(0.0) -> Action.BOLUS carbs.equals(0.0) -> Action.BOLUS
else -> Action.TREATMENT else -> Action.TREATMENT
} }
uel.log(action, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog, uel.log(action, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
notes, notes,
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()), ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 }, ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 }, ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 },
ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 }) ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 })
commandQueue.bolus(this, object : Callback() { commandQueue.bolus(this, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
@ -465,9 +497,9 @@ class BolusWizard @Inject constructor(
private fun calcPercentageWithConstraints() { private fun calcPercentageWithConstraints() {
calculatedPercentage = 100.0 calculatedPercentage = 100.0
if (totalBeforePercentageAdjustment != insulinFromCorrection) if (totalBeforePercentageAdjustment != insulinFromCorrection)
calculatedPercentage = calculatedTotalInsulin/(totalBeforePercentageAdjustment-insulinFromCorrection) * 100 calculatedPercentage = calculatedTotalInsulin / (totalBeforePercentageAdjustment - insulinFromCorrection) * 100
calculatedPercentage = max(calculatedPercentage, 10.0) calculatedPercentage = max(calculatedPercentage, 10.0)
calculatedPercentage = min(calculatedPercentage,250.0) calculatedPercentage = min(calculatedPercentage, 250.0)
} }
private fun calcCorrectionWithConstraints() { private fun calcCorrectionWithConstraints() {
@ -477,4 +509,4 @@ class BolusWizard @Inject constructor(
calculatedCorrection = max(-constraintChecker.getMaxBolusAllowed().value(), calculatedCorrection) calculatedCorrection = max(-constraintChecker.getMaxBolusAllowed().value(), calculatedCorrection)
} }
} }

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.utils.wizard package info.nightscout.androidaps.utils.wizard
import android.util.Log
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import java.util.*
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -18,6 +20,18 @@ class QuickWizard @Inject constructor(
init { init {
setData(JSONArray(sp.getString(R.string.key_quickwizard, "[]"))) 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? { fun getActive(): QuickWizardEntry? {
@ -41,6 +55,38 @@ class QuickWizard @Inject constructor(
operator fun get(position: Int): QuickWizardEntry = operator fun get(position: Int): QuickWizardEntry =
QuickWizardEntry(injector).from(storage.get(position) as JSONObject, position) 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 { fun newEmptyItem(): QuickWizardEntry {
return QuickWizardEntry(injector) return QuickWizardEntry(injector)
} }
@ -57,4 +103,5 @@ class QuickWizard @Inject constructor(
storage.remove(position) storage.remove(position)
save() save()
} }
} }

View file

@ -19,6 +19,7 @@ import info.nightscout.androidaps.utils.JsonHelper.safeGetString
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import java.util.*
import javax.inject.Inject import javax.inject.Inject
class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjector) { class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjector) {
@ -41,11 +42,26 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
const val NO = 1 const val NO = 1
private const val POSITIVE_ONLY = 2 private const val POSITIVE_ONLY = 2
private const val NEGATIVE_ONLY = 3 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 { init {
injector.androidInjector().inject(this) 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 { try {
storage = JSONObject(emptyData) storage = JSONObject(emptyData)
} catch (e: JSONException) { } catch (e: JSONException) {
@ -55,6 +71,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
/* /*
{ {
guid: string,
device: string, // (phone, watch, all)
buttonText: "Meal", buttonText: "Meal",
carbs: 36, carbs: 36,
validFrom: 8 * 60 * 60, // seconds from midnight validFrom: 8 * 60 * 60, // seconds from midnight
@ -66,15 +84,18 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
useTrend: 0, useTrend: 0,
useSuperBolus: 0, useSuperBolus: 0,
useTemptarget: 0 useTemptarget: 0
usePercentage: string, // default, custom
percentage: int,
} }
*/ */
fun from(entry: JSONObject, position: Int): QuickWizardEntry { fun from(entry: JSONObject, position: Int): QuickWizardEntry {
// TODO set guid if missing for migration
storage = entry storage = entry
this.position = position this.position = position
return this 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 { fun doCalc(profile: Profile, profileName: String, lastBG: GlucoseValue, _synchronized: Boolean): BolusWizard {
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() 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) { } else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.shortAvgDelta < 0) {
trend = true 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 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 buttonText(): String = safeGetString(storage, "buttonText", "")
fun carbs(): Int = safeGetInt(storage, "carbs") 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 useSuperBolus(): Int = safeGetInt(storage, "useSuperBolus", NO)
fun useTempTarget(): Int = safeGetInt(storage, "useTempTarget", NO) fun useTempTarget(): Int = safeGetInt(storage, "useTempTarget", NO)
}
fun usePercentage(): Int = safeGetInt(storage, "usePercentage", DEFAULT)
fun percentage(): Int = safeGetInt(storage, "percentage", 100)
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="26dp"
android:height="26dp"
android:drawable="@drawable/ic_xdrip" />
</layer-list>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="26dp"
android:height="26dp"
android:drawable="@drawable/ic_cp_bolus_carbs" />
</layer-list>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="26dp"
android:height="26dp"
android:drawable="@drawable/ic_bolus" />
</layer-list>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="26dp"
android:height="26dp"
android:drawable="@drawable/ic_fortyfiveup" />
</layer-list>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/cb_background_bg" />
</selector>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/cb_background_cob" />
</selector>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/cb_background_iob" />
</selector>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/cb_background_trend" />
</selector>

View file

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="80"
android:viewportHeight="80">
<path
android:fillAlpha="0.5"
android:fillColor="#FFFFFF"
android:pathData="M 18 54 a 3 3 0 0 0 3 3 L 45 57 A 19 19 0 0 0 62 40 A 19 19 0 0 0 45 24 L 21 24 a 3 3 0 0 0 -3 3 Z M 67 40 A 22 22 0 0 1 45 62 L 19 62 a 6 6 0 0 1 -6 -6 L 13 25 a 6 6 0 0 1 6 -6 L 45 19 A 22 22 0 0 1 67 40"
android:strokeAlpha="0.5" />
</vector>

View file

@ -23,7 +23,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/carbs" android:importantForAccessibility="no"
app:srcCompat="@mipmap/ic_launcher" /> app:srcCompat="@mipmap/ic_launcher" />
<TextView <TextView

View file

@ -83,14 +83,14 @@
android:layout_width="150dp" android:layout_width="150dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:labelFor="@+id/age"
android:text="@string/age" android:text="@string/age"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" /> android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/age" android:id="@+id/age"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/age" />
</TableRow> </TableRow>
@ -105,14 +105,14 @@
android:layout_width="150dp" android:layout_width="150dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:labelFor="@+id/weight"
android:text="@string/tdd_total" android:text="@string/tdd_total"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" /> android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/tdd" android:id="@+id/tdd"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/tdd_total" />
</TableRow> </TableRow>
@ -123,18 +123,18 @@
android:gravity="center_vertical"> android:gravity="center_vertical">
<TextView <TextView
android:id="@+id/weigth_label" android:id="@+id/weight_label"
android:layout_width="150dp" android:layout_width="150dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:labelFor="@+id/weight"
android:text="@string/weight_label" android:text="@string/weight_label"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" /> android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/weight" android:id="@+id/weight"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/weight_label" />
</TableRow> </TableRow>
@ -149,14 +149,14 @@
android:layout_width="150dp" android:layout_width="150dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:labelFor="@+id/basalpctfromtdd"
android:text="@string/basalpctfromtdd_label" android:text="@string/basalpctfromtdd_label"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" /> android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/basalpctfromtdd" android:id="@+id/basalpctfromtdd"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/basalpctfromtdd_label" />
</TableRow> </TableRow>

View file

@ -23,7 +23,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/carbs" android:importantForAccessibility="no"
app:srcCompat="@mipmap/ic_launcher" /> app:srcCompat="@mipmap/ic_launcher" />
<TextView <TextView

View file

@ -1,68 +1,84 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/bg_card"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
card_view:cardBackgroundColor="@color/cardColorBackground" card_view:cardBackgroundColor="@color/cardColorBackground"
card_view:cardCornerRadius="6dp" card_view:cardUseCompatPadding="true">
card_view:cardUseCompatPadding="true"
card_view:contentPadding="6dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:orientation="vertical">
android:orientation="horizontal">
<TextView <TextView
android:id="@+id/date" android:id="@+id/date"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="16:55" android:background="@color/list_delimiter"
android:textStyle="bold" /> android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView <LinearLayout
android:id="@+id/value" android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="10dp" android:gravity="center"
android:text="Name" android:orientation="horizontal"
android:textStyle="bold" /> android:padding="6dp">
<ImageView <TextView
android:id="@+id/direction" android:id="@+id/time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:text="16:55"
card_view:srcCompat="@drawable/ic_flat" /> android:textStyle="bold" />
<TextView <TextView
android:id="@+id/ns" android:id="@+id/value"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="10dp" android:paddingStart="10dp"
android:text="NS" android:text="Name"
android:textAlignment="viewEnd" android:textStyle="bold" />
android:textColor="@color/colorSetTempButton" />
<TextView <ImageView
android:id="@+id/invalid" android:id="@+id/direction"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:paddingStart="10dp" android:layout_gravity="center_vertical"
android:text="@string/invalid" card_view:srcCompat="@drawable/ic_flat" />
android:textColor="@android:color/holo_red_light" />
<TextView <TextView
android:id="@+id/remove" android:id="@+id/ns"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="10dp" android:paddingStart="10dp"
android:paddingEnd="5dp" android:text="NS"
android:text="@string/remove_button" android:textAlignment="viewEnd"
android:textAlignment="viewEnd" android:textColor="@color/colorSetTempButton" />
android:textColor="@android:color/holo_orange_light" />
<TextView
android:id="@+id/invalid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:text="@string/invalid"
android:textColor="@android:color/holo_red_light" />
<TextView
android:id="@+id/remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="5dp"
android:text="@string/remove_button"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_orange_light" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -8,7 +8,8 @@
<TableRow <TableRow
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:focusable="true">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -20,7 +21,6 @@
android:textSize="14sp" android:textSize="14sp"
app:drawableStartCompat="@drawable/ic_cp_age_sensor" /> app:drawableStartCompat="@drawable/ic_cp_age_sensor" />
<TextView <TextView
android:id="@+id/sensor_age_label" android:id="@+id/sensor_age_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -83,7 +83,8 @@
<TableRow <TableRow
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:focusable="true">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -158,9 +159,11 @@
<TableRow <TableRow
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:focusable="true">
<TextView <TextView
android:id="@+id/cannula_or_patch"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="25dp" android:layout_height="25dp"
android:gravity="center_vertical" android:gravity="center_vertical"
@ -229,7 +232,8 @@
<TableRow <TableRow
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:focusable="true">
<TextView <TextView
android:id="@+id/pb_label" android:id="@+id/pb_label"

View file

@ -8,7 +8,8 @@
<TableRow <TableRow
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:focusable="true">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -63,7 +64,8 @@
<TableRow <TableRow
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:focusable="true">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -118,9 +120,11 @@
<TableRow <TableRow
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:focusable="true">
<TextView <TextView
android:id="@+id/cannula_or_patch"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="25dp" android:layout_height="25dp"
android:gravity="center_vertical" android:gravity="center_vertical"
@ -171,7 +175,8 @@
<TableRow <TableRow
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:focusable="true">
<TextView <TextView
android:id="@+id/pb_label" android:id="@+id/pb_label"

View file

@ -26,7 +26,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/overview_calibration" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_calibration" /> app:srcCompat="@drawable/ic_calibration" />
<TextView <TextView
@ -58,6 +58,7 @@
android:paddingTop="10dp"> android:paddingTop="10dp">
<TextView <TextView
android:id="@+id/bg_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -70,7 +71,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/bg" android:id="@+id/bg"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_bg_label" />
<TextView <TextView
android:id="@+id/units" android:id="@+id/units"

View file

@ -25,7 +25,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/carbs" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_cp_bolus_carbs" /> app:srcCompat="@drawable/ic_cp_bolus_carbs" />
<TextView <TextView
@ -93,6 +93,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/time_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -105,25 +106,24 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="bold" /> android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_access_alarm_24dp" />
<CheckBox <CheckBox
android:id="@+id/alarmCheckBox" android:id="@+id/alarmCheckBox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:checked="false" android:checked="false"
android:padding="2dp" /> android:padding="2dp"
android:layoutDirection="rtl"
android:contentDescription="@string/a11y_carb_reminder"
android:drawableEnd="@drawable/ic_access_alarm_24dp" />
</LinearLayout> </LinearLayout>
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker <info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/time" android:id="@+id/time"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/time_offset" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -143,6 +143,7 @@
android:layout_gravity="center_vertical"> android:layout_gravity="center_vertical">
<TextView <TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
@ -156,7 +157,8 @@
android:id="@+id/duration" android:id="@+id/duration"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_gravity="center_horizontal" /> android:layout_gravity="center_horizontal"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -176,6 +178,7 @@
android:layout_gravity="center_vertical"> android:layout_gravity="center_vertical">
<TextView <TextView
android:id="@+id/carbs_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
@ -190,7 +193,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/carbs" android:id="@+id/carbs"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_carbs_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -26,7 +26,7 @@
android:id="@+id/icon" android:id="@+id/icon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/careportal_profileswitch" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_actions_profileswitch" /> app:srcCompat="@drawable/ic_actions_profileswitch" />
<TextView <TextView
@ -86,6 +86,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/bg_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -98,7 +99,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/bg" android:id="@+id/bg"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_bg_label" />
<TextView <TextView
android:id="@+id/bg_units" android:id="@+id/bg_units"
@ -121,6 +123,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -133,7 +136,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker <info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration" android:id="@+id/duration"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/virtualpump_extendedbolus_label" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_actions_startextbolus" /> app:srcCompat="@drawable/ic_actions_startextbolus" />
<TextView <TextView
@ -53,6 +53,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/insulin_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -65,7 +66,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/insulin" android:id="@+id/insulin"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/overview_insulin_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -86,6 +88,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -98,7 +101,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker <info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration" android:id="@+id/duration"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/primefill" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_cp_pump_canula" /> app:srcCompat="@drawable/ic_cp_pump_canula" />
<TextView <TextView
@ -75,6 +75,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/fill_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
@ -89,7 +90,8 @@
android:layout_height="40dp" android:layout_height="40dp"
android:layout_gravity="end" android:layout_gravity="end"
android:paddingLeft="5dp" android:paddingLeft="5dp"
android:paddingRight="5dp" /> android:paddingRight="5dp"
app:customContentDescription="@string/overview_insulin_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/overview_insulin_label" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_bolus" /> app:srcCompat="@drawable/ic_bolus" />
<TextView <TextView
@ -76,6 +76,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/time_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -88,7 +89,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker <info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/time" android:id="@+id/time"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/time_offset"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -109,6 +111,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/insulin_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -121,7 +124,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/amount" android:id="@+id/amount"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/overview_insulin_label"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -147,6 +151,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:contentDescription="Increment insuline with 0.5"
android:text="+0.5" /> android:text="+0.5" />
<Button <Button

View file

@ -26,7 +26,7 @@
android:id="@+id/loop_icon" android:id="@+id/loop_icon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/boluswizard" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_loop_closed" /> app:srcCompat="@drawable/ic_loop_closed" />
<TextView <TextView

View file

@ -25,7 +25,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/careportal_profileswitch" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_actions_profileswitch" /> app:srcCompat="@drawable/ic_actions_profileswitch" />
<TextView <TextView
@ -58,6 +58,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:width="120dp" android:width="120dp"
android:labelFor="@+id/profile"
android:padding="10dp" android:padding="10dp"
android:text="@string/profile_label" android:text="@string/profile_label"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
@ -95,6 +96,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -108,7 +110,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker <info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration" android:id="@+id/duration"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -129,6 +132,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/percentage_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -142,7 +146,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/percentage" android:id="@+id/percentage"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_percentage_label"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -163,6 +168,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/timeshift_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
@ -176,7 +182,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/timeshift" android:id="@+id/timeshift"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_timeshift_label"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/tempbasal_label" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_cp_basal_start" /> app:srcCompat="@drawable/ic_cp_basal_start" />
<TextView <TextView
@ -54,6 +54,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/basal_percent_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -66,7 +67,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/basal_percent_input" android:id="@+id/basal_percent_input"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/basal_rate" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -88,6 +90,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/basal_absolute_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -100,7 +103,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/basal_absolute_input" android:id="@+id/basal_absolute_input"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/basal_rate" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -121,6 +125,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -133,7 +138,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker <info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration" android:id="@+id/duration"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/careportal_temporarytarget" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_temptarget_high" /> app:srcCompat="@drawable/ic_temptarget_high" />
<TextView <TextView
@ -54,6 +54,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/temptarget_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
@ -67,7 +68,8 @@
android:id="@+id/temptarget" android:id="@+id/temptarget"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_gravity="center_vertical" /> android:layout_gravity="center_vertical"
app:customContentDescription="@string/target_label" />
<TextView <TextView
android:id="@+id/units" android:id="@+id/units"
@ -89,6 +91,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -101,7 +104,8 @@
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker <info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/duration" android:id="@+id/duration"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -127,6 +131,7 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:width="120dp" android:width="120dp"
android:padding="10dp" android:padding="10dp"
android:labelFor="@+id/reason"
android:text="@string/reason" android:text="@string/reason"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="bold" /> android:textStyle="bold" />

View file

@ -25,30 +25,21 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/overview_treatment_label" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_bolus" /> app:srcCompat="@drawable/ic_bolus" />
</RelativeLayout>
<LinearLayout
android:id="@+id/spacer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp" >
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:layout_centerInParent="true"
android:layout_centerVertical="true"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginLeft="10dp" android:layout_marginLeft="10dp"
android:layout_marginRight="10dp" android:layout_marginRight="10dp"
android:text="@string/overview_treatment_label" android:text="@string/overview_treatment_label"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceLarge" /> android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
</RelativeLayout>
<LinearLayout <LinearLayout
android:id="@+id/recordOnlyLayout" android:id="@+id/recordOnlyLayout"
@ -72,6 +63,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/insulin_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -84,7 +76,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/insulin" android:id="@+id/insulin"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/overview_insulin_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -105,6 +98,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/carbs_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -117,7 +111,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/carbs" android:id="@+id/carbs"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_carbs_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -25,7 +25,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/boluswizard" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_calculator" /> app:srcCompat="@drawable/ic_calculator" />
<TextView <TextView
@ -59,6 +59,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <TextView
android:id="@+id/bg_input_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
@ -70,7 +71,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/bg_input" android:id="@+id/bg_input"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" /> android:layout_height="40dp"
app:customContentDescription="@string/a11y_current_bg" />
<TextView <TextView
android:id="@+id/bg_units" android:id="@+id/bg_units"
@ -89,9 +91,11 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <TextView
android:id="@+id/carbs_input_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:labelFor="@id/carbs_input"
android:padding="10dp" android:padding="10dp"
android:text="@string/treatments_wizard_carbs_label" android:text="@string/treatments_wizard_carbs_label"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
@ -101,8 +105,8 @@
android:id="@+id/carbs_input" android:id="@+id/carbs_input"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_gravity="center_horizontal" /> android:layout_gravity="center_horizontal"
app:customContentDescription="@string/treatments_wizard_carbs_label" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -127,6 +131,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/correction_input_label"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
@ -135,32 +140,26 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text=" %"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<CheckBox <CheckBox
android:id="@+id/correction_percent" android:id="@+id/correction_percent"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:checked="false" android:checked="false"
android:padding="2dp" /> android:layoutDirection="rtl"
android:padding="2dp"
android:text="%"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
</LinearLayout> </LinearLayout>
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/correction_input" android:id="@+id/correction_input"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_gravity="center_horizontal" /> android:layout_gravity="center_horizontal"
app:customContentDescription="@string/a11_correction_units" />
<TextView <TextView
android:id="@+id/correction_unit" android:id="@+id/correction_unit"
@ -241,6 +240,69 @@
android:textAppearance="?android:attr/textAppearanceSmall" /> android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|center_vertical"
android:layout_marginTop="0dp"
android:background="@android:color/transparent"
android:orientation="horizontal"
android:padding="0dp">
<CheckBox
android:id="@+id/bg_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.7"
android:scaleY="0.7"
android:button="@drawable/checkbox_bg_icon"
android:checked="true"
android:contentDescription="@string/treatments_wizard_bg_label" />
<CheckBox
android:id="@+id/trend_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.7"
android:scaleY="0.7"
android:button="@drawable/checkbox_trend_icon"
android:checked="true"
android:contentDescription="@string/bg_trend_label" />
<CheckBox
android:id="@+id/iob_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.9"
android:scaleY="0.9"
android:button="@drawable/checkbox_iob_icon"
android:checked="true"
android:contentDescription="@string/iob" />
<CheckBox
android:id="@+id/cob_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.7"
android:scaleY="0.7"
android:button="@drawable/checkbox_cob_icon"
android:checked="true"
android:contentDescription="@string/treatments_wizard_cob_label" />
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/done_background" android:id="@+id/done_background"
@ -255,77 +317,16 @@
<CheckBox <CheckBox
android:id="@+id/calculation_checkbox" android:id="@+id/calculation_checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
android:checked="false" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:checked="false"
android:contentDescription="@string/show_calculation" android:contentDescription="@string/show_calculation"
app:srcCompat="@drawable/ic_visibility" /> android:drawableEnd="@drawable/ic_visibility" />
<ImageView <include
android:id="@+id/bg_enabled_icon" android:id="@+id/okcancel"
android:layout_width="wrap_content" layout="@layout/okcancel" />
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="-11dp"
android:paddingEnd="-11dp"
android:scaleX="0.5"
android:scaleY="0.5"
app:srcCompat="@drawable/ic_xdrip"/>
<ImageView
android:id="@+id/trend_enabled_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="-11dp"
android:paddingEnd="-11dp"
android:scaleX="0.5"
android:scaleY="0.5"
app:srcCompat="@drawable/ic_fortyfiveup" />
<ImageView
android:id="@+id/iob_enabled_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="-11dp"
android:paddingEnd="-11dp"
android:scaleX="0.5"
android:scaleY="0.5"
app:srcCompat="@drawable/ic_bolus" />
<ImageView
android:id="@+id/cob_enabled_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="-11dp"
android:paddingEnd="-11dp"
android:scaleX="0.5"
android:scaleY="0.5"
app:srcCompat="@drawable/ic_cp_bolus_carbs" />
<Button
android:id="@+id/cancel"
style="@style/mdtp_ActionButton.Text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/mdtp_cancel"
android:textAlignment="textEnd" />
<Button
android:id="@+id/ok"
style="@style/mdtp_ActionButton.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/mdtp_ok" />
</LinearLayout> </LinearLayout>
<View <View
@ -350,6 +351,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/carb_time_input_label"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
@ -360,27 +362,23 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="bold" /> android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/alarm"
android:src="@drawable/ic_access_alarm_24dp" />
<CheckBox <CheckBox
android:id="@+id/alarm" android:id="@+id/alarm"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:checked="false" android:checked="false"
android:contentDescription="set carb timer alarm"
android:drawableEnd="@drawable/ic_access_alarm_24dp"
android:layoutDirection="rtl"
android:padding="2dp" /> android:padding="2dp" />
<info.nightscout.androidaps.utils.ui.NumberPicker <info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/carb_time_input" android:id="@+id/carb_time_input"
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_gravity="center" /> android:layout_gravity="center"
app:contentDescription="carb time" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -402,6 +400,7 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:labelFor="@id/profile"
android:padding="10dp" android:padding="10dp"
android:text="@string/profile_label" android:text="@string/profile_label"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
@ -414,7 +413,6 @@
android:layout_gravity="center_vertical|center_horizontal" android:layout_gravity="center_vertical|center_horizontal"
android:layout_weight="0.5" /> android:layout_weight="0.5" />
<CheckBox <CheckBox
android:id="@+id/sb_checkbox" android:id="@+id/sb_checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -445,38 +443,24 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<CheckBox
android:id="@+id/bg_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="32dp"
android:checked="true" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <CheckBox
android:id="@+id/bg_checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:width="24dp" android:checked="true"
android:text="@string/treatments_wizard_bg_label" android:text="@string/treatments_wizard_bg_label" />
android:textAppearance="?android:attr/textAppearanceSmall" />
<CheckBox <CheckBox
android:id="@+id/tt_checkbox" android:id="@+id/tt_checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:width="32dp" android:checked="false"
android:checked="false" /> android:text="@string/treatments_wizard_tt_label" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="30dp"
android:text="@string/treatments_wizard_tt_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout> </LinearLayout>
@ -506,15 +490,9 @@
android:id="@+id/bg_trend_checkbox" android:id="@+id/bg_trend_checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:width="32dp" android:checked="false"
android:checked="false" /> android:text="@string/bg_trend_label" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/bg_trend_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView <TextView
android:id="@+id/bg_trend" android:id="@+id/bg_trend"
@ -542,15 +520,8 @@
android:id="@+id/iob_checkbox" android:id="@+id/iob_checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:width="32dp" android:checked="true"
android:checked="true" /> android:text="@string/iob" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="130dp"
android:text="@string/iob"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -578,14 +549,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:width="32dp" android:width="32dp"
android:checked="false" /> android:checked="false"
android:text="@string/treatments_wizard_cob_label" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/treatments_wizard_cob_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView <TextView
android:id="@+id/cob" android:id="@+id/cob"
@ -607,19 +572,27 @@
<TableRow <TableRow
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:focusable="true">
<TextView <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:width="32dp" /> android:orientation="horizontal">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:width="86dp" android:width="32dp" />
android:text="@string/treatments_wizard_carbs_label"
android:textAppearance="?android:attr/textAppearanceSmall" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/treatments_wizard_carbs_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<TextView <TextView
android:id="@+id/carbs" android:id="@+id/carbs"
@ -642,19 +615,27 @@
<TableRow <TableRow
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:focusable="true">
<TextView <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:width="32dp" /> android:orientation="horizontal">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:width="86dp" android:width="32dp" />
android:text="@string/superbolus"
android:textAppearance="?android:attr/textAppearanceSmall" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/superbolus"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<TextView <TextView
android:id="@+id/sb" android:id="@+id/sb"
@ -676,19 +657,27 @@
<TableRow <TableRow
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:focusable="true">
<TextView <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:width="32dp" /> android:orientation="horizontal">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:width="86dp" android:width="32dp" />
android:text="@string/treatments_wizard_correction_label"
android:textAppearance="?android:attr/textAppearanceSmall" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="86dp"
android:text="@string/treatments_wizard_correction_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -704,6 +693,7 @@
android:width="50dp" android:width="50dp"
android:gravity="end" android:gravity="end"
android:textAppearance="?android:attr/textAppearanceSmall" /> android:textAppearance="?android:attr/textAppearanceSmall" />
</TableRow> </TableRow>
</TableLayout> </TableLayout>
@ -712,4 +702,4 @@
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View file

@ -25,7 +25,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/carbs" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_calculator" /> app:srcCompat="@drawable/ic_calculator" />
<TextView <TextView

View file

@ -22,6 +22,7 @@
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:labelFor="@+id/spinner"
android:text="@string/selected_profile" android:text="@string/selected_profile"
android:textAppearance="?android:attr/textAppearanceMedium" /> android:textAppearance="?android:attr/textAppearanceMedium" />
@ -35,6 +36,40 @@
</LinearLayout> </LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:labelFor="@+id/name"
android:text="@string/profile_name"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:ems="10"
android:importantForAutofill="no"
android:inputType="text" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -63,7 +98,7 @@
android:layout_height="35dp" android:layout_height="35dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginStart="15dp" android:layout_marginStart="15dp"
android:contentDescription="@string/addnew" android:contentDescription="@string/a11y_add_new_profile"
app:srcCompat="@drawable/ic_add" /> app:srcCompat="@drawable/ic_add" />
<ImageView <ImageView
@ -72,7 +107,7 @@
android:layout_height="35dp" android:layout_height="35dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginStart="15dp" android:layout_marginStart="15dp"
android:contentDescription="@string/clone_label" android:contentDescription="@string/a11y_clone_profile"
app:srcCompat="@drawable/ic_clone" /> app:srcCompat="@drawable/ic_clone" />
<ImageView <ImageView
@ -81,7 +116,7 @@
android:layout_height="35dp" android:layout_height="35dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginStart="15dp" android:layout_marginStart="15dp"
android:contentDescription="@string/remove_label" android:contentDescription="@string/a11y_delete_current_profile"
android:scaleX="1" android:scaleX="1"
android:scaleY="1" android:scaleY="1"
app:srcCompat="@drawable/ic_remove" /> app:srcCompat="@drawable/ic_remove" />
@ -152,32 +187,13 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="10dp" android:gravity="center_horizontal"
android:orientation="horizontal"> android:text="@string/dia_long_label"
android:textColor="@android:color/white"
<TextView android:textSize="20sp" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:labelFor="@+id/name"
android:text="@string/profile_name"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:ems="10"
android:importantForAutofill="no"
android:inputType="text" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -187,6 +203,7 @@
android:paddingTop="5dp"> android:paddingTop="5dp">
<TextView <TextView
android:id="@+id/dia_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
@ -199,7 +216,8 @@
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp" /> android:layout_marginBottom="10dp"
app:customContentDescription="@string/dia" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -210,6 +228,12 @@
</LinearLayout> </LinearLayout>
<info.nightscout.androidaps.plugins.insulin.ActivityGraph
android:id="@+id/insulin_graph"
android:layout_width="match_parent"
android:layout_height="100dip"
android:layout_margin="20dp" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@ -277,11 +301,23 @@
<LinearLayout <LinearLayout
android:id="@+id/target" android:id="@+id/target"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout
android:id="@+id/target_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:orientation="vertical" />
<info.nightscout.androidaps.utils.ui.TargetBgProfileGraph
android:id="@+id/target_graph"
android:layout_width="match_parent"
android:layout_height="100dip"
android:layout_margin="20dp" />
</LinearLayout> </LinearLayout>
<Button <Button

View file

@ -20,6 +20,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -65,7 +66,9 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:focusable="true"
android:orientation="horizontal"
android:screenReaderFocusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -110,6 +113,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -155,6 +159,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -200,6 +205,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -245,6 +251,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -290,6 +297,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -335,6 +343,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -380,6 +389,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -425,6 +435,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -470,6 +481,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView

View file

@ -27,7 +27,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -98,7 +99,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -143,7 +145,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -188,7 +191,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -233,7 +237,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -278,7 +283,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -323,7 +329,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -368,7 +375,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -448,7 +456,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -493,7 +502,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -538,7 +548,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -126,6 +126,7 @@
android:layout_weight="0.5" android:layout_weight="0.5"
android:drawableTop="@drawable/ic_quick_wizard" android:drawableTop="@drawable/ic_quick_wizard"
android:text="@string/quickwizard" android:text="@string/quickwizard"
android:hint="@string/quickwizard"
android:textColor="@color/colorQuickWizardButton" android:textColor="@color/colorQuickWizardButton"
android:textSize="10sp" android:textSize="10sp"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />

View file

@ -21,7 +21,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/quickwizard" android:importantForAccessibility="no"
app:srcCompat="@drawable/ic_quick_wizard" /> app:srcCompat="@drawable/ic_quick_wizard" />
<TextView <TextView
@ -108,6 +108,35 @@
</LinearLayout> </LinearLayout>
<TextView
android:id="@+id/device_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/overview_editquickwizard_show_on_device"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<RadioGroup
android:id="@+id/device"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp">
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="All" />
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Phone" />
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Watch" />
</RadioGroup>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -276,7 +305,6 @@
</RadioGroup> </RadioGroup>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -301,6 +329,47 @@
</RadioGroup> </RadioGroup>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/overview_editquickwizard_usepercentage"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<RadioGroup
android:id="@+id/use_percentage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp">
<RadioButton
android:id="@+id/use_percentage_default"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_default" />
<RadioButton
android:id="@+id/use_percentage_custom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/custom" />
</RadioGroup>
<TextView
android:id="@+id/percentage_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/overview_editquickwizard_percentage"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<EditText
android:id="@+id/percentage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
android:maxLength="3"
android:paddingLeft="10dp" />
<include <include
android:id="@+id/okcancel" android:id="@+id/okcancel"

View file

@ -39,6 +39,7 @@
android:gravity="center_vertical|center_horizontal" android:gravity="center_vertical|center_horizontal"
android:paddingTop="6dp" android:paddingTop="6dp"
android:paddingBottom="6dp" android:paddingBottom="6dp"
android:hint="active profile"
android:text="Profile" android:text="Profile"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
@ -52,6 +53,7 @@
android:gravity="center_vertical|center_horizontal" android:gravity="center_vertical|center_horizontal"
android:paddingTop="6dp" android:paddingTop="6dp"
android:paddingBottom="6dp" android:paddingBottom="6dp"
android:hint="temp target"
android:text="@string/notavailable" android:text="@string/notavailable"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/mdtp_white" android:textColor="@color/mdtp_white"

View file

@ -14,7 +14,8 @@
<com.jjoe64.graphview.GraphView <com.jjoe64.graphview.GraphView
android:id="@+id/bg_graph" android:id="@+id/bg_graph"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="200dp" /> android:layout_height="200dp"
android:contentDescription="@string/a11y_graph"/>
<ImageButton <ImageButton
android:id="@+id/chart_menu_button" android:id="@+id/chart_menu_button"

View file

@ -25,7 +25,7 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="Blood glucose quality icon" android:contentDescription="@string/a11y_bg_quality"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
@ -52,7 +52,8 @@
app:layout_constraintEnd_toStartOf="@+id/deltas_layout" app:layout_constraintEnd_toStartOf="@+id/deltas_layout"
app:layout_constraintStart_toEndOf="@+id/delta_large" app:layout_constraintStart_toEndOf="@+id/delta_large"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables"> tools:ignore="UseCompoundDrawables"
android:focusable="true">
<ImageView <ImageView
android:id="@+id/arrow" android:id="@+id/arrow"
@ -87,7 +88,8 @@
<TableRow <TableRow
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -95,6 +97,7 @@
android:layout_gravity="end" android:layout_gravity="end"
android:textAlignment="textEnd" android:textAlignment="textEnd"
android:text="Δ: " android:text="Δ: "
android:contentDescription="last delta"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
@ -113,7 +116,8 @@
<TableRow <TableRow
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -121,6 +125,7 @@
android:layout_gravity="end" android:layout_gravity="end"
android:textAlignment="textEnd" android:textAlignment="textEnd"
android:text="15m Δ: " android:text="15m Δ: "
android:contentDescription="15 minutes delta"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
@ -139,7 +144,8 @@
<TableRow <TableRow
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -147,6 +153,7 @@
android:layout_gravity="end" android:layout_gravity="end"
android:textAlignment="textEnd" android:textAlignment="textEnd"
android:text="40m Δ: " android:text="40m Δ: "
android:contentDescription="40 minutes delta"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
@ -185,7 +192,7 @@
android:layout_marginBottom="-4dp" android:layout_marginBottom="-4dp"
android:visibility="gone" android:visibility="gone"
app:srcCompat="@drawable/ic_loop_closed" app:srcCompat="@drawable/ic_loop_closed"
android:contentDescription="@string/closedloop" /> android:contentDescription="@string/apsmode_title" />
<TextView <TextView
android:id="@+id/aps_mode_text" android:id="@+id/aps_mode_text"
@ -282,7 +289,8 @@
app:layout_constraintEnd_toStartOf="@+id/basal_layout" app:layout_constraintEnd_toStartOf="@+id/basal_layout"
app:layout_constraintStart_toEndOf="@+id/iob_layout" app:layout_constraintStart_toEndOf="@+id/iob_layout"
app:layout_constraintTop_toTopOf="@+id/iob_layout" app:layout_constraintTop_toTopOf="@+id/iob_layout"
tools:ignore="UseCompoundDrawables"> tools:ignore="UseCompoundDrawables"
android:focusable="true">
<ImageView <ImageView
android:id="@+id/carbs_icon" android:id="@+id/carbs_icon"
@ -377,7 +385,8 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/extended_layout" app:layout_constraintStart_toEndOf="@+id/extended_layout"
app:layout_constraintTop_toTopOf="@+id/iob_layout" app:layout_constraintTop_toTopOf="@+id/iob_layout"
tools:ignore="UseCompoundDrawables"> tools:ignore="UseCompoundDrawables"
android:focusable="true">
<ImageView <ImageView
android:id="@+id/sensitivity_icon" android:id="@+id/sensitivity_icon"
@ -385,7 +394,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
app:srcCompat="@drawable/ic_swap_vert_black_48dp_green" app:srcCompat="@drawable/ic_swap_vert_black_48dp_green"
android:contentDescription="@string/autosenslabel" /> android:contentDescription="@string/a11y_autosenslabel" />
<TextView <TextView
android:id="@+id/sensitivity" android:id="@+id/sensitivity"
@ -398,6 +407,19 @@
android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" android:textStyle="bold"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView
android:id="@+id/variable_sensitivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-9dp"
android:gravity="center_horizontal"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
android:visibility="visible"
tools:ignore="HardcodedText" />
</LinearLayout> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -16,9 +16,9 @@
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -29,37 +29,64 @@
card_view:srcCompat="@drawable/ic_quick_wizard" /> card_view:srcCompat="@drawable/ic_quick_wizard" />
<LinearLayout <LinearLayout
android:orientation="vertical" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="wrap_content"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:baselineAligned="true" android:baselineAligned="true"
android:orientation="horizontal"> android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView <TextView
android:id="@+id/overview_quickwizard_item_buttonText" android:id="@+id/overview_quickwizard_item_buttonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:text="Sample button text"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/cardObjectiveText"
android:textStyle="normal|bold" />
<TextView
android:id="@+id/overview_quickwizard_item_carbs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:text="36g"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/cardObjectiveText"
android:textStyle="normal|bold" />
</LinearLayout>
<ImageView
android:id="@+id/overview_quickwizard_item_device"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="10dp" android:adjustViewBounds="false"
android:text="Sample button text" android:cropToPadding="false"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:paddingRight="10dp"
android:textStyle="normal|bold" android:scaleType="fitStart"
android:textColor="@color/cardObjectiveText" /> card_view:srcCompat="@drawable/ic_smartphone" />
<TextView <ImageView
android:id="@+id/overview_quickwizard_item_carbs" android:id="@+id/handleView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="10dp" android:layout_alignParentEnd="true"
android:text="36g" android:layout_centerVertical="true"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:adjustViewBounds="false"
android:textColor="@color/cardObjectiveText" android:cropToPadding="false"
android:textStyle="normal|bold" /> android:scaleType="fitStart"
card_view:srcCompat="@drawable/ic_reorder_gray_24dp" />
</LinearLayout> </LinearLayout>
@ -88,9 +115,9 @@
android:textStyle="normal|bold" /> android:textStyle="normal|bold" />
<TextView <TextView
android:text="-"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
android:text="-" />
<TextView <TextView
android:id="@+id/overview_quickwizard_item_to" android:id="@+id/overview_quickwizard_item_to"

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/status_lights" android:id="@+id/status_lights"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -11,100 +12,117 @@
android:paddingTop="4dp" android:paddingTop="4dp"
android:paddingBottom="4dp"> android:paddingBottom="4dp">
<ImageView <LinearLayout
android:layout_width="40dp" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_vertical" android:focusable="true"
android:scaleType="centerInside" android:gravity="center_horizontal">
android:scaleX="2"
android:scaleY="2"
app:srcCompat="@drawable/ic_cp_age_cannula"
android:contentDescription="@string/cannula" />
<TextView <ImageView
android:id="@+id/cannula_age" android:id="@+id/cannula_or_patch"
android:layout_width="38dp"
android:layout_height="fill_parent"
android:contentDescription="@string/statuslights_cannula_age"
android:scaleX="2"
android:scaleY="2"
app:srcCompat="@drawable/ic_cp_age_cannula" />
<TextView
android:id="@+id/cannula_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
tools:text="1d12h" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="fill_parent"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_vertical" android:focusable="true"
android:scaleType="centerInside" android:gravity="center_horizontal">
android:scaleX="1.8"
android:scaleY="1.8"
app:srcCompat="@drawable/ic_cp_age_insulin"
android:contentDescription="@string/insulin_label" />
<TextView <ImageView
android:id="@+id/insulin_age" android:layout_width="26dp"
android:layout_height="fill_parent"
android:contentDescription="@string/a11y_insulin_label"
android:scaleX="1.7"
android:scaleY="1.7"
app:srcCompat="@drawable/ic_cp_age_insulin" />
<TextView
android:id="@+id/insulin_age"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:lines="1"
tools:text="12h" />
<TextView
android:id="@+id/reservoir_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:paddingStart="2dp"
tools:text="50+U" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="fill_parent"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<TextView
android:id="@+id/reservoir_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_vertical" android:focusable="true"
android:scaleType="centerInside" android:gravity="center_horizontal">
android:scaleX="2"
android:scaleY="2"
app:srcCompat="@drawable/ic_cp_age_sensor"
android:contentDescription="@string/careportal_sensor_label" />
<TextView <ImageView
android:id="@+id/sensor_age" android:layout_width="28dp"
android:layout_height="fill_parent"
android:contentDescription="@string/careportal_sensor_label"
android:scaleX="1.6"
android:scaleY="1.6"
app:srcCompat="@drawable/ic_cp_age_sensor" />
<TextView
android:id="@+id/sensor_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
tools:text="1d12h" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="fill_parent"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_vertical" android:focusable="true"
android:scaleType="centerInside" android:gravity="center_horizontal">
android:scaleX="2"
android:scaleY="2"
app:srcCompat="@drawable/ic_cp_age_battery"
android:contentDescription="@string/battery_label" />
<TextView <ImageView
android:id="@+id/pb_age" android:layout_width="32dp"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:contentDescription="@string/battery_label"
android:gravity="center_vertical" android:scaleX="1.8"
android:paddingStart="1dp" android:scaleY="1.8"
android:paddingEnd="1dp" app:srcCompat="@drawable/ic_cp_age_battery" />
android:textSize="14sp" />
<TextView <TextView
android:id="@+id/battery_level" android:id="@+id/pb_age"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="fill_parent"
android:gravity="center_vertical" android:lines="1"
android:paddingStart="1dp" tools:text="-" />
android:paddingEnd="2dp"
android:textSize="14sp" /> <TextView
android:id="@+id/battery_level"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:lines="1"
android:paddingStart="2dp"
tools:text="100%" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -38,6 +38,7 @@
android:layout_height="35dp" android:layout_height="35dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp" android:layout_marginLeft="15dp"
android:contentDescription="@string/addnew_above"
app:srcCompat="@drawable/ic_add" /> app:srcCompat="@drawable/ic_add" />
<ImageView <ImageView
@ -46,5 +47,6 @@
android:layout_height="35dp" android:layout_height="35dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp" android:layout_marginLeft="15dp"
android:contentDescription="@string/remove_label"
app:srcCompat="@drawable/ic_remove" /> app:srcCompat="@drawable/ic_remove" />
</LinearLayout> </LinearLayout>

View file

@ -38,6 +38,7 @@
android:layout_height="35dp" android:layout_height="35dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp" android:layout_marginLeft="15dp"
android:contentDescription="@string/addnew_above"
app:srcCompat="@drawable/ic_add" /> app:srcCompat="@drawable/ic_add" />
<ImageView <ImageView
@ -46,5 +47,6 @@
android:layout_height="35dp" android:layout_height="35dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp" android:layout_marginLeft="15dp"
android:contentDescription="@string/remove_label"
app:srcCompat="@drawable/ic_remove" /> app:srcCompat="@drawable/ic_remove" />
</LinearLayout> </LinearLayout>

View file

@ -12,6 +12,20 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout <LinearLayout
android:id="@+id/metadata_layout" android:id="@+id/metadata_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -29,11 +43,11 @@
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
android:id="@+id/date" android:id="@+id/calc_time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:text="1.1.2000" android:text="11:45"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
@ -65,17 +79,17 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginStart="15dp" android:layout_marginStart="5dp"
android:gravity="center" android:gravity="center"
android:text="{fa-clock-o}" android:text="{fa-clock-o}"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
android:id="@+id/bolus_date" android:id="@+id/bolus_time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:text="1.1.2000" android:text="11:45"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
@ -173,17 +187,17 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginStart="15dp" android:layout_marginStart="5dp"
android:gravity="center" android:gravity="center"
android:text="{fa-clock-o}" android:text="{fa-clock-o}"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
android:id="@+id/carbs_date" android:id="@+id/carbs_time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:text="1.1.2000" android:text="11:45"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
@ -258,6 +272,7 @@
</LinearLayout> </LinearLayout>
<View <View
android:id="@+id/delimiter"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="2dip" android:layout_height="2dip"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:baselineAligned="true" android:baselineAligned="true"
android:orientation="horizontal"> android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView <com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -30,11 +43,11 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/date" android:id="@+id/time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingEnd="10dp" android:paddingEnd="10dp"
android:text="1.1.2000 18:00" android:text="18:00"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
@ -111,6 +124,7 @@
</LinearLayout> </LinearLayout>
<View <View
android:id="@+id/delimiter"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="2dip" android:layout_height="2dip"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:baselineAligned="true" android:baselineAligned="true"
android:orientation="horizontal"> android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView <com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -30,10 +43,10 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/date" android:id="@+id/time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="1.1.2000 18:00" android:text="18:00"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
@ -158,6 +171,7 @@
</LinearLayout> </LinearLayout>
<View <View
android:id="@+id/delimiter"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="2dip" android:layout_height="2dip"
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:baselineAligned="true" android:baselineAligned="true"
android:orientation="horizontal"> android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView <com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -30,11 +43,11 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/date" android:id="@+id/time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="10dp" android:paddingStart="10dp"
android:text="1.1.2000 18:00" android:text="18:00"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
@ -124,6 +137,7 @@
</LinearLayout> </LinearLayout>
<View <View
android:id="@+id/delimiter"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="2dip" android:layout_height="2dip"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:baselineAligned="true" android:baselineAligned="true"
android:orientation="horizontal"> android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView <com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -30,10 +43,10 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/date" android:id="@+id/time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="1.1.2000 18:00" android:text="18:00"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
@ -178,6 +191,7 @@
</LinearLayout> </LinearLayout>
<View <View
android:id="@+id/delimiter"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="2dip" android:layout_height="2dip"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"

View file

@ -12,13 +12,26 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:ignore="HardcodedText" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:baselineAligned="true" android:baselineAligned="true"
android:orientation="horizontal"> android:orientation="horizontal">
<com.joanzapata.iconify.widget.IconTextView <com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -30,7 +43,7 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/date" android:id="@+id/time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="10dp" android:paddingStart="10dp"
@ -146,6 +159,7 @@
</LinearLayout> </LinearLayout>
<View <View
android:id="@+id/delimiter"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="2dip" android:layout_height="2dip"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"

View file

@ -5,82 +5,96 @@
android:id="@+id/info_layout" android:id="@+id/info_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" > android:orientation="horizontal">
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
android:gravity="center"
android:text="1.1.2000"
android:textAppearance="?android:attr/textAppearanceMedium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
android:id="@+id/date" android:id="@+id/time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="10dp" android:paddingStart="10dp"
android:paddingTop="3dp" android:paddingTop="3dp"
android:text="1.1.2021 09:00" android:text="09:00"
app:layout_constraintStart_toStartOf="parent" android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintTop_toTopOf="@+id/iconSource" app:layout_constraintBottom_toBottomOf="@+id/iconSource"
app:layout_constraintBottom_toBottomOf="@+id/iconSource" app:layout_constraintStart_toStartOf="parent"
android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintTop_toTopOf="@+id/iconSource"
tools:ignore="HardcodedText,RtlSymmetry" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView <TextView
android:id="@+id/action" android:id="@+id/action"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="10dp" android:paddingStart="10dp"
android:paddingTop="3dp" android:paddingTop="3dp"
android:text="USER ENTRY" android:text="USER ENTRY"
app:layout_constraintStart_toEndOf="@id/date" android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintEnd_toStartOf="@+id/iconSource" app:layout_constraintEnd_toStartOf="@+id/iconSource"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toEndOf="@id/time"
android:textAppearance="?android:attr/textAppearanceSmall" /> app:layout_constraintTop_toBottomOf="@id/date" />
<ImageView <ImageView
android:id="@+id/iconSource" android:id="@+id/iconSource"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:orientation="horizontal" android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="@+id/action"
app:layout_constraintTop_toTopOf="@+id/action" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@+id/action" app:layout_constraintTop_toTopOf="@+id/action"
app:srcCompat="@drawable/ic_cp_bolus_carbs" /> app:srcCompat="@drawable/ic_cp_bolus_carbs" />
<TextView
android:id="@+id/values"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="10dp"
android:text="Values with units"
android:textStyle="bold"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/action" />
<TextView <TextView
android:id="@+id/values" android:id="@+id/notes"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:paddingStart="20dp"
android:paddingStart="20dp" android:paddingEnd="10dp"
android:paddingEnd="10dp" android:text="Notes"
android:textStyle="bold" android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintStart_toStartOf="parent" android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/action" app:layout_constraintStart_toStartOf="parent"
android:visibility="gone" app:layout_constraintTop_toBottomOf="@id/values"
android:text="Values with units" /> tools:ignore="HardcodedText,RtlSymmetry" />
<TextView
android:id="@+id/s"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="20dp"
android:paddingEnd="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/values"
android:textAppearance="?android:attr/textAppearanceSmall"
android:visibility="gone"
android:text="Notes"
tools:ignore="HardcodedText,RtlSymmetry" />
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/s"
android:background="@color/list_delimiter" />
<View
android:id="@+id/delimiter"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/notes" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -25,7 +25,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -69,7 +70,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -113,7 +115,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -157,7 +160,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -202,7 +206,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -247,7 +252,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -292,7 +298,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -337,7 +344,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
android:focusable="true">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -369,8 +377,6 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View file

@ -80,6 +80,7 @@
<string name="description_ns_client">Synchronizes your data with Nightscout</string> <string name="description_ns_client">Synchronizes your data with Nightscout</string>
<string name="description_ama">State of the algorithm in 2017</string> <string name="description_ama">State of the algorithm in 2017</string>
<string name="description_smb">Most recent algorithm for advanced users</string> <string name="description_smb">Most recent algorithm for advanced users</string>
<string name="description_smb_dynamic_isf">Most recent algorithm for advanced users with dynamic/automatic ISF</string>
<string name="description_overview">Displays the current state of your loop and buttons for most common actions</string> <string name="description_overview">Displays the current state of your loop and buttons for most common actions</string>
<string name="description_persistent_notification">Shows an ongoing notification with a short overview of what your loop is doing</string> <string name="description_persistent_notification">Shows an ongoing notification with a short overview of what your loop is doing</string>
<string name="description_profile_local">Define a profile which is available offline.</string> <string name="description_profile_local">Define a profile which is available offline.</string>
@ -169,7 +170,6 @@
<string name="configbuilder_bgsource_description">Where should AndroidAPS gain it\'s data from?</string> <string name="configbuilder_bgsource_description">Where should AndroidAPS gain it\'s data from?</string>
<string name="xdrip">xDrip+</string> <string name="xdrip">xDrip+</string>
<string name="apsmode_title">APS Mode</string> <string name="apsmode_title">APS Mode</string>
<string name="closedloop">Closed Loop</string> <string name="closedloop">Closed Loop</string>
<string name="openloop">Open Loop</string> <string name="openloop">Open Loop</string>
<string name="lowglucosesuspend">Low Glucose Suspend</string> <string name="lowglucosesuspend">Low Glucose Suspend</string>
@ -314,7 +314,7 @@
<string name="wear">Wear</string> <string name="wear">Wear</string>
<string name="resend_all_data">Resend All Data</string> <string name="resend_all_data">Resend All Data</string>
<string name="open_settings_on_wear">Open Settings on Wear</string> <string name="open_settings_on_wear">Open Settings on Wear</string>
<string name="basal_rate">Basal rate:</string> <string name="basal_rate">Basal rate</string>
<string name="basalvaluebelowminimum">Basal value below minimum. Profile not set!</string> <string name="basalvaluebelowminimum">Basal value below minimum. Profile not set!</string>
<string name="sms_actualbg">BG:</string> <string name="sms_actualbg">BG:</string>
<string name="sms_lastbg">Last BG:</string> <string name="sms_lastbg">Last BG:</string>
@ -536,6 +536,7 @@
<string name="ns_localbroadcasts">Enable broadcasts to other apps (like xDrip+). Do not enable if you have more than one instance of AAPS or NSClient installed!</string> <string name="ns_localbroadcasts">Enable broadcasts to other apps (like xDrip+). Do not enable if you have more than one instance of AAPS or NSClient installed!</string>
<string name="ns_localbroadcasts_title">Enable local Broadcasts.</string> <string name="ns_localbroadcasts_title">Enable local Broadcasts.</string>
<string name="openapssmb">OpenAPS SMB</string> <string name="openapssmb">OpenAPS SMB</string>
<string name="openaps_smb_dynamic_isf">OpenAPS SMB Dynamic ISF</string>
<string name="key_use_smb" translatable="false">use_smb</string> <string name="key_use_smb" translatable="false">use_smb</string>
<string name="key_use_uam" translatable="false">use_uam</string> <string name="key_use_uam" translatable="false">use_uam</string>
<string name="key_smb_enable_carbs_suggestions_threshold" translatable="false">smb_enable_carbs_suggestions_threshold</string> <string name="key_smb_enable_carbs_suggestions_threshold" translatable="false">smb_enable_carbs_suggestions_threshold</string>
@ -618,6 +619,7 @@
<string name="negativeonly">Negative only</string> <string name="negativeonly">Negative only</string>
<string name="overview_editquickwizard_usecob">COB calculation</string> <string name="overview_editquickwizard_usecob">COB calculation</string>
<string name="overview_editquickwizard_usetemptarget">Temporary target calculation</string> <string name="overview_editquickwizard_usetemptarget">Temporary target calculation</string>
<string name="overview_editquickwizard_usepercentage">Percentage calculation</string>
<string name="loopenabled">Loop enabled</string> <string name="loopenabled">Loop enabled</string>
<string name="apsselected">APS selected</string> <string name="apsselected">APS selected</string>
<string name="nsclienthaswritepermission">NSClient has write permission</string> <string name="nsclienthaswritepermission">NSClient has write permission</string>
@ -954,8 +956,8 @@
<string name="low_mark_comment">Lower value of in range area (display only)</string> <string name="low_mark_comment">Lower value of in range area (display only)</string>
<string name="high_mark_comment">Higher value of in range area (display only)</string> <string name="high_mark_comment">Higher value of in range area (display only)</string>
<string name="age">Age:</string> <string name="age">Age</string>
<string name="weight_label">Weight:</string> <string name="weight_label">Weight</string>
<string name="id">ID:</string> <string name="id">ID:</string>
<string name="submit">Submit</string> <string name="submit">Submit</string>
<string name="mostcommonprofile">Most common profile:</string> <string name="mostcommonprofile">Most common profile:</string>
@ -1133,11 +1135,76 @@
<string name="errors">Errors</string> <string name="errors">Errors</string>
<string name="ns_sync_slow">Slow down uploads</string> <string name="ns_sync_slow">Slow down uploads</string>
<string name="data_status">BG data status</string> <string name="data_status">BG data status</string>
<string name="statuslights_cannula_age">cannula age</string>
<string name="statuslights_patch_pump_age">patch pump age</string>
<string name="patch_pump">Patch pump</string>
<string name="recalculated_data_used">Recalculated data used</string> <string name="recalculated_data_used">Recalculated data used</string>
<string name="bg_too_close">BG too close:\n%1$s\n%2$s</string> <string name="bg_too_close">BG too close:\n%1$s\n%2$s</string>
<string name="key_last_processed_glunovo_timestamp" translatable="false">last_processed_glunovo_timestamp</string> <string name="key_last_processed_glunovo_timestamp" translatable="false">last_processed_glunovo_timestamp</string>
<string name="identification">Identification (email, FB or Discord nick etc)</string> <string name="identification">Identification (email, FB or Discord nick etc)</string>
<string name="identification_not_set">Identification not set in dev mode</string> <string name="identification_not_set">Identification not set in dev mode</string>
<string name="a11y_dialog">dialog</string>
<string name="a11y_current_bg">current blood glucose</string>
<string name="a11_correction_percentage">correct outcome with %</string>
<string name="a11_correction_units">correct outcome with units</string>
<string name="not_available_full">Not available</string> <string name="not_available_full">Not available</string>
<string name="a11y_high">high</string>
<string name="a11y_inrange">in range</string>
<string name="a11y_low">low</string>
<string name="a11y_arrow_double_down">falling rapidly</string>
<string name="a11y_arrow_single_down">falling</string>
<string name="a11y_arrow_forty_five_down">falling slowly</string>
<string name="a11y_arrow_flat">stable</string>
<string name="a11y_arrow_forty_five_up">rising slowly</string>
<string name="a11y_arrow_single_up">rising</string>
<string name="a11y_arrow_double_up">rising rapidly</string>
<string name="a11y_arrow_none">none</string>
<string name="a11y_arrow_unknown">unknown</string>
<string name="a11y_graph">graph</string>
<string name="a11y_bg_quality">blood glucose quality</string>
<string name="a11y_bg_quality_recalculated">recalculated</string>
<string name="a11y_bg_quality_doubles">double entries</string>
<string name="a11y_insulin_label">insulin</string>
<string name="a11y_blood_glucose">blood glucose</string>
<string name="a11y_bg_outdated">outdated</string>
<string name="a11y_carb_reminder">set reminder</string>
<string name="a11y_add_new_profile">add new profile</string>
<string name="a11y_clone_profile">clone current profile</string>
<string name="a11y_delete_current_profile">delete current profile</string>
<string name="a11y_add_new_to_list">add new to list</string>
<!-- WEAR OS-->
<string name="wear_action_tempt_preset_error">Temptarget unknown preset: %1$s</string>
<string name="wear_action_tempt_cancel_message">Cancelling running Temp-Targets?</string>
<string name="wear_action_tempt_unit_error">Different units used on watch and phone!</string>
<string name="wear_action_tempt_zero_message">Zero-Temp-Target - cancelling running Temp-Targets?</string>
<string name="wear_action_tempt_min_bg_error">Min-BG out of range!</string>
<string name="wear_action_tempt_max_bg_error">Max-BG out of range!</string>
<string name="wear_action_tempt_manual_range_message">Temptarget:\nMin: %1$s\nMax: %2$s\nDuration: %3$s</string>
<string name="wear_action_tempt_manual_message">Temptarget:\nTarget: %1$s\nDuration: %2$s</string>
<string name="wear_action_tempt_preset_message">Temptarget:\Reason: %1$s\nTarget: %2$s\nDuration: %3$s</string>
<string name="quick_wizard_message">QuickWizard: %1$s\nInsulin: %2$.2fU\nCarbs: %3$dg</string>
<string name="wizard_result">Calc. Wizard:\nInsulin: %1$.2fU\nCarbs: %2$dg</string>
<string name="overview_editquickwizard_show_on_device">Show entry on device:</string>
<string name="quick_wizard_not_available">Selected quickwizard no longer available, please refresh your tile</string>
<string name="wizard_no_actual_bg">No recent BG to base calculation on!</string>
<string name="wizard_no_active_profile">No active profile set!</string>
<string name="wizard_no_cob">Unknown COB! BG reading missing or recent app restart?</string>
<string name="wizard_carbs_constraint">Carb constraint violation!</string>
<string name="wizard_explain_calc">Calc (IC: %2$.1f, ISF: %2$.1f) from:"</string>
<string name="wizard_explain_carbs">Carbs: %1$.2fU</string>
<string name="wizard_explain_cob">COB: %1$.0fg %2$.2fU</string>
<string name="wizard_explain_bg">BG: %1$.2fU</string>
<string name="wizard_explain_basal_iob">Basal IOB: %1$.2fU</string>
<string name="wizard_explain_bolus_iob">Bolus IOB: %1$.2fU</string>
<string name="wizard_explain_superbolus">Superbolus: %1$.2fU</string>
<string name="wizard_explain_trend">15\' trend: %1$.2fU</string>
<string name="wizard_explain_percent">Percentage: %1$.2fU x %2$d%% ≈ %3$.2fU</string>
<string name="wizard_constraint_bolus_size">Insulin constraint violation!\nCannot deliver %1$.2fU</string>
<string name="wizard_explain_tt">TempT: %1$s</string>
<string name="wizard_explain_tt_to">%1$s to %2$s</string>
<string name="wizard_pump_not_available">No pump available!</string>
<string name="wear_unknown_action_string">Unknown action command:</string>
<string name="overview_editquickwizard_percentage">Percentage</string>
<string name="app_default">Application default</string>
</resources> </resources>

Some files were not shown because too many files have changed in this diff Show more