This commit is contained in:
Milos Kozak 2022-04-03 00:54:32 +02:00
parent 07c7ac4818
commit 08d7a38dfb
19 changed files with 679 additions and 10 deletions

View file

@ -37,14 +37,25 @@
<application <application
android:name=".MainApp" android:name=".MainApp"
android:allowBackup="true" android:allowBackup="true"
android:backupAgent=".utils.SPBackupAgent"
android:fullBackupOnly="false"
android:icon="${appIcon}" android:icon="${appIcon}"
android:label="@string/app_name" android:label="@string/app_name"
android:restoreAnyVersion="true"
android:roundIcon="${appIconRound}" android:roundIcon="${appIconRound}"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme.Launcher" android:theme="@style/AppTheme.Launcher" >
android:fullBackupOnly="false" <receiver
android:backupAgent=".utils.SPBackupAgent" android:name=".Widget"
android:restoreAnyVersion="true"> android:exported="true" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_info" />
</receiver>
<meta-data <meta-data
android:name="com.google.android.backup.api_key" android:name="com.google.android.backup.api_key"

View file

@ -6,6 +6,8 @@ import android.content.IntentFilter
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.wifi.WifiManager import android.net.wifi.WifiManager
import android.os.Build import android.os.Build
import android.os.Handler
import android.os.HandlerThread
import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner
import androidx.work.Data import androidx.work.Data
import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ExistingPeriodicWorkPolicy
@ -76,6 +78,9 @@ class MainApp : DaggerApplication() {
@Inject lateinit var profileSwitchPlugin: ThemeSwitcherPlugin @Inject lateinit var profileSwitchPlugin: ThemeSwitcherPlugin
@Inject lateinit var localAlertUtils: LocalAlertUtils @Inject lateinit var localAlertUtils: LocalAlertUtils
private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
private lateinit var refreshWidget: Runnable
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
aapsLogger.debug("onCreate") aapsLogger.debug("onCreate")
@ -133,6 +138,13 @@ class MainApp : DaggerApplication() {
localAlertUtils.preSnoozeAlarms() localAlertUtils.preSnoozeAlarms()
doMigrations() doMigrations()
uel.log(UserEntry.Action.START_AAPS, UserEntry.Sources.Aaps) uel.log(UserEntry.Action.START_AAPS, UserEntry.Sources.Aaps)
// schedule widget update
refreshWidget = Runnable {
handler.postDelayed(refreshWidget, 60000)
updateWidget(this)
}
handler.postDelayed(refreshWidget, 60000)
} }
private fun setRxErrorHandler() { private fun setRxErrorHandler() {

View file

@ -0,0 +1,202 @@
package info.nightscout.androidaps
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Paint
import android.widget.RemoteViews
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.extensions.directionToIcon
import info.nightscout.androidaps.extensions.isInProgress
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.extensions.valueToUnitsString
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.plugins.general.overview.OverviewData
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.TrendCalculator
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
import kotlin.math.abs
/**
* Implementation of App Widget functionality.
*/
class Widget : AppWidgetProvider() {
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var overviewData: OverviewData
@Inject lateinit var trendCalculator: TrendCalculator
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var loop: Loop
@Inject lateinit var config: Config
override fun onReceive(context: Context, intent: Intent?) {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
super.onReceive(context, intent)
}
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onEnabled(context: Context) {
// Enter relevant functionality for when the first widget is created
}
override fun onDisabled(context: Context) {
// Enter relevant functionality for when the last widget is disabled
}
private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
aapsLogger.debug(LTag.WIDGET, "updateAppWidget called")
val views = RemoteViews(context.packageName, R.layout.widget_layout)
updateBg(views)
updateTemporaryBasal(views)
updateExtendedBolus(views)
updateIobCob(views)
updateTemporaryTarget(views)
updateProfile(views)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}
private fun updateBg(views: RemoteViews) {
val units = profileFunction.getUnits()
views.setTextViewText(R.id.bg, overviewData.lastBg?.valueToUnitsString(units) ?: rh.gs(R.string.notavailable))
views.setTextColor(
R.id.bg, when {
overviewData.isLow -> rh.gc(R.color.low)
overviewData.isHigh -> rh.gc(R.color.high)
else -> rh.gc(R.color.inrange)
}
)
views.setImageViewResource(R.id.arrow, trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
//binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor(context))
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
if (glucoseStatus != null) {
views.setTextViewText(R.id.delta, Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units))
views.setTextViewText(R.id.avg_delta, Profile.toSignedUnitsString(glucoseStatus.shortAvgDelta, glucoseStatus.shortAvgDelta * Constants.MGDL_TO_MMOLL, units))
views.setTextViewText(R.id.long_avg_delta, Profile.toSignedUnitsString(glucoseStatus.longAvgDelta, glucoseStatus.longAvgDelta * Constants.MGDL_TO_MMOLL, units))
} else {
views.setTextViewText(R.id.delta, rh.gs(R.string.notavailable))
views.setTextViewText(R.id.avg_delta, rh.gs(R.string.notavailable))
views.setTextViewText(R.id.long_avg_delta, rh.gs(R.string.notavailable))
}
// strike through if BG is old
if (!overviewData.isActualBg) views.setInt(R.id.bg, "setPaintFlags", Paint.STRIKE_THRU_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG)
else views.setInt(R.id.bg, "setPaintFlags", Paint.ANTI_ALIAS_FLAG)
views.setTextViewText(R.id.time_ago, dateUtil.minAgo(rh, overviewData.lastBg?.timestamp))
views.setTextViewText(R.id.time_ago_short, "(" + dateUtil.minAgoShort(overviewData.lastBg?.timestamp) + ")")
}
private fun updateTemporaryBasal(views: RemoteViews) {
views.setTextViewText(R.id.base_basal, overviewData.temporaryBasalText)
views.setTextColor(R.id.base_basal, overviewData.temporaryBasalColor)
views.setImageViewResource(R.id.base_basal_icon, overviewData.temporaryBasalIcon)
}
private fun updateExtendedBolus(views: RemoteViews) {
val pump = activePlugin.activePump
views.setTextViewText(R.id.extended_bolus, overviewData.extendedBolusText)
views.setViewVisibility(R.id.extended_layout, (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null && !pump.isFakingTempsByExtendedBoluses).toVisibility())
}
private fun updateIobCob(views: RemoteViews) {
views.setTextViewText(R.id.iob, overviewData.iobText)
// cob
var cobText = overviewData.cobInfo?.displayText(rh, dateUtil, isDev = false) ?: rh.gs(R.string.value_unavailable_short)
val constraintsProcessed = loop.lastRun?.constraintsProcessed
val lastRun = loop.lastRun
if (config.APS && constraintsProcessed != null && lastRun != null) {
if (constraintsProcessed.carbsReq > 0) {
//only display carbsreq when carbs have not been entered recently
if (overviewData.lastCarbsTime < lastRun.lastAPSRun) {
cobText += " | " + constraintsProcessed.carbsReq + " " + rh.gs(R.string.required)
}
}
}
views.setTextViewText(R.id.cob, cobText)
}
private fun updateTemporaryTarget(views: RemoteViews) {
val units = profileFunction.getUnits()
if (overviewData.temporaryTarget?.isInProgress(dateUtil) == false) overviewData.temporaryTarget = null
val tempTarget = overviewData.temporaryTarget
if (tempTarget != null) {
// this is crashing, use background as text for now
//views.setTextColor(R.id.temp_target, rh.gc(R.color.ribbonTextWarning))
//views.setInt(R.id.temp_target, "setBackgroundColor", rh.gc(R.color.ribbonWarning))
views.setTextColor(R.id.temp_target, rh.gc(R.color.ribbonWarning))
views.setTextViewText(R.id.temp_target, Profile.toTargetRangeString(tempTarget.lowTarget, tempTarget.highTarget, GlucoseUnit.MGDL, units) + " " + dateUtil.untilString(tempTarget.end, rh))
} else {
// If the target is not the same as set in the profile then oref has overridden it
profileFunction.getProfile()?.let { profile ->
val targetUsed = loop.lastRun?.constraintsProcessed?.targetBG ?: 0.0
if (targetUsed != 0.0 && abs(profile.getTargetMgdl() - targetUsed) > 0.01) {
aapsLogger.debug("Adjusted target. Profile: ${profile.getTargetMgdl()} APS: $targetUsed")
views.setTextViewText(R.id.temp_target, Profile.toTargetRangeString(targetUsed, targetUsed, GlucoseUnit.MGDL, units))
// this is crashing, use background as text for now
//views.setTextColor(R.id.temp_target, rh.gc(R.color.ribbonTextWarning))
//views.setInt(R.id.temp_target, "setBackgroundResource", rh.gc(R.color.tempTargetBackground))
views.setTextColor(R.id.temp_target, rh.gc(R.color.ribbonWarning))
} else {
// this is crashing, use background as text for now
//views.setTextColor(R.id.temp_target, rh.gc(R.color.ribbonTextDefault))
//views.setInt(R.id.temp_target, "setBackgroundColor", rh.gc(R.color.ribbonDefault))
views.setTextColor(R.id.temp_target, rh.gc(R.color.ribbonTextDefault))
views.setTextViewText(R.id.temp_target, Profile.toTargetRangeString(profile.getTargetLowMgdl(), profile.getTargetHighMgdl(), GlucoseUnit.MGDL, units))
}
}
}
}
fun updateProfile(views: RemoteViews) {
val profileTextColor =
profileFunction.getProfile()?.let {
if (it is ProfileSealed.EPS) {
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
rh.gc(R.color.ribbonWarning)
else rh.gc(R.color.ribbonTextDefault)
} else if (it is ProfileSealed.PS) {
rh.gc(R.color.ribbonTextDefault)
} else {
rh.gc(R.color.ribbonTextDefault)
}
} ?: rh.gc(R.color.ribbonCritical)
views.setTextViewText(R.id.active_profile, profileFunction.getProfileNameWithRemainingTime())
// this is crashing, use background as text for now
//views.setInt(R.id.active_profile, "setBackgroundColor", profileBackgroundColor)
//views.setTextColor(R.id.active_profile, profileTextColor)
views.setTextColor(R.id.active_profile, profileTextColor)
}
}
internal fun updateWidget(context: Context) {
context.sendBroadcast(Intent().also {
it.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, AppWidgetManager.getInstance(context).getAppWidgetIds(ComponentName(context, Widget::class.java)))
it.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
})
}

