From e1e7b4a7a8b5834c13651c39603abe0c556e5c02 Mon Sep 17 00:00:00 2001 From: Andries Smit Date: Wed, 19 Jan 2022 17:21:59 +0100 Subject: [PATCH] Improve screenreader accesibility --- .../bgQualityCheck/BgQualityCheckPlugin.kt | 7 + .../plugins/general/overview/OverviewData.kt | 29 ++- .../general/overview/OverviewFragment.kt | 22 ++ .../androidaps/utils/TrendCalculator.kt | 45 ++-- .../androidaps/utils/ui/TimeListEdit.java | 1 + .../res/layout/overview_buttons_layout.xml | 1 + app/src/main/res/layout/overview_fragment.xml | 2 + .../res/layout/overview_graphs_layout.xml | 3 +- .../main/res/layout/overview_info_layout.xml | 27 ++- .../layout/overview_statuslights_layout.xml | 192 ++++++++++-------- .../main/res/layout/timelistedit_element.xml | 2 + .../layout/timelistedit_element_vertical.xml | 2 + app/src/main/res/values/strings.xml | 18 +- automation/src/main/res/values/strings.xml | 1 + .../nightscout/androidaps/utils/DateUtil.kt | 6 + core/src/main/res/values/strings.xml | 2 + 16 files changed, 244 insertions(+), 116 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/bgQualityCheck/BgQualityCheckPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/bgQualityCheck/BgQualityCheckPlugin.kt index 4b0c9c8e4b..19868a5524 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/bgQualityCheck/BgQualityCheckPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/bgQualityCheck/BgQualityCheckPlugin.kt @@ -102,4 +102,11 @@ class BgQualityCheckPlugin @Inject constructor( State.RECALCULATED -> R.drawable.ic_baseline_warning_24_yellow State.DOUBLED -> R.drawable.ic_baseline_warning_24_red } + + fun stateDescription(): String = + when (state) { + State.RECALCULATED -> rh.gs(R.string.a11_bg_quality_recalculated) + State.DOUBLED -> rh.gs(R.string.a11_bg_quality_doubles) + else -> "" + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewData.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewData.kt index 8437c500fa..8eaf29a08c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewData.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewData.kt @@ -128,14 +128,29 @@ class OverviewData @Inject constructor( var lastBg: GlucoseValue? = null - val lastBgColor: Int + val isLow: Boolean get() = lastBg?.let { lastBg -> - when { - lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine() -> rh.gc(R.color.low) - lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine() -> rh.gc(R.color.high) - else -> rh.gc(R.color.inrange) - } - } ?: rh.gc(R.color.inrange) + lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine() + } ?: false + + val isHigh: Boolean + get() = lastBg?.let { lastBg -> + lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine() + } ?: false + + val lastBgColor: Int + get() = when { + isLow -> rh.gc(R.color.low) + isHigh -> rh.gc(R.color.high) + else -> rh.gc(R.color.inrange) + } + + val lastBgDescription: String + get() = when { + isLow -> rh.gs(R.string.a11y_low) + isHigh -> rh.gs(R.string.a11y_high) + else -> rh.gs(R.string.a11y_inrange) + } val isActualBg: Boolean get() = diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt index d82e315359..fd5201ee2f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt @@ -8,6 +8,7 @@ import android.content.Intent import android.graphics.Color import android.graphics.Paint import android.graphics.drawable.AnimationDrawable +import android.os.Build import android.os.Bundle import android.os.Handler import android.os.HandlerThread @@ -597,24 +598,36 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList // aps mode val closedLoopEnabled = constraintChecker.isClosedLoopAllowed() + + fun apsModeSetA11yLabel(stringRes: Int) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + binding.infoLayout.apsMode.stateDescription = rh.gs(stringRes) + } else { + binding.infoLayout.apsMode.contentDescription = rh.gs(R.string.apsmode_title) + " " + rh.gs(stringRes) + } + } + if (config.APS && pump.pumpDescription.isTempBasalCapable) { binding.infoLayout.apsMode.visibility = View.VISIBLE binding.infoLayout.timeLayout.visibility = View.GONE when { (loop as PluginBase).isEnabled() && loop.isSuperBolus -> { binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_superbolus) + apsModeSetA11yLabel(R.string.superbolus) binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh) binding.infoLayout.apsModeText.visibility = View.VISIBLE } loop.isDisconnected -> { binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disconnected) + apsModeSetA11yLabel(R.string.disconnected) binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh) binding.infoLayout.apsModeText.visibility = View.VISIBLE } (loop as PluginBase).isEnabled() && loop.isSuspended -> { binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_paused) + apsModeSetA11yLabel(R.string.suspendloop_label) binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh) binding.infoLayout.apsModeText.visibility = View.VISIBLE } @@ -624,8 +637,10 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) { // For Omnipod, indicate the pump as disconnected when it's suspended. // The only way to 'reconnect' it, is through the Omnipod tab + apsModeSetA11yLabel(R.string.disconnected) R.drawable.ic_loop_disconnected } else { + apsModeSetA11yLabel(R.string.pump_paused) R.drawable.ic_loop_paused } ) @@ -634,21 +649,25 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList (loop as PluginBase).isEnabled() && closedLoopEnabled.value() && loop.isLGS -> { binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_lgs) + apsModeSetA11yLabel(R.string.uel_lgs_loop_mode) binding.infoLayout.apsModeText.visibility = View.GONE } (loop as PluginBase).isEnabled() && closedLoopEnabled.value() -> { binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_closed) + apsModeSetA11yLabel(R.string.closedloop) binding.infoLayout.apsModeText.visibility = View.GONE } (loop as PluginBase).isEnabled() && !closedLoopEnabled.value() -> { binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_open) + apsModeSetA11yLabel(R.string.openloop) binding.infoLayout.apsModeText.visibility = View.GONE } else -> { binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disabled) + apsModeSetA11yLabel(R.string.disabledloop) binding.infoLayout.apsModeText.visibility = View.GONE } } @@ -732,6 +751,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList binding.infoLayout.bg.setTextColor(overviewData.lastBgColor) binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon()) binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor) + binding.infoLayout.arrow.contentDescription = trendCalculator.getTrendDescription(overviewData.lastBg) + " " + overviewData.lastBgDescription val glucoseStatus = glucoseStatusProvider.glucoseStatusData if (glucoseStatus != null) { @@ -752,12 +772,14 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList 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() binding.infoLayout.timeAgo.text = dateUtil.minAgo(rh, overviewData.lastBg?.timestamp) + binding.infoLayout.timeAgo.contentDescription = dateUtil.minAgoLong(rh, overviewData.lastBg?.timestamp) binding.infoLayout.timeAgoShort.text = "(" + dateUtil.minAgoShort(overviewData.lastBg?.timestamp) + ")" val qualityIcon = bgQualityCheckPlugin.icon() if (qualityIcon != 0) { binding.infoLayout.bgQuality.visibility = View.VISIBLE binding.infoLayout.bgQuality.setImageResource(qualityIcon) + binding.infoLayout.bgQuality.contentDescription = rh.gs(R.string.a11y_bg_quality) + " " + bgQualityCheckPlugin.stateDescription() binding.infoLayout.bgQuality.setOnClickListener { context?.let { context -> OKDialog.show(context, rh.gs(R.string.data_status), bgQualityCheckPlugin.message) } } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/TrendCalculator.kt b/app/src/main/java/info/nightscout/androidaps/utils/TrendCalculator.kt index a5f2dc2dcb..869feb2fe8 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/TrendCalculator.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/TrendCalculator.kt @@ -1,20 +1,37 @@ package info.nightscout.androidaps.utils +import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.entities.GlucoseValue.TrendArrow.* +import info.nightscout.androidaps.utils.resources.ResourceHelper import javax.inject.Inject import javax.inject.Singleton @Singleton class TrendCalculator @Inject constructor( - private val repository: AppRepository + private val repository: AppRepository, + private val rh: ResourceHelper ) { fun getTrendArrow(glucoseValue: GlucoseValue?): GlucoseValue.TrendArrow = when { - glucoseValue?.trendArrow == null -> GlucoseValue.TrendArrow.NONE - glucoseValue.trendArrow != GlucoseValue.TrendArrow.NONE -> glucoseValue.trendArrow - else -> calculateDirection(glucoseValue) + glucoseValue?.trendArrow == null -> NONE + glucoseValue.trendArrow != NONE -> glucoseValue.trendArrow + else -> calculateDirection(glucoseValue) + } + + fun getTrendDescription(glucoseValue: GlucoseValue?): String = + when (getTrendArrow(glucoseValue)) { + DOUBLE_DOWN -> rh.gs(R.string.a11y_arrow_double_down) + SINGLE_DOWN -> rh.gs(R.string.a11y_arrow_single_down) + FORTY_FIVE_DOWN -> rh.gs(R.string.a11y_arrow_forty_five_down) + FLAT -> rh.gs(R.string.a11y_arrow_flat) + FORTY_FIVE_UP -> rh.gs(R.string.a11y_arrow_forty_five_up) + SINGLE_UP -> rh.gs(R.string.a11y_arrow_single_up) + DOUBLE_UP -> rh.gs(R.string.a11y_arrow_double_up) + NONE -> rh.gs(R.string.a11y_arrow_none) + else -> rh.gs(R.string.a11y_arrow_unknown) } private fun calculateDirection(glucoseValue: GlucoseValue): GlucoseValue.TrendArrow { @@ -23,7 +40,7 @@ class TrendCalculator @Inject constructor( val readings = repository.compatGetBgReadingsDataFromTime(toTime - T.mins(10).msecs(), toTime, false).blockingGet() if (readings.size < 2) - return GlucoseValue.TrendArrow.NONE + return NONE val current = readings[0] val previous = readings[1] @@ -35,14 +52,14 @@ class TrendCalculator @Inject constructor( val slopeByMinute = slope * 60000 return when { - slopeByMinute <= -3.5 -> GlucoseValue.TrendArrow.DOUBLE_DOWN - slopeByMinute <= -2 -> GlucoseValue.TrendArrow.SINGLE_DOWN - slopeByMinute <= -1 -> GlucoseValue.TrendArrow.FORTY_FIVE_DOWN - slopeByMinute <= 1 -> GlucoseValue.TrendArrow.FLAT - slopeByMinute <= 2 -> GlucoseValue.TrendArrow.FORTY_FIVE_UP - slopeByMinute <= 3.5 -> GlucoseValue.TrendArrow.SINGLE_UP - slopeByMinute <= 40 -> GlucoseValue.TrendArrow.DOUBLE_UP - else -> GlucoseValue.TrendArrow.NONE + slopeByMinute <= -3.5 -> DOUBLE_DOWN + slopeByMinute <= -2 -> SINGLE_DOWN + slopeByMinute <= -1 -> FORTY_FIVE_DOWN + slopeByMinute <= 1 -> FLAT + slopeByMinute <= 2 -> FORTY_FIVE_UP + slopeByMinute <= 3.5 -> SINGLE_UP + slopeByMinute <= 40 -> DOUBLE_UP + else -> NONE } } -} \ No newline at end of file +} diff --git a/app/src/main/java/info/nightscout/androidaps/utils/ui/TimeListEdit.java b/app/src/main/java/info/nightscout/androidaps/utils/ui/TimeListEdit.java index 246792e17b..918758fce4 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/ui/TimeListEdit.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/ui/TimeListEdit.java @@ -112,6 +112,7 @@ public class TimeListEdit { float factor = layout.getContext().getResources().getDisplayMetrics().density; finalAdd = new ImageView(context); finalAdd.setImageResource(R.drawable.ic_add); + finalAdd.setContentDescription(layout.getContext().getResources().getString(R.string.addnew)); LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams((int) (35d * factor), (int) (35 * factor)); illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom); illp.gravity = Gravity.CENTER; diff --git a/app/src/main/res/layout/overview_buttons_layout.xml b/app/src/main/res/layout/overview_buttons_layout.xml index c8c761c3d2..9414b63c91 100644 --- a/app/src/main/res/layout/overview_buttons_layout.xml +++ b/app/src/main/res/layout/overview_buttons_layout.xml @@ -126,6 +126,7 @@ android:layout_weight="0.5" android:drawableTop="@drawable/ic_quick_wizard" android:text="@string/quickwizard" + android:hint="@string/quickwizard" android:textColor="@color/colorQuickWizardButton" android:textSize="10sp" tools:ignore="SmallSp" /> diff --git a/app/src/main/res/layout/overview_fragment.xml b/app/src/main/res/layout/overview_fragment.xml index 22f3cd77cf..092464e219 100644 --- a/app/src/main/res/layout/overview_fragment.xml +++ b/app/src/main/res/layout/overview_fragment.xml @@ -39,6 +39,7 @@ android:gravity="center_vertical|center_horizontal" android:paddingTop="6dp" android:paddingBottom="6dp" + android:hint="active profile" android:text="Profile" android:textAppearance="?android:attr/textAppearanceSmall" tools:ignore="HardcodedText" /> @@ -52,6 +53,7 @@ android:gravity="center_vertical|center_horizontal" android:paddingTop="6dp" android:paddingBottom="6dp" + android:hint="temp target" android:text="@string/notavailable" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/mdtp_white" diff --git a/app/src/main/res/layout/overview_graphs_layout.xml b/app/src/main/res/layout/overview_graphs_layout.xml index 8583e3c6ff..7fdb20f6d9 100644 --- a/app/src/main/res/layout/overview_graphs_layout.xml +++ b/app/src/main/res/layout/overview_graphs_layout.xml @@ -14,7 +14,8 @@ + android:layout_height="200dp" + android:contentDescription="@string/a11y_graph"/> + tools:ignore="UseCompoundDrawables" + android:screenReaderFocusable="true"> + android:orientation="horizontal" + android:focusable="true"> @@ -113,7 +116,8 @@ + android:orientation="horizontal" + android:focusable="true"> @@ -139,7 +144,8 @@ + android:orientation="horizontal" + android:focusable="true"> @@ -185,7 +192,7 @@ android:layout_marginBottom="-4dp" android:visibility="gone" app:srcCompat="@drawable/ic_loop_closed" - android:contentDescription="@string/closedloop" /> + android:contentDescription="@string/apsmode_title" /> + tools:ignore="UseCompoundDrawables" + android:focusable="true"> + tools:ignore="UseCompoundDrawables" + android:focusable="true"> + android:contentDescription="@string/a11y_autosenslabel" /> - + android:focusable="true"> - + + + + + + - - + android:focusable="true"> - + + + + + + + - - - - + android:focusable="true"> - + + + + + + - - + android:focusable="true"> - + - + + + + + diff --git a/app/src/main/res/layout/timelistedit_element.xml b/app/src/main/res/layout/timelistedit_element.xml index fb4b84bd96..4ff1634cb0 100644 --- a/app/src/main/res/layout/timelistedit_element.xml +++ b/app/src/main/res/layout/timelistedit_element.xml @@ -38,6 +38,7 @@ android:layout_height="35dp" android:layout_gravity="center_vertical" android:layout_marginLeft="15dp" + android:contentDescription="@string/addnew_above" app:srcCompat="@drawable/ic_add" /> diff --git a/app/src/main/res/layout/timelistedit_element_vertical.xml b/app/src/main/res/layout/timelistedit_element_vertical.xml index a76a8bc20b..fbe0bce438 100644 --- a/app/src/main/res/layout/timelistedit_element_vertical.xml +++ b/app/src/main/res/layout/timelistedit_element_vertical.xml @@ -38,6 +38,7 @@ android:layout_height="35dp" android:layout_gravity="center_vertical" android:layout_marginLeft="15dp" + android:contentDescription="@string/addnew_above" app:srcCompat="@drawable/ic_add" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 98678d3e8d..1d9c967d69 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -169,7 +169,6 @@ Where should AndroidAPS gain it\'s data from? xDrip+ APS Mode - Closed Loop Open Loop Low Glucose Suspend @@ -1163,5 +1162,22 @@ correct outcome with % correct outcome with units Not available + heigh + in range + low + down fast + down + down trending + flat + up trending + up + up fast + none + unknown + graph + Blood glucose quality + recalculated + double entries + insulin diff --git a/automation/src/main/res/values/strings.xml b/automation/src/main/res/values/strings.xml index 334d6530d1..cf546122e2 100644 --- a/automation/src/main/res/values/strings.xml +++ b/automation/src/main/res/values/strings.xml @@ -83,6 +83,7 @@ WiFi SSID %1$s %2$s Autosens %1$s %2$s %% Autosens % + Auto sens %3$s %1$s %2$s BG difference BG difference [%1$s] diff --git a/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.kt b/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.kt index 20718814ff..a8c8f504fd 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.kt @@ -156,6 +156,12 @@ class DateUtil @Inject constructor(private val context: Context) { return (if (mins > 0) "+" else "") + mins } + fun minAgoLong(rh: ResourceHelper, time: Long?): String { + if (time == null) return "" + val mins = ((now() - time) / 1000 / 60).toInt() + return rh.gs(R.string.minago_long, mins) + } + fun hourAgo(time: Long, rh: ResourceHelper): String { val hours = (now() - time) / 1000.0 / 60 / 60 return rh.gs(R.string.hoursago, hours) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 0486648df8..e0c2c022a0 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -173,6 +173,7 @@ Notes Remove Add new + Add new above Data is coming from different pump. Change pump driver to reset pump state. @@ -199,6 +200,7 @@ %1$d m ago + %1$d minutes ago %1$.1f h ago h days