View file

@ -2,10 +2,13 @@ package info.nightscout.androidaps.di
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.Widget
import info.nightscout.androidaps.skins.SkinListPreference import info.nightscout.androidaps.skins.SkinListPreference
@Module @Module
@Suppress("unused") @Suppress("unused")
abstract class UIModule { abstract class UIModule {
@ContributesAndroidInjector abstract fun skinListPreferenceInjector(): SkinListPreference @ContributesAndroidInjector abstract fun skinListPreferenceInjector(): SkinListPreference
@ContributesAndroidInjector abstract fun aapsWidgetInjector(): Widget
} }

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.overview
import android.content.Context import android.content.Context
import android.graphics.DashPathEffect import android.graphics.DashPathEffect
import android.graphics.Paint import android.graphics.Paint
import androidx.annotation.ColorInt
import com.jjoe64.graphview.series.BarGraphSeries import com.jjoe64.graphview.series.BarGraphSeries
import com.jjoe64.graphview.series.DataPoint import com.jjoe64.graphview.series.DataPoint
import com.jjoe64.graphview.series.LineGraphSeries import com.jjoe64.graphview.series.LineGraphSeries
@ -129,23 +130,23 @@ class OverviewData @Inject constructor(
var lastBg: GlucoseValue? = null var lastBg: GlucoseValue? = null
private val isLow: Boolean val isLow: Boolean
get() = lastBg?.let { lastBg -> get() = lastBg?.let { lastBg ->
lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine() lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine()
} ?: false } ?: false
private val isHigh: Boolean val isHigh: Boolean
get() = lastBg?.let { lastBg -> get() = lastBg?.let { lastBg ->
lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine() lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine()
} ?: false } ?: false
fun lastBgColor(context: Context?): Int { @ColorInt
return when { fun lastBgColor(context: Context?): Int =
when {
isLow -> rh.gac(context, R.attr.bgLow) isLow -> rh.gac(context, R.attr.bgLow)
isHigh -> rh.gac(context, R.attr.highColor) isHigh -> rh.gac(context, R.attr.highColor)
else -> rh.gac(context, R.attr.bgInRange) else -> rh.gac(context, R.attr.bgInRange)
} }
}
val lastBgDescription: String val lastBgDescription: String
get() = when { get() = when {

View file

@ -15,6 +15,7 @@ import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin
import info.nightscout.androidaps.queue.commands.Command import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.updateWidget
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.LocalAlertUtils import info.nightscout.androidaps.utils.LocalAlertUtils
@ -86,6 +87,7 @@ class KeepAliveWorker(
) )
} }
updateWidget(context)
localAlertUtils.shortenSnoozeInterval() localAlertUtils.shortenSnoozeInterval()
localAlertUtils.checkStaleBGAlert() localAlertUtils.checkStaleBGAlert()
checkPump() checkPump()

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Background for widgets to make the rounded corners based on the
appWidgetRadius attribute value
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="?attr/appWidgetRadius" />
<solid android:color="?android:attr/colorBackground" />
</shape>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Background for views inside widgets to make the rounded corners based on the
appWidgetInnerRadius attribute value
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="?attr/appWidgetInnerRadius" />
<solid android:color="?android:attr/colorAccent" />
</shape>

View file

@ -0,0 +1,344 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.AndroidAPS.AppWidget.Container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:theme="@style/AppTheme.Launcher.AppWidgetContainer">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/active_profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/temp_target"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:gravity="center_vertical|center_horizontal"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="00.0"
android:textSize="60sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<LinearLayout
android:id="@+id/arrows_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:focusable="true"
android:gravity="center"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/trend_arrow"
android:src="@drawable/ic_flat" />
<TextView
android:id="@+id/time_ago"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/deltas_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="end|center_vertical"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:contentDescription="last delta"
android:text="Δ: "
android:textAlignment="textEnd"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="n/a"
android:textAlignment="textEnd"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:contentDescription="15 minutes delta"
android:text="15m Δ: "
android:textAlignment="textEnd"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/avg_delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="n/a"
android:textAlignment="textEnd"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:contentDescription="40 minutes delta"
android:text="40m Δ: "
android:textAlignment="textEnd"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/long_avg_delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="n/a"
android:textAlignment="textEnd"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/iob_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="@string/iob"
android:src="@drawable/ic_bolus" />
<TextView
android:id="@+id/iob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/cob_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:focusable="true"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/carbs_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@drawable/anim_carbs"
android:contentDescription="@string/cob" />
<TextView
android:id="@+id/cob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/basal_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/base_basal_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="@string/basal"
android:src="@drawable/ic_cp_basal_no_tbr" />
<TextView
android:id="@+id/base_basal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/extended_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="@string/extended_bolus"
android:src="@drawable/ic_actions_startextbolus" />
<TextView
android:id="@+id/extended_bolus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/as_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:focusable="true"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/sensitivity_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="@string/a11y_autosenslabel"
android:src="@drawable/ic_swap_vert_black_48dp_green" />
<TextView
android:id="@+id/sensitivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,11 @@
<resources>
<style name="Widget.AndroidAPS.AppWidget.Container" parent="android:Widget">
<item name="android:padding">?attr/appWidgetPadding</item>
<item name="android:background">@drawable/app_widget_background</item>
</style>
<style name="Widget.AndroidAPS.AppWidget.InnerView" parent="android:Widget">
<item name="android:padding">?attr/appWidgetPadding</item>
<item name="android:background">@drawable/app_widget_inner_view_background</item>
</style>
</resources>

View file

@ -0,0 +1,7 @@
<resources>
<declare-styleable name="AppWidgetAttrs">
<attr name="appWidgetPadding" format="dimension" />
<attr name="appWidgetInnerRadius" format="dimension" />
<attr name="appWidgetRadius" format="dimension" />
</declare-styleable>
</resources>

View file

@ -1,2 +1,9 @@
<resources> <resources>
<!--
Refer to App Widget Documentation for margin information
http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
-->
<dimen name="widget_margin">0dp</dimen>
</resources> </resources>

View file

@ -1208,4 +1208,5 @@
<string name="above" comment="above &quot;in range&quot;">Above</string> <string name="above" comment="above &quot;in range&quot;">Above</string>
<string name="show_loop_records">Show loop records</string> <string name="show_loop_records">Show loop records</string>
<string name="show_hide_records">Hide loop records</string> <string name="show_hide_records">Hide loop records</string>
<string name="widget_description">AndroidAPS widget</string>
</resources> </resources>

View file

@ -0,0 +1,11 @@
<resources>
<style name="Widget.AndroidAPS.AppWidget.Container" parent="android:Widget">
<item name="android:id">@android:id/background</item>
<item name="android:background">?android:attr/colorBackground</item>
</style>
<style name="Widget.AndroidAPS.AppWidget.InnerView" parent="android:Widget">
<item name="android:background">?android:attr/colorBackground</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
</resources>

View file

@ -0,0 +1,22 @@
<resources>
<style name="AppTheme.Launcher.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault">
<!-- Radius of the outer bound of widgets to make the rounded corners -->
<item name="appWidgetRadius">16dp</item>
<!--
Radius of the inner view's bound of widgets to make the rounded corners.
It needs to be 8dp or less than the value of appWidgetRadius
-->
<item name="appWidgetInnerRadius">8dp</item>
</style>
<style name="AppTheme.Launcher.AppWidgetContainer"
parent="AppTheme.Launcher.AppWidgetContainerParent">
<!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
<item name="appWidgetPadding">16dp</item>
<item name="icBolusColor">@color/colorInsulinButton</item>
<item name="icBolusCarbsColor">@color/colorCarbsButton</item>
</style>
</resources>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="250dp"
android:minHeight="110dp"
android:updatePeriodMillis="86400000"
android:previewImage="@drawable/widget_preview"
android:initialLayout="@layout/widget_layout"
android:description="@string/widget_description"
android:widgetCategory="home_screen"
android:initialKeyguardLayout="@layout/widget_layout"
/>

View file

@ -58,6 +58,7 @@ plugins {
id "io.gitlab.arturbosch.detekt" version "1.19.0" id "io.gitlab.arturbosch.detekt" version "1.19.0"
id "org.jlleitschuh.gradle.ktlint" version "10.2.1" id "org.jlleitschuh.gradle.ktlint" version "10.2.1"
id 'org.barfuin.gradle.jacocolog' version '2.0.0' id 'org.barfuin.gradle.jacocolog' version '2.0.0'
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
} }
allprojects { allprojects {

View file

@ -24,5 +24,6 @@ enum class LTag(val tag: String, val defaultValue : Boolean = true, val requires
SMS("SMS"), SMS("SMS"),
TIDEPOOL("TIDEPOOL"), TIDEPOOL("TIDEPOOL"),
UI("UI", defaultValue = false), UI("UI", defaultValue = false),
WEAR("WEAR") WEAR("WEAR"),
WIDGET("WIDGET")
} }