Merge branch 'dev' into DynamicISF

This commit is contained in:
Milos Kozak 2022-02-15 20:25:30 +01:00
commit e32515a369
100 changed files with 2359 additions and 729 deletions

View file

@ -239,6 +239,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
}
ToastUtils.showToastInUiThread(this, R.string.invalidinput)
}
binding.age.editText?.id?.let { binding.ageLabel.labelFor = it }
binding.tdd.editText?.id?.let { binding.tddLabel.labelFor = it }
binding.weight.editText?.id?.let { binding.weightLabel.labelFor = it }
binding.basalpctfromtdd.editText?.id?.let { binding.basalpctfromtddLabel.labelFor = it }
switchTab(0, typeSelected[0], false)
}

View file

@ -64,6 +64,7 @@ class CalibrationDialog : DialogFragmentWithDate() {
binding.bg.setParams(savedInstanceState?.getDouble("bg")
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
binding.units.text = if (units == GlucoseUnit.MMOL) rh.gs(R.string.mmol) else rh.gs(R.string.mgdl)
binding.bg.editText?.id?.let { binding.bgLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -137,32 +137,39 @@ class CarbsDialog : DialogFragmentWithDate() {
savedInstanceState?.getDouble("carbs")
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher
)
binding.plus1.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
val plus1text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
binding.plus1.text = plus1text
binding.plus1.contentDescription = rh.gs(R.string.treatments_wizard_carbs_label) + " " + plus1text
binding.plus1.setOnClickListener {
binding.carbs.value = max(
0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)
)
validateInputs()
binding.carbs.announceValue()
}
binding.plus2.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
val plus2text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
binding.plus2.text = plus2text
binding.plus2.contentDescription = rh.gs(R.string.treatments_wizard_carbs_label) + " " + plus2text
binding.plus2.setOnClickListener {
binding.carbs.value = max(
0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)
)
validateInputs()
binding.carbs.announceValue()
}
binding.plus3.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
val plus3text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
binding.plus3.text = plus3text
binding.plus2.contentDescription = rh.gs(R.string.treatments_wizard_carbs_label) + " " + plus3text
binding.plus3.setOnClickListener {
binding.carbs.value = max(
0.0, binding.carbs.value
+ sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)
)
validateInputs()
binding.carbs.announceValue()
}
setOnValueChangedListener { eventTime: Long ->
@ -188,6 +195,9 @@ class CarbsDialog : DialogFragmentWithDate() {
binding.hypoTt.isChecked = false
binding.activityTt.isChecked = false
}
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
binding.time.editText?.id?.let { binding.timeLabel.labelFor = it }
binding.carbs.editText?.id?.let { binding.carbsLabel.labelFor = it }
}
override fun onDestroyView() {

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)
if (options == EventType.NOTE || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT || options == EventType.EXERCISE)
binding.notesLayout.root.visibility = View.VISIBLE // independent to preferences
binding.bg.editText?.id?.let { binding.bgLabel.labelFor = it }
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -70,6 +70,8 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
binding.duration.setParams(savedInstanceState?.getDouble("duration")
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, binding.okcancel.ok)
binding.insulin.editText?.id?.let { binding.insulinLabel.labelFor = it }
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
}
override fun onDestroyView() {

View file

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

View file

@ -116,29 +116,40 @@ class InsulinDialog : DialogFragmentWithDate() {
binding.amount.setParams(savedInstanceState?.getDouble("amount")
?: 0.0, 0.0, maxInsulin, activePlugin.activePump.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
binding.plus05.text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
val plus05Text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
binding.plus05.text = plus05Text
binding.plus05.contentDescription = rh.gs(R.string.overview_insulin_label) + " " + plus05Text
binding.plus05.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
validateInputs()
binding.amount.announceValue()
}
binding.plus10.text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
val plus10Text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
binding.plus10.text = plus10Text
binding.plus10.contentDescription = rh.gs(R.string.overview_insulin_label) + " " + plus10Text
binding.plus10.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
validateInputs()
binding.amount.announceValue()
}
binding.plus20.text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
val plus20Text = sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
binding.plus20.text = plus20Text
binding.plus20.contentDescription = rh.gs(R.string.overview_insulin_label) + " " + plus20Text
binding.plus20.setOnClickListener {
binding.amount.value = max(0.0, binding.amount.value
+ sp.getDouble(rh.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
validateInputs()
binding.amount.announceValue()
}
binding.timeLayout.visibility = View.GONE
binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean ->
binding.timeLayout.visibility = isChecked.toVisibility()
}
binding.amount.editText?.id?.let { binding.insulinLabel.labelFor = it }
binding.time.editText?.id?.let { binding.timeLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -148,6 +148,9 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
}
}
binding.ttLayout.visibility = View.GONE
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
binding.percentage.editText?.id?.let { binding.percentageLabel.labelFor = it }
binding.timeshift.editText?.id?.let { binding.timeshiftLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -86,6 +86,9 @@ class TempBasalDialog : DialogFragmentWithDate() {
binding.percentLayout.visibility = View.GONE
binding.absoluteLayout.visibility = View.VISIBLE
}
binding.basalPercentInput.editText?.id?.let { binding.basalPercentLabel.labelFor = it }
binding.basalAbsoluteInput.editText?.id?.let { binding.basalAbsoluteLabel.labelFor = it }
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
}
override fun onDestroyView() {

View file

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

View file

@ -106,6 +106,8 @@ class TreatmentDialog : DialogFragmentWithDate() {
binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
binding.recordOnlyLayout.visibility = View.GONE
binding.insulin.editText?.id?.let { binding.insulinLabel.labelFor = it }
binding.carbs.editText?.id?.let { binding.carbsLabel.labelFor = it }
}
override fun onDestroyView() {

View file

@ -70,7 +70,7 @@ class WizardInfoDialog : DaggerDialogFragment() {
val units = profileFunction.getUnits()
val bgString = Profile.toUnitsString(data.glucoseValue, data.glucoseValue * Constants.MGDL_TO_MMOLL, units)
val isf = Profile.toUnits(data.isf, data.isf * Constants.MGDL_TO_MMOLL, units)
val trend = Profile.toUnitsString(data.glucoseTrend * 3, data.glucoseTrend * 3 * Constants.MGDL_TO_MMOLL, profileFunction.getUnits())
val trend = Profile.toUnitsString(data.glucoseTrend * 3, data.glucoseTrend * 3 * Constants.MGDL_TO_MMOLL, units)
// BG
binding.bg.text = rh.gs(R.string.format_bg_isf, bgString, isf)
binding.bgInsulin.text = rh.gs(R.string.formatinsulinunits, data.glucoseInsulin)

View file

@ -1,12 +1,18 @@
package info.nightscout.androidaps.plugins.general.overview.activities
import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.ItemTouchHelper.*
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import info.nightscout.androidaps.R
@ -20,6 +26,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.rxkotlin.plusAssign
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import javax.inject.Inject
@ -30,20 +38,95 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var quickWizard: QuickWizard
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var sp: SP
private var disposable: CompositeDisposable = CompositeDisposable()
private lateinit var binding: OverviewQuickwizardlistActivityBinding
private val itemTouchHelper by lazy {
val simpleItemTouchCallback = object : ItemTouchHelper.SimpleCallback(UP or DOWN or START or END, 0) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val adapter = recyclerView.adapter as RecyclerViewAdapter
val from = viewHolder.layoutPosition
val to = target.layoutPosition
adapter.moveItem(from, to)
adapter.notifyItemMoved(from, to)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
if (actionState == ACTION_STATE_DRAG) {
viewHolder?.itemView?.alpha = 0.5f
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.alpha = 1.0f
val adapter = recyclerView.adapter as RecyclerViewAdapter
adapter.onDrop()
}
}
ItemTouchHelper(simpleItemTouchCallback)
}
fun startDragging(viewHolder: RecyclerView.ViewHolder) {
itemTouchHelper.startDrag(viewHolder)
}
private inner class RecyclerViewAdapter(var fragmentManager: FragmentManager) : RecyclerView.Adapter<RecyclerViewAdapter.QuickWizardEntryViewHolder>() {
@SuppressLint("ClickableViewAccessibility")
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickWizardEntryViewHolder {
return QuickWizardEntryViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.overview_quickwizardlist_item, parent, false), fragmentManager)
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.overview_quickwizardlist_item, parent, false)
val viewHolder = QuickWizardEntryViewHolder(itemView, fragmentManager)
viewHolder.handleView.setOnTouchListener { _, event ->
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
startDragging(viewHolder)
}
return@setOnTouchListener true
}
return viewHolder
}
override fun onBindViewHolder(holder: QuickWizardEntryViewHolder, position: Int) {
holder.from.text = dateUtil.timeString(quickWizard[position].validFromDate())
holder.to.text = dateUtil.timeString(quickWizard[position].validToDate())
val wearControl = sp.getBoolean(R.string.key_wear_control, false)
if (wearControl) {
holder.handleView.visibility = View.VISIBLE
} else {
holder.handleView.visibility = View.GONE
}
if (quickWizard[position].device() == QuickWizardEntry.DEVICE_ALL) {
holder.device.visibility = View.GONE
} else {
holder.device.visibility = View.VISIBLE
holder.device.setImageResource(
when (quickWizard[position].device()) {
QuickWizardEntry.DEVICE_WATCH -> R.drawable.ic_watch
else -> R.drawable.ic_smartphone
}
)
}
holder.buttonText.text = quickWizard[position].buttonText()
holder.carbs.text = rh.gs(R.string.format_carbs, quickWizard[position].carbs())
}
@ -55,6 +138,8 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
val buttonText: TextView = itemView.findViewById(R.id.overview_quickwizard_item_buttonText)
val carbs: TextView = itemView.findViewById(R.id.overview_quickwizard_item_carbs)
val from: TextView = itemView.findViewById(R.id.overview_quickwizard_item_from)
val handleView: ImageView = itemView.findViewById(R.id.handleView)
val device: ImageView = itemView.findViewById(R.id.overview_quickwizard_item_device)
val to: TextView = itemView.findViewById(R.id.overview_quickwizard_item_to)
private val editButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_edit_button)
private val removeButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_remove_button)
@ -74,6 +159,16 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
}
}
}
fun moveItem(from: Int, to: Int) {
Log.i("QuickWizard", "moveItem")
quickWizard.move(from, to)
}
fun onDrop() {
Log.i("QuickWizard", "onDrop")
rxBus.send(EventQuickWizardChange())
}
}
override fun onCreate(savedInstanceState: Bundle?) {
@ -84,6 +179,7 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(this)
binding.recyclerview.adapter = RecyclerViewAdapter(supportFragmentManager)
itemTouchHelper.attachToRecyclerView(binding.recyclerview)
binding.addButton.setOnClickListener {
val manager = supportFragmentManager
@ -98,13 +194,13 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
.toObservable(EventQuickWizardChange::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({
val adapter = RecyclerViewAdapter(supportFragmentManager)
binding.recyclerview.swapAdapter(adapter, false)
}, fabricPrivacy::logException)
val adapter = RecyclerViewAdapter(supportFragmentManager)
binding.recyclerview.swapAdapter(adapter, false)
}, fabricPrivacy::logException)
}
override fun onPause() {
disposable.clear()
super.onPause()
}
}
}

View file

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

View file

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

View file

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

View file

@ -121,6 +121,7 @@ class LocalProfileFragment : DaggerFragment() {
processVisibilityOnClick(it)
binding.target.visibility = View.VISIBLE
}
binding.dia.editText?.id?.let { binding.diaLabel.labelFor = it }
}
fun build() {

View file

@ -112,7 +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));
finalAdd.setContentDescription(layout.getContext().getResources().getString(R.string.a11y_add_new_to_list));
LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams((int) (35d * factor), (int) (35 * factor));
illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom);
illp.gravity = Gravity.CENTER;

View file

@ -18,6 +18,8 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertOrUpdateBolusCalculatorResultTransaction
import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.extensions.highValueToUnitsToString
import info.nightscout.androidaps.extensions.lowValueToUnitsToString
import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
@ -135,27 +137,28 @@ class BolusWizard @Inject constructor(
private var quickWizard: Boolean = true
var usePercentage: Boolean = false
fun doCalc(profile: Profile,
profileName: String,
tempTarget: TemporaryTarget?,
carbs: Int,
cob: Double,
bg: Double,
correction: Double,
percentageCorrection: Int = 100,
useBg: Boolean,
useCob: Boolean,
includeBolusIOB: Boolean,
includeBasalIOB: Boolean,
useSuperBolus: Boolean,
useTT: Boolean,
useTrend: Boolean,
useAlarm: Boolean,
notes: String = "",
carbTime: Int = 0,
usePercentage: Boolean = false,
totalPercentage: Double = 100.0,
quickWizard: Boolean = false
fun doCalc(
profile: Profile,
profileName: String,
tempTarget: TemporaryTarget?,
carbs: Int,
cob: Double,
bg: Double,
correction: Double,
percentageCorrection: Int = 100,
useBg: Boolean,
useCob: Boolean,
includeBolusIOB: Boolean,
includeBasalIOB: Boolean,
useSuperBolus: Boolean,
useTT: Boolean,
useTrend: Boolean,
useAlarm: Boolean,
notes: String = "",
carbTime: Int = 0,
usePercentage: Boolean = false,
totalPercentage: Double = 100.0,
quickWizard: Boolean = false
): BolusWizard {
this.profile = profile
@ -314,7 +317,9 @@ class BolusWizard @Inject constructor(
actions.add(rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs).formatColor(rh, R.color.carbs) + timeShift)
}
if (insulinFromCOB > 0) {
actions.add(rh.gs(R.string.cobvsiob) + ": " + rh.gs(R.string.formatsignedinsulinunits, insulinFromBolusIOB + insulinFromBasalIOB + insulinFromCOB + insulinFromBG).formatColor(rh, R.color.cobAlert))
actions.add(
rh.gs(R.string.cobvsiob) + ": " + rh.gs(R.string.formatsignedinsulinunits, insulinFromBolusIOB + insulinFromBasalIOB + insulinFromCOB + insulinFromBG).formatColor(rh, R.color.cobAlert)
)
val absorptionRate = iobCobCalculator.ads.slowAbsorptionPercentage(60)
if (absorptionRate > .25)
actions.add(rh.gs(R.string.slowabsorptiondetected, rh.gc(R.color.cobAlert), (absorptionRate * 100).toInt()))
@ -344,8 +349,8 @@ class BolusWizard @Inject constructor(
carbTimer.removeEatReminder()
if (sp.getBoolean(R.string.key_usebolusadvisor, false) && Profile.toMgdl(bg, profile.units) > 180 && carbs > 0 && carbTime >= 0)
OKDialog.showYesNoCancel(ctx, rh.gs(R.string.bolusadvisor), rh.gs(R.string.bolusadvisormessage),
{ bolusAdvisorProcessing(ctx) },
{ commonProcessing(ctx) }
{ bolusAdvisorProcessing(ctx) },
{ commonProcessing(ctx) }
)
else
commonProcessing(ctx)
@ -367,10 +372,13 @@ class BolusWizard @Inject constructor(
carbTime = 0
bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes
uel.log(Action.BOLUS_ADVISOR, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
uel.log(
Action.BOLUS_ADVISOR,
if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
notes,
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
ValueWithUnit.Insulin(insulinAfterConstraints))
ValueWithUnit.Insulin(insulinAfterConstraints)
)
if (insulin > 0) {
commandQueue.bolus(this, object : Callback() {
override fun run() {
@ -385,6 +393,26 @@ class BolusWizard @Inject constructor(
})
}
fun explainShort(): String {
var message = rh.gs(R.string.wizard_explain_calc, ic, sens)
message += "\n" + rh.gs(R.string.wizard_explain_carbs, insulinFromCarbs)
if (useTT && tempTarget != null) {
val tt = if (tempTarget?.lowTarget == tempTarget?.highTarget) tempTarget?.lowValueToUnitsToString(profile.units)
else rh.gs(R.string.wizard_explain_tt_to, tempTarget?.lowValueToUnitsToString(profile.units), tempTarget?.highValueToUnitsToString(profile.units))
message += "\n" + rh.gs(R.string.wizard_explain_tt, tt)
}
if (useCob) message += "\n" + rh.gs(R.string.wizard_explain_cob, cob, insulinFromCOB)
if (useBg) message += "\n" + rh.gs(R.string.wizard_explain_bg, insulinFromBG)
if (includeBolusIOB) message += "\n" + rh.gs(R.string.wizard_explain_bolus_iob, insulinFromBolusIOB)
if (includeBasalIOB) message += "\n" + rh.gs(R.string.wizard_explain_basal_iob, insulinFromBasalIOB)
if (useTrend) message += "\n" + rh.gs(R.string.wizard_explain_trend, insulinFromTrend)
if (useSuperBolus) message += "\n" + rh.gs(R.string.wizard_explain_superbolus, insulinFromSuperBolus)
if (percentageCorrection != 100) {
message += "\n" + rh.gs(R.string.wizard_explain_percent, totalBeforePercentageAdjustment, percentageCorrection, calculatedTotalInsulin)
}
return message
}
private fun commonProcessing(ctx: Context) {
val profile = profileFunction.getProfile() ?: return
val pump = activePlugin.activePump
@ -433,17 +461,17 @@ class BolusWizard @Inject constructor(
bolusCalculatorResult = createBolusCalculatorResult()
notes = this@BolusWizard.notes
if (insulin > 0 || carbs > 0) {
val action = when {
val action = when {
insulinAfterConstraints.equals(0.0) -> Action.CARBS
carbs.equals(0.0) -> Action.BOLUS
else -> Action.TREATMENT
}
uel.log(action, if (quickWizard) Sources.QuickWizard else Sources.WizardDialog,
notes,
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 },
ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 })
notes,
ValueWithUnit.TherapyEventType(eventType.toDBbEventType()),
ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
ValueWithUnit.Gram(this@BolusWizard.carbs).takeIf { this@BolusWizard.carbs != 0 },
ValueWithUnit.Minute(carbTime).takeIf { carbTime != 0 })
commandQueue.bolus(this, object : Callback() {
override fun run() {
if (!result.success) {
@ -469,9 +497,9 @@ class BolusWizard @Inject constructor(
private fun calcPercentageWithConstraints() {
calculatedPercentage = 100.0
if (totalBeforePercentageAdjustment != insulinFromCorrection)
calculatedPercentage = calculatedTotalInsulin/(totalBeforePercentageAdjustment-insulinFromCorrection) * 100
calculatedPercentage = calculatedTotalInsulin / (totalBeforePercentageAdjustment - insulinFromCorrection) * 100
calculatedPercentage = max(calculatedPercentage, 10.0)
calculatedPercentage = min(calculatedPercentage,250.0)
calculatedPercentage = min(calculatedPercentage, 250.0)
}
private fun calcCorrectionWithConstraints() {
@ -481,4 +509,4 @@ class BolusWizard @Inject constructor(
calculatedCorrection = max(-constraintChecker.getMaxBolusAllowed().value(), calculatedCorrection)
}
}
}

View file

@ -1,10 +1,12 @@
package info.nightscout.androidaps.utils.wizard
import android.util.Log
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONObject
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@ -18,6 +20,18 @@ class QuickWizard @Inject constructor(
init {
setData(JSONArray(sp.getString(R.string.key_quickwizard, "[]")))
setGuidsForOldEntries()
}
private fun setGuidsForOldEntries() {
// for migration purposes; guid is a new required property
for (i in 0 until storage.length()) {
val entry = QuickWizardEntry(injector).from(storage.get(i) as JSONObject, i)
if (entry.guid() == "") {
val guid = UUID.randomUUID().toString()
entry.storage.put("guid", guid)
}
}
}
fun getActive(): QuickWizardEntry? {
@ -41,6 +55,38 @@ class QuickWizard @Inject constructor(
operator fun get(position: Int): QuickWizardEntry =
QuickWizardEntry(injector).from(storage.get(position) as JSONObject, position)
fun get(guid: String): QuickWizardEntry? {
for (i in 0 until storage.length()) {
val entry = QuickWizardEntry(injector).from(storage.get(i) as JSONObject, i)
if (entry.guid() == guid) {
return entry
}
}
return null
}
fun move(from: Int, to: Int) {
Log.i("QuickWizard", "moveItem: $from $to")
val fromEntry = storage[from] as JSONObject
storage.remove(from)
addToPos(to, fromEntry, storage)
save()
}
fun removePos(pos: Int, jsonObj: JSONObject?, jsonArr: JSONArray) {
for (i in jsonArr.length() downTo pos + 1) {
jsonArr.put(i, jsonArr[i - 1])
}
jsonArr.put(pos, jsonObj)
}
private fun addToPos(pos: Int, jsonObj: JSONObject?, jsonArr: JSONArray) {
for (i in jsonArr.length() downTo pos + 1) {
jsonArr.put(i, jsonArr[i - 1])
}
jsonArr.put(pos, jsonObj)
}
fun newEmptyItem(): QuickWizardEntry {
return QuickWizardEntry(injector)
}
@ -57,4 +103,5 @@ class QuickWizard @Inject constructor(
storage.remove(position)
save()
}
}

View file

@ -19,6 +19,7 @@ import info.nightscout.androidaps.utils.JsonHelper.safeGetString
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONException
import org.json.JSONObject
import java.util.*
import javax.inject.Inject
class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjector) {
@ -41,11 +42,26 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
const val NO = 1
private const val POSITIVE_ONLY = 2
private const val NEGATIVE_ONLY = 3
const val DEVICE_ALL = 0
const val DEVICE_PHONE = 1
const val DEVICE_WATCH = 2
const val DEFAULT = 0
const val CUSTOM = 1
}
init {
injector.androidInjector().inject(this)
val emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}"
val guid = UUID.randomUUID().toString()
val emptyData = """{
"guid": "$guid",
"buttonText": "",
"carbs": 0,
"validFrom": 0,
"validTo": 86340,
"device": "all",
"usePercentage": "default",
"percentage": 100
}""".trimMargin()
try {
storage = JSONObject(emptyData)
} catch (e: JSONException) {
@ -55,6 +71,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
/*
{
guid: string,
device: string, // (phone, watch, all)
buttonText: "Meal",
carbs: 36,
validFrom: 8 * 60 * 60, // seconds from midnight
@ -66,15 +84,18 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
useTrend: 0,
useSuperBolus: 0,
useTemptarget: 0
usePercentage: string, // default, custom
percentage: int,
}
*/
fun from(entry: JSONObject, position: Int): QuickWizardEntry {
// TODO set guid if missing for migration
storage = entry
this.position = position
return this
}
fun isActive(): Boolean = profileFunction.secondsFromMidnight() >= validFrom() && profileFunction.secondsFromMidnight() <= validTo()
fun isActive(): Boolean = profileFunction.secondsFromMidnight() >= validFrom() && profileFunction.secondsFromMidnight() <= validTo() && forDevice(DEVICE_PHONE)
fun doCalc(profile: Profile, profileName: String, lastBG: GlucoseValue, _synchronized: Boolean): BolusWizard {
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
@ -119,10 +140,16 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
} else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.shortAvgDelta < 0) {
trend = true
}
val percentage = sp.getInt(R.string.key_boluswizard_percentage, 100)
val percentage = if (usePercentage() == DEFAULT) sp.getInt(R.string.key_boluswizard_percentage, 100) else percentage()
return BolusWizard(injector).doCalc(profile, profileName, tempTarget, carbs(), cob, bg, 0.0, percentage, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, false, buttonText(), quickWizard = true) //tbc, ok if only quickwizard, but if other sources elsewhere use Sources.QuickWizard
}
fun guid(): String = safeGetString(storage, "guid", "")
fun device(): Int = safeGetInt(storage, "device", DEVICE_ALL)
fun forDevice(device: Int) = device() == device || device() == DEVICE_ALL
fun buttonText(): String = safeGetString(storage, "buttonText", "")
fun carbs(): Int = safeGetInt(storage, "carbs")
@ -148,4 +175,8 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec
fun useSuperBolus(): Int = safeGetInt(storage, "useSuperBolus", NO)
fun useTempTarget(): Int = safeGetInt(storage, "useTempTarget", NO)
}
fun usePercentage(): Int = safeGetInt(storage, "usePercentage", DEFAULT)
fun percentage(): Int = safeGetInt(storage, "percentage", 100)
}

View file

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

View file

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

View file

@ -93,6 +93,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/time_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
@ -105,25 +106,24 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small"
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
android:id="@+id/alarmCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
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>
<info.nightscout.androidaps.utils.ui.MinutesNumberPicker
android:id="@+id/time"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/time_offset" />
<TextView
android:layout_width="wrap_content"
@ -143,6 +143,7 @@
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -156,7 +157,8 @@
android:id="@+id/duration"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal" />
android:layout_gravity="center_horizontal"
app:customContentDescription="@string/careportal_newnstreatment_duration_label" />
<TextView
android:layout_width="wrap_content"
@ -176,6 +178,7 @@
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/carbs_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -190,7 +193,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/carbs"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_carbs_label" />
<TextView
android:layout_width="wrap_content"

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -63,6 +63,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/insulin_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -75,7 +76,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/insulin"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/overview_insulin_label" />
<TextView
android:layout_width="wrap_content"
@ -96,6 +98,7 @@
android:orientation="horizontal">
<TextView
android:id="@+id/carbs_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -108,7 +111,8 @@
<info.nightscout.androidaps.utils.ui.NumberPicker
android:id="@+id/carbs"
android:layout_width="130dp"
android:layout_height="40dp" />
android:layout_height="40dp"
app:customContentDescription="@string/treatments_wizard_carbs_label" />
<TextView
android:layout_width="wrap_content"

View file

@ -22,6 +22,7 @@
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:labelFor="@+id/spinner"
android:text="@string/selected_profile"
android:textAppearance="?android:attr/textAppearanceMedium" />
@ -97,7 +98,7 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:contentDescription="@string/addnew"
android:contentDescription="@string/a11y_add_new_profile"
app:srcCompat="@drawable/ic_add" />
<ImageView
@ -106,7 +107,7 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:contentDescription="@string/clone_label"
android:contentDescription="@string/a11y_clone_profile"
app:srcCompat="@drawable/ic_clone" />
<ImageView
@ -115,7 +116,7 @@
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:contentDescription="@string/remove_label"
android:contentDescription="@string/a11y_delete_current_profile"
android:scaleX="1"
android:scaleY="1"
app:srcCompat="@drawable/ic_remove" />
@ -190,7 +191,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/dia_label"
android:text="@string/dia_long_label"
android:textColor="@android:color/white"
android:textSize="20sp" />
@ -202,6 +203,7 @@
android:paddingTop="5dp">
<TextView
android:id="@+id/dia_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
@ -214,7 +216,8 @@
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp" />
android:layout_marginBottom="10dp"
app:customContentDescription="@string/dia" />
<TextView
android:layout_width="wrap_content"

View file

@ -108,6 +108,35 @@
</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
android:layout_width="match_parent"
@ -276,7 +305,6 @@
</RadioGroup>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -301,6 +329,47 @@
</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
android:id="@+id/okcancel"

View file

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

View file

@ -313,7 +313,7 @@
<string name="wear">Wear</string>
<string name="resend_all_data">Resend All Data</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="sms_actualbg">BG:</string>
<string name="sms_lastbg">Last BG:</string>
@ -617,6 +617,7 @@
<string name="negativeonly">Negative only</string>
<string name="overview_editquickwizard_usecob">COB 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="apsselected">APS selected</string>
<string name="nsclienthaswritepermission">NSClient has write permission</string>
@ -953,8 +954,8 @@
<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="age">Age:</string>
<string name="weight_label">Weight:</string>
<string name="age">Age</string>
<string name="weight_label">Weight</string>
<string name="id">ID:</string>
<string name="submit">Submit</string>
<string name="mostcommonprofile">Most common profile:</string>
@ -1164,5 +1165,44 @@
<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>

View file

@ -41,7 +41,7 @@ buildscript {
maven { url "https://plugins.gradle.org/m2/" } // jacoco 0.2
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.1'
classpath 'com.android.tools.build:gradle:7.1.0'
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'

View file

@ -11,7 +11,6 @@
android:shape="rectangle">
<stroke android:width="1dp" android:color="@color/colorLightGray" />
<solid android:color="@android:color/white" />
<corners android:radius="4dp" />
</shape>
</item>
</layer-list>

View file

@ -1,8 +1,9 @@
<vector
android:height="48dp"
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:viewportHeight="24"
android:height="48dp"
android:viewportWidth="24"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#67DFE8" android:pathData="M18.501,12.002l-0.428,0.564L8.179,5.064c-0.092,-0.07 -0.212,-0.09 -0.323,-0.055L5.115,5.89L1.571,3.501L4.755,6.36L4.647,9.243c-0.004,0.116 0.047,0.226 0.14,0.296l9.895,7.502l-0.428,0.564c-0.26,0.343 -0.193,0.832 0.15,1.092s0.832,0.193 1.092,-0.15l1.653,-2.18l2.219,1.683l-0.719,0.948c-0.26,0.343 -0.193,0.832 0.15,1.092c0.343,0.26 0.832,0.193 1.092,-0.15l2.379,-3.138c0.26,-0.343 0.193,-0.832 -0.15,-1.092c-0.343,-0.26 -0.832,-0.193 -1.092,0.15l-0.719,0.948l-2.219,-1.683l1.653,-2.18c0.26,-0.343 0.193,-0.832 -0.15,-1.092S18.762,11.659 18.501,12.002zM5.458,6.524l2.44,-0.783l9.748,7.39L17.26,13.64l-5.754,-4.362c-0.091,-0.069 -0.221,-0.053 -0.293,0.035L9.087,11.91l-0.67,-0.508l1.526,-1.833c0.002,-0.002 0.004,-0.005 0.006,-0.008c0.068,-0.09 0.054,-0.219 -0.033,-0.291c-0.09,-0.075 -0.224,-0.063 -0.299,0.027l-1.538,1.848l-0.769,-0.583l1.526,-1.833c0.002,-0.002 0.004,-0.005 0.006,-0.008c0.068,-0.09 0.054,-0.219 -0.033,-0.291c-0.09,-0.075 -0.224,-0.063 -0.299,0.027L6.97,10.305L6.201,9.721l1.526,-1.833C7.728,7.886 7.731,7.882 7.732,7.88c0.068,-0.09 0.054,-0.219 -0.033,-0.291C7.609,7.513 7.475,7.526 7.4,7.616L5.861,9.464L5.362,9.085L5.458,6.524z"/>
android:viewportHeight="24">
<path
android:fillColor="#67DFE8"
android:pathData="M18.501,12.002l-0.428,0.564L8.179,5.064c-0.092,-0.07 -0.212,-0.09 -0.323,-0.055L5.115,5.89L1.571,3.501L4.755,6.36L4.647,9.243c-0.004,0.116 0.047,0.226 0.14,0.296l9.895,7.502l-0.428,0.564c-0.26,0.343 -0.193,0.832 0.15,1.092s0.832,0.193 1.092,-0.15l1.653,-2.18l2.219,1.683l-0.719,0.948c-0.26,0.343 -0.193,0.832 0.15,1.092c0.343,0.26 0.832,0.193 1.092,-0.15l2.379,-3.138c0.26,-0.343 0.193,-0.832 -0.15,-1.092c-0.343,-0.26 -0.832,-0.193 -1.092,0.15l-0.719,0.948l-2.219,-1.683l1.653,-2.18c0.26,-0.343 0.193,-0.832 -0.15,-1.092S18.762,11.659 18.501,12.002zM5.458,6.524l2.44,-0.783l9.748,7.39L17.26,13.64l-5.754,-4.362c-0.091,-0.069 -0.221,-0.053 -0.293,0.035L9.087,11.91l-0.67,-0.508l1.526,-1.833c0.002,-0.002 0.004,-0.005 0.006,-0.008c0.068,-0.09 0.054,-0.219 -0.033,-0.291c-0.09,-0.075 -0.224,-0.063 -0.299,0.027l-1.538,1.848l-0.769,-0.583l1.526,-1.833c0.002,-0.002 0.004,-0.005 0.006,-0.008c0.068,-0.09 0.054,-0.219 -0.033,-0.291c-0.09,-0.075 -0.224,-0.063 -0.299,0.027L6.97,10.305L6.201,9.721l1.526,-1.833C7.728,7.886 7.731,7.882 7.732,7.88c0.068,-0.09 0.054,-0.219 -0.033,-0.291C7.609,7.513 7.475,7.526 7.4,7.616L5.861,9.464L5.362,9.085L5.458,6.524z" />
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M17,1.01L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,19H7V5h10v14z"/>
</vector>

View file

@ -9,13 +9,13 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:width="120dp"
android:labelFor="@+id/eventtime"
android:paddingLeft="10dp"
android:paddingRight="4dp"
android:text="@string/event_time_label"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="bold" />
<TextView
android:id="@+id/eventdate"
android:layout_width="wrap_content"

View file

@ -27,6 +27,7 @@
<string name="key_virtualpump_type" translatable="false">virtualpump_type</string>
<string name="key_quickwizard" translatable="false">QuickWizard</string>
<string name="key_wear_control" translatable="false">wearcontrol</string>
<string name="key_units_mgdl" translatable="false">units_mgdl</string>
<string name="key_show_notes_entry_dialogs" translatable="false">show_notes_entry_dialogs</string>
<string name="key_openapsama_autosens_max" translatable="false">autosens_max</string>
<string name="key_openapsama_autosens_min" translatable="false">autosens_min</string>

View file

@ -25,7 +25,7 @@ dependencies {
api "io.reactivex.rxjava2:rxandroid:$rxandroid_version"
api("io.reactivex.rxjava2:rxkotlin:$rxkotlin_version")
api "com.google.code.gson:gson:2.8.9"
api "com.google.code.gson:gson:2.9.0"
api "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

View file

@ -30,7 +30,7 @@ android {
targetCompatibility JavaVersion.VERSION_11
}
lintOptions {
lint {
checkReleaseBuilds false
disable 'MissingTranslation'
disable 'ExtraTranslation'

View file

@ -768,7 +768,7 @@ class MedtronicPumpPlugin @Inject constructor(
medtronicPumpStatus.tempBasalAmount = absoluteRate
medtronicPumpStatus.tempBasalLength = durationInMinutes
val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType)
val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes * 60, tbrType)
medtronicPumpStatus.runningTBRWithTemp = tempData
pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this)

View file

@ -3,7 +3,11 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble
import android.annotation.SuppressLint
import android.bluetooth.*
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.SystemClock
import androidx.core.content.ContextCompat
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes
@ -32,14 +36,15 @@ import javax.inject.Singleton
* Added: State handling, configuration of RF for different configuration ranges, connection handling
*/
@Singleton
class RileyLinkBLE @Inject constructor(private val context: Context) {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rileyLinkServiceData: RileyLinkServiceData
@Inject lateinit var rileyLinkUtil: RileyLinkUtil
@Inject lateinit var sp: SP
@Inject lateinit var orangeLink: OrangeLinkImpl
class RileyLinkBLE @Inject constructor(
private val context: Context,
private val aapsLogger: AAPSLogger,
private val rileyLinkServiceData: RileyLinkServiceData,
private val rileyLinkUtil: RileyLinkUtil,
private val sp: SP,
private val orangeLink: OrangeLinkImpl,
private val config: Config
) {
private val gattDebugEnabled = true
private var manualDisconnect = false
@ -154,7 +159,12 @@ class RileyLinkBLE @Inject constructor(private val context: Context) {
aapsLogger.error(LTag.PUMPBTCOMM, "RileyLink device is null, can't do connectGatt.")
return
}
bluetoothConnectionGatt = rileyLinkDevice?.connectGatt(context, true, bluetoothGattCallback)
if (config.PUMPDRIVERS && Build.VERSION.SDK_INT >= /*Build.VERSION_CODES.S*/31 &&
ContextCompat.checkSelfPermission(context, "android.permission.BLUETOOTH_CONNECT") == PackageManager.PERMISSION_GRANTED
) {
aapsLogger.debug(LTag.PUMPBTCOMM, "no permission")
return
} else bluetoothConnectionGatt = rileyLinkDevice?.connectGatt(context, true, bluetoothGattCallback)
// , BluetoothDevice.TRANSPORT_LE
if (bluetoothConnectionGatt == null)
aapsLogger.error(LTag.PUMPBTCOMM, "Failed to connect to Bluetooth Low Energy device at " + bluetoothAdapter?.address)

View file

@ -53,7 +53,7 @@ android {
defaultConfig {
applicationId "info.nightscout.androidaps"
minSdkVersion 23
targetSdkVersion 28
targetSdkVersion 29
versionCode 2
versionName "1.0.3"
buildConfigField "String", "BUILDVERSION", generateGitBuild()
@ -107,7 +107,6 @@ dependencies {
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.wear:wear:1.2.0'
compileOnly "com.google.android.wearable:wearable:${wearableVersion}"
implementation "com.google.android.support:wearable:${wearableVersion}"
implementation "com.google.android.gms:play-services-wearable:${playServicesWearable}"
@ -115,6 +114,10 @@ dependencies {
implementation(name: 'wearpreferenceactivity-0.5.0', ext: 'aar')
implementation('com.github.lecho:hellocharts-library:1.5.8@aar')
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0'
implementation "androidx.core:core-ktx:$core_version"
implementation "androidx.wear.tiles:tiles:1.0.1"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testImplementation "junit:junit:$junit_version"

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="info.nightscout.androidaps">
<uses-feature android:name="android.hardware.type.watch" />
@ -8,6 +9,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-sdk tools:overrideLibrary="androidx.wear.tiles" />
<application
android:name=".Aaps"
@ -256,6 +258,10 @@
android:host="*"
android:pathPrefix="/openwearsettings"
android:scheme="wear" />
<data
android:host="*"
android:pathPrefix="/send_quick_wizard"
android:scheme="wear" />
<data
android:host="*"
android:pathPrefix="/sendstatustowear"
@ -508,6 +514,54 @@
android:value="0" />
</service>
<service
android:name=".tile.ActionsTileService"
android:exported="true"
android:label="@string/label_actions_tile"
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
<intent-filter>
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
</intent-filter>
<meta-data
android:name="com.google.android.clockwork.tiles.PROVIDER_CONFIG_ACTION"
android:value="tile_configuration_activity" />
<meta-data
android:name="androidx.wear.tiles.PREVIEW"
android:resource="@drawable/action_tile_preview" />
</service>
<service
android:name=".tile.TempTargetTileService"
android:exported="true"
android:label="@string/label_temp_target_tile"
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
<intent-filter>
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
</intent-filter>
<meta-data
android:name="com.google.android.clockwork.tiles.PROVIDER_CONFIG_ACTION"
android:value="tile_configuration_tempt" />
<meta-data
android:name="androidx.wear.tiles.PREVIEW"
android:resource="@drawable/temp_target_tile_preview" />
</service>
<service
android:name=".tile.QuickWizardTileService"
android:exported="true"
android:label="@string/label_quick_wizard_tile"
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
<intent-filter>
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
</intent-filter>
<meta-data
android:name="androidx.wear.tiles.PREVIEW"
android:resource="@drawable/quick_wizard_tile_preview" />
</service>
<receiver android:name=".complications.ComplicationTapBroadcastReceiver" />
<activity
@ -523,6 +577,7 @@
android:label="@string/menu_settings" />
<activity
android:name=".interaction.actions.WizardActivity"
android:exported="true"
android:label="@string/menu_wizard" />
<activity
android:name=".interaction.menus.FillMenuActivity"
@ -530,9 +585,14 @@
<activity
android:name=".interaction.menus.StatusMenuActivity"
android:label="@string/menu_status" />
<activity
android:name=".interaction.actions.TreatmentActivity"
android:exported="true"
android:label="@string/menu_treatment" />
<activity
android:name=".interaction.actions.BolusActivity"
android:label="@string/action_bolus" />
android:exported="true"
android:label="@string/action_insulin" />
<activity
android:name=".interaction.actions.CPPActivity"
android:label="@string/status_cpp" />
@ -542,14 +602,21 @@
android:launchMode="singleInstance" />
<activity
android:name=".interaction.actions.FillActivity"
android:exported="true"
android:label="@string/menu_prime_fill" />
<activity
android:name=".interaction.actions.ECarbActivity"
android:exported="true"
android:label="@string/action_carbs" />
<activity
android:name=".interaction.actions.TempTargetActivity"
android:exported="true"
android:label="@string/menu_tempt" />
<activity
android:name=".interaction.actions.BackgroundActionActivity"
android:exported="true" />
<activity android:name=".interaction.ConfigurationActivity">
<intent-filter>
<!-- action-name must be equal with name of xml-ressource where the configuration is describe -->
@ -567,5 +634,16 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".interaction.TileConfigurationActivity">
<intent-filter>
<action android:name="tile_configuration_activity" />
<action android:name="tile_configuration_tempt" />
<category android:name="com.google.android.clockwork.tiles.category.PROVIDER_CONFIG" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>

View file

@ -15,7 +15,7 @@ import javax.inject.Inject;
import dagger.android.DaggerBroadcastReceiver;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.actions.BolusActivity;
import info.nightscout.androidaps.interaction.actions.TreatmentActivity;
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
import info.nightscout.androidaps.interaction.actions.WizardActivity;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
@ -77,7 +77,7 @@ public class ComplicationTapBroadcastReceiver extends DaggerBroadcastReceiver {
intentOpen = new Intent(context, WizardActivity.class);
break;
case BOLUS:
intentOpen = new Intent(context, BolusActivity.class);
intentOpen = new Intent(context, TreatmentActivity.class);
break;
case ECARB:
intentOpen = new Intent(context, ECarbActivity.class);

View file

@ -13,18 +13,16 @@ import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.util.Base64;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.wear.tiles.TileService;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.CapabilityApi;
import com.google.android.gms.wearable.CapabilityInfo;
import com.google.android.gms.wearable.ChannelApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
@ -35,7 +33,8 @@ import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
@ -46,9 +45,11 @@ import info.nightscout.androidaps.interaction.AAPSPreferences;
import info.nightscout.androidaps.interaction.actions.AcceptActivity;
import info.nightscout.androidaps.interaction.actions.CPPActivity;
import info.nightscout.androidaps.interaction.utils.Persistence;
import info.nightscout.shared.SafeParse;
import info.nightscout.androidaps.interaction.utils.WearUtil;
import info.nightscout.androidaps.tile.ActionsTileService;
import info.nightscout.androidaps.tile.QuickWizardTileService;
import info.nightscout.androidaps.tile.TempTargetTileService;
import info.nightscout.shared.SafeParse;
/**
* Created by emmablack on 12/26/14.
@ -59,7 +60,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
@Inject WearUtil wearUtil;
@Inject Persistence persistence;
private static final String WEARABLE_DATA_PATH = "/nightscout_watch_data";
private static final String WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend";
private static final String WEARABLE_CANCELBOLUS_PATH = "/nightscout_watch_cancel_bolus";
public static final String WEARABLE_CONFIRM_ACTIONSTRING_PATH = "/nightscout_watch_confirmactionstring";
@ -68,13 +68,13 @@ public class ListenerService extends WearableListenerService implements GoogleAp
private static final String OPEN_SETTINGS = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear";
private static final String NEW_PREFERENCES_PATH = "/sendpreferencestowear";
private static final String QUICK_WIZARD_PATH = "/send_quick_wizard";
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress";
public static final String ACTION_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
public static final String NEW_CHANGECONFIRMATIONREQUEST_PATH = "/nightscout_watch_changeconfirmationrequest";
public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest";
public static final int BOLUS_PROGRESS_NOTIF_ID = 1;
public static final int CONFIRM_NOTIF_ID = 2;
public static final int CHANGE_NOTIF_ID = 556677;
@ -85,29 +85,15 @@ public class ListenerService extends WearableListenerService implements GoogleAp
private static final String ACTION_CONFIRMCHANGE = "com.dexdrip.stephenblack.nightwatch.CONFIRMCHANGE";
private static final String ACTION_INITIATE_ACTION = "com.dexdrip.stephenblack.nightwatch.INITIATE_ACTION";
private static final String ACTION_RESEND_BULK = "com.dexdrip.stephenblack.nightwatch.RESEND_BULK_DATA";
private static final String AAPS_NOTIFY_CHANNEL_ID_OPENLOOP = "AndroidAPS-OpenLoop";
private static final String AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS = "bolus progress vibration";
private static final String AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT = "bolus progress silent";
GoogleApiClient googleApiClient;
private long lastRequest = 0;
private DismissThread bolusprogressThread;
private static final String TAG = "ListenerService";
private DataRequester mDataRequester = null;
private static final int GET_CAPABILITIES_TIMEOUT_MS = 5000;
// Phone
private static final String CAPABILITY_PHONE_APP = "phone_app_sync_bgs";
private static final String MESSAGE_PATH_PHONE = "/phone_message_path";
// Wear
private static final String CAPABILITY_WEAR_APP = "wear_app_sync_bgs";
private static final String MESSAGE_PATH_WEAR = "/wear_message_path";
private final String mPhoneNodeId = null;
private String localnode = null;
private final String logPrefix = ""; // "WR: "
// Not derived from DaggerService, do injection here
@ -117,143 +103,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
super.onCreate();
}
public class DataRequester extends AsyncTask<Void, Void, Void> {
Context mContext;
String path;
byte[] payload;
DataRequester(Context context, String thispath, byte[] thispayload) {
path = thispath;
payload = thispayload;
// Log.d(TAG, logPrefix + "DataRequester DataRequester: " + thispath + " lastRequest:" + lastRequest);
}
@Override
protected Void doInBackground(Void... params) {
// Log.d(TAG, logPrefix + "DataRequester: doInBack: " + params);
try {
forceGoogleApiConnect();
DataMap datamap;
if (isCancelled()) {
Log.d(TAG, "doInBackground CANCELLED programmatically");
return null;
}
if (googleApiClient != null) {
if (!googleApiClient.isConnected())
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
}
// this code might not be needed in this way, but we need to see that later
if ((googleApiClient != null) && (googleApiClient.isConnected())) {
if ((System.currentTimeMillis() - lastRequest > 20 * 1000)) {
// enforce 20-second debounce period
lastRequest = System.currentTimeMillis();
// NodeApi.GetConnectedNodesResult nodes =
// Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
if (localnode == null || (localnode != null && localnode.isEmpty()))
setLocalNodeName();
CapabilityInfo capabilityInfo = getCapabilities();
int count = 0;
Node phoneNode = null;
if (capabilityInfo != null) {
phoneNode = updatePhoneSyncBgsCapability(capabilityInfo);
count = capabilityInfo.getNodes().size();
}
Log.d(TAG, "doInBackground connected. CapabilityApi.GetCapabilityResult mPhoneNodeID="
+ (phoneNode != null ? phoneNode.getId() : "") + " count=" + count + " localnode="
+ localnode);// KS
if (count > 0) {
for (Node node : capabilityInfo.getNodes()) {
// Log.d(TAG, "doInBackground path: " + path);
switch (path) {
// simple send as is payloads
case WEARABLE_RESEND_PATH:
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(),
WEARABLE_RESEND_PATH, null);
break;
case WEARABLE_DATA_PATH:
case WEARABLE_CANCELBOLUS_PATH:
case WEARABLE_CONFIRM_ACTIONSTRING_PATH:
case WEARABLE_INITIATE_ACTIONSTRING_PATH:
case OPEN_SETTINGS:
case NEW_STATUS_PATH:
case NEW_PREFERENCES_PATH:
case BASAL_DATA_PATH:
case BOLUS_PROGRESS_PATH:
case ACTION_CONFIRMATION_REQUEST_PATH:
case NEW_CHANGECONFIRMATIONREQUEST_PATH:
case ACTION_CANCELNOTIFICATION_REQUEST_PATH: {
Log.w(TAG, logPrefix + "Unhandled path");
// sendMessagePayload(node, path, path, payload);
}
default:// SYNC_ALL_DATA
// this fall through is messy and non-deterministic for new paths
}
}
} else {
Log.d(TAG, logPrefix + "doInBackground connected but getConnectedNodes returns 0.");
}
} else {
// no resend
Log.d(TAG, logPrefix + "Inside the timeout, will not be executed");
}
} else {
Log.d(TAG, logPrefix + "Not connected for sending: api "
+ ((googleApiClient == null) ? "is NULL!" : "not null"));
if (googleApiClient != null) {
googleApiClient.connect();
} else {
googleApiConnect();
}
}
} catch (Exception ex) {
Log.e(TAG, logPrefix + "Error executing DataRequester in background. Exception: " + ex.getMessage());
}
return null;
}
}
public CapabilityInfo getCapabilities() {
CapabilityApi.GetCapabilityResult capabilityResult = Wearable.CapabilityApi.getCapability(googleApiClient,
CAPABILITY_PHONE_APP, CapabilityApi.FILTER_REACHABLE).await(GET_CAPABILITIES_TIMEOUT_MS,
TimeUnit.MILLISECONDS);
if (!capabilityResult.getStatus().isSuccess()) {
Log.e(TAG, logPrefix + "doInBackground Failed to get capabilities, status: "
+ capabilityResult.getStatus().getStatusMessage());
return null;
}
return capabilityResult.getCapability();
}
public class BolusCancelTask extends AsyncTask<Void, Void, Void> {
Context mContext;
@ -263,8 +112,11 @@ public class ListenerService extends WearableListenerService implements GoogleAp
@Override
protected Void doInBackground(Void... params) {
// Log.d(TAG, logPrefix + "BolusCancelTask: doInBack: " + params);
Log.d(TAG, logPrefix + "BolusCancelTask.doInBackground: " + params);
if (!googleApiClient.isConnected()) {
Log.i(TAG, "BolusCancelTask.doInBackground: not connected");
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
}
if (googleApiClient.isConnected()) {
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
@ -272,16 +124,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_CANCELBOLUS_PATH, null);
}
} else {
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
if (googleApiClient.isConnected()) {
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_CANCELBOLUS_PATH, null);
}
}
}
return null;
}
@ -300,9 +142,12 @@ public class ListenerService extends WearableListenerService implements GoogleAp
@Override
protected Void doInBackground(Void... params) {
Log.i(TAG, "MessageActionTask.doInBackground: ");
forceGoogleApiConnect();
if (!googleApiClient.isConnected()) {
Log.i(TAG, "MessageActionTask.doInBackground: not connected");
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
}
if (googleApiClient.isConnected()) {
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
@ -310,22 +155,42 @@ public class ListenerService extends WearableListenerService implements GoogleAp
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), mMessagePath, mActionstring.getBytes());
}
} else {
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
if (googleApiClient.isConnected()) {
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), mMessagePath, mActionstring.getBytes());
}
}
}
return null;
}
}
public class ResendDataTask extends AsyncTask<Void, Void, Void> {
Context mContext;
ResendDataTask(Context context) {
mContext = context;
}
@Override
protected Void doInBackground(Void... params) {
Log.d(TAG, logPrefix + "ResendDataTask.doInBackground: " + params);
if (!googleApiClient.isConnected()) {
Log.i(TAG, "ResendDataTask.doInBackground: not connected");
googleApiClient.blockingConnect(15, TimeUnit.SECONDS);
}
if (googleApiClient.isConnected()) {
Log.i(TAG, "ResendDataTask.doInBackground: connected");
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), WEARABLE_RESEND_PATH, null);
}
} else {
Log.i(TAG, "ResendDataTask.doInBackground: could not connect");
}
return null;
}
}
public void requestData() {
sendData(WEARABLE_RESEND_PATH, null);
new ResendDataTask(this).execute();
}
public void cancelBolus() {
@ -340,59 +205,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
new MessageActionTask(this, WEARABLE_INITIATE_ACTIONSTRING_PATH, actionstring).execute();
}
private Node updatePhoneSyncBgsCapability(CapabilityInfo capabilityInfo) {
// Log.d(TAG, "CapabilityInfo: " + capabilityInfo);
Set<Node> connectedNodes = capabilityInfo.getNodes();
return pickBestNode(connectedNodes);
// mPhoneNodeId = pickBestNodeId(connectedNodes);
}
private Node pickBestNode(Set<Node> nodes) {
Node bestNode = null;
// Find a nearby node or pick one arbitrarily
for (Node node : nodes) {
if (node.isNearby()) {
return node;
}
bestNode = node;
}
return bestNode;
}
private synchronized void sendData(String path, byte[] payload) {
// Log.d(TAG, "WR: sendData: path: " + path + ", payload=" + payload);
if (path == null)
return;
if (mDataRequester != null) {
// Log.d(TAG, logPrefix + "sendData DataRequester != null lastRequest:" +
// WearUtil.dateTimeText(lastRequest));
if (mDataRequester.getStatus() != AsyncTask.Status.FINISHED) {
// Log.d(TAG, logPrefix + "sendData Should be canceled? Let run 'til finished.");
// mDataRequester.cancel(true);
}
}
Log.d(TAG,
logPrefix + "sendData: execute lastRequest:" + wearUtil.dateTimeText(lastRequest));
mDataRequester = (DataRequester) new DataRequester(this, path, payload).execute();
// executeTask(mDataRequester);
// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Log.d(TAG, "sendData SDK < M call execute lastRequest:" + WearUtil.dateTimeText(lastRequest));
// mDataRequester = (DataRequester) new DataRequester(this, path, payload).execute();
// } else {
// Log.d(TAG, "sendData SDK >= M call executeOnExecutor lastRequest:" + WearUtil.dateTimeText(lastRequest));
// // TODO xdrip executor
// mDataRequester = (DataRequester) new DataRequester(this, path, payload).executeOnExecutor(xdrip.executor);
// }
}
private void googleApiConnect() {
if (googleApiClient != null) {
// Remove old listener(s)
@ -416,20 +228,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
Wearable.MessageApi.addListener(googleApiClient, this);
}
private void forceGoogleApiConnect() {
if (googleApiClient == null || (!googleApiClient.isConnected() && !googleApiClient.isConnecting())) {
try {
Log.d(TAG, "forceGoogleApiConnect: forcing google api reconnection");
googleApiConnect();
Thread.sleep(2000);
} catch (InterruptedException e) {
//
}
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
@ -483,7 +281,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
return START_STICKY;
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
@ -541,12 +338,62 @@ public class ListenerService extends WearableListenerService implements GoogleAp
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
} else if (path.equals(NEW_PREFERENCES_PATH)) {
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
if (dataMap.containsKey("wearcontrol")) {
boolean wearcontrol = dataMap.getBoolean("wearcontrol", false);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("wearcontrol", wearcontrol);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
String keyControl = getString(R.string.key_wear_control);
if (dataMap.containsKey(keyControl)) {
boolean previousWearControl = sharedPreferences.getBoolean(keyControl, false);
boolean wearControl = dataMap.getBoolean(keyControl, false);
editor.putBoolean(keyControl, wearControl);
editor.apply();
if (wearControl != previousWearControl) {
updateTiles();
}
}
String keyPercentage = getString(R.string.key_boluswizard_percentage);
if (dataMap.containsKey(keyPercentage)) {
int wpercentage = dataMap.getInt(keyPercentage, 100);
editor.putInt(keyPercentage, wpercentage);
editor.apply();
}
String keyUnits = getString(R.string.key_units_mgdl);
if (dataMap.containsKey(keyUnits)) {
boolean mgdl = dataMap.getBoolean(keyUnits, true);
editor.putBoolean(keyUnits, mgdl);
editor.apply();
}
String keyMaxCarbs = getString(R.string.key_treatmentssafety_maxcarbs);
if (dataMap.containsKey(keyMaxCarbs)) {
int maxCarbs = dataMap.getInt(keyMaxCarbs, 48);
editor.putInt(keyMaxCarbs, maxCarbs);
editor.apply();
}
String keyMaxBolus = getString(R.string.key_treatmentssafety_maxbolus);
if (dataMap.containsKey(keyMaxBolus)) {
float maxBolus = (float)dataMap.getDouble(keyMaxBolus, 3.0f);
editor.putFloat(keyMaxBolus, maxBolus);
editor.apply();
}
} else if (path.equals(QUICK_WIZARD_PATH)) {
dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
Log.i(TAG, "onDataChanged: QUICK_WIZARD_PATH" + dataMap);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
dataMap.remove("timestamp");
String key = getString(R.string.key_quick_wizard_data_map);
String dataString = Base64.encodeToString(dataMap.toByteArray(), Base64.DEFAULT);
if (!dataString.equals(sharedPreferences.getString(key, ""))) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(key, dataString);
editor.apply();
// Todo maybe add debounce function, due to 20 seconds update limit?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
TileService.getUpdater(this)
.requestUpdate(QuickWizardTileService.class);
}
Log.i(TAG, "onDataChanged: updated QUICK_WIZARD");
} else {
Log.i(TAG, "onDataChanged: ignore update");
}
} else if (path.equals(NEW_CHANGECONFIRMATIONREQUEST_PATH)) {
String title = DataMapItem.fromDataItem(event.getDataItem()).getDataMap().getString("title");
@ -568,6 +415,19 @@ public class ListenerService extends WearableListenerService implements GoogleAp
}
}
private void updateTiles() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
TileService.getUpdater(this)
.requestUpdate(ActionsTileService.class);
TileService.getUpdater(this)
.requestUpdate(TempTargetTileService.class);
TileService.getUpdater(this)
.requestUpdate(QuickWizardTileService.class);
}
}
private void notifyChangeRequest(String title, String message, String actionstring) {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
@ -639,7 +499,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp
PendingIntent cancelPendingIntent = PendingIntent.getService(this, 0, cancelIntent, 0);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, vibrate ? AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS: AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT)
new NotificationCompat.Builder(this, vibrate ? AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS : AAPS_NOTIFY_CHANNEL_ID_BOLUSPROGRESS_SILENT)
.setSmallIcon(R.drawable.ic_icon)
.setContentTitle(getString(R.string.bolus_progress))
.setContentText(progresspercent + "% - " + progresstatus)
@ -696,7 +556,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
bolusprogressThread.start();
}
private class DismissThread extends Thread {
private final int notificationID;
private final int seconds;
@ -730,7 +589,7 @@ public class ListenerService extends WearableListenerService implements GoogleAp
context.startService(intent);
}
public static void initiateAction(Context context, String actionstring) {
public static void initiateAction(Context context, @NotNull String actionstring) {
Intent intent = new Intent(context, ListenerService.class);
intent.putExtra("actionstring", actionstring);
intent.setAction(ACTION_INITIATE_ACTION);
@ -753,20 +612,8 @@ public class ListenerService extends WearableListenerService implements GoogleAp
public void onConnected(Bundle bundle) {
// Log.d(TAG, logPrefix + "onConnected call requestData");
CapabilityApi.CapabilityListener capabilityListener = new CapabilityApi.CapabilityListener() {
@Override
public void onCapabilityChanged(CapabilityInfo capabilityInfo) {
updatePhoneSyncBgsCapability(capabilityInfo);
Log.d(TAG, logPrefix + "onConnected onCapabilityChanged mPhoneNodeID:" + mPhoneNodeId
+ ", Capability: " + capabilityInfo);
}
};
Wearable.CapabilityApi.addCapabilityListener(googleApiClient, capabilityListener, CAPABILITY_PHONE_APP);
Wearable.ChannelApi.addListener(googleApiClient, this);
requestData();
// requestData();
}
@Override
@ -779,28 +626,6 @@ public class ListenerService extends WearableListenerService implements GoogleAp
}
private void setLocalNodeName() {
forceGoogleApiConnect();
PendingResult<NodeApi.GetLocalNodeResult> result = Wearable.NodeApi.getLocalNode(googleApiClient);
result.setResultCallback(new ResultCallback<NodeApi.GetLocalNodeResult>() {
@Override
public void onResult(NodeApi.GetLocalNodeResult getLocalNodeResult) {
if (!getLocalNodeResult.getStatus().isSuccess()) {
Log.e(TAG, "ERROR: failed to getLocalNode Status="
+ getLocalNodeResult.getStatus().getStatusMessage());
} else {
Log.d(TAG, "getLocalNode Status=: " + getLocalNodeResult.getStatus().getStatusMessage());
Node getnode = getLocalNodeResult.getNode();
localnode = getnode != null ? getnode.getDisplayName() + "|" + getnode.getId() : "";
Log.d(TAG, "setLocalNodeName. localnode=" + localnode);
}
}
});
}
@Override
public void onDestroy() {
super.onDestroy();

View file

@ -5,6 +5,8 @@ import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import androidx.core.content.ContextCompat;
import info.nightscout.androidaps.R;
import preference.WearPreferenceActivity;
@ -14,21 +16,15 @@ public class AAPSPreferences extends WearPreferenceActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
ViewGroup view = (ViewGroup)getWindow().getDecorView();
ViewGroup view = (ViewGroup) getWindow().getDecorView();
removeBackgroundRecursively(view);
view.setBackground(getResources().getDrawable(R.drawable.settings_background));
view.setBackground(ContextCompat.getDrawable(this, R.drawable.settings_background));
view.requestFocus();
}
@Override
protected void onPause(){
super.onPause();
finish();
}
void removeBackgroundRecursively(View parent) {
if (parent instanceof ViewGroup) {
ViewGroup group = (ViewGroup)parent;
ViewGroup group = (ViewGroup) parent;
for (int i = 0; i < group.getChildCount(); i++) {
removeBackgroundRecursively(group.getChildAt(i));
}
@ -36,5 +32,4 @@ public class AAPSPreferences extends WearPreferenceActivity {
parent.setBackground(null);
}
}
}

View file

@ -5,6 +5,9 @@ import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import androidx.core.content.ContextCompat;
import info.nightscout.androidaps.R;
import preference.WearPreferenceActivity;
@ -14,14 +17,14 @@ public class ConfigurationActivity extends WearPreferenceActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Watchface");
String configFileName=getIntent().getAction();
String configFileName = getIntent().getAction();
int resXmlId = getResources().getIdentifier(configFileName, "xml", getApplicationContext().getPackageName());
Log.d("ConfigurationActivity::onCreate --->> getIntent().getAction()",configFileName);
Log.d("ConfigurationActivity::onCreate --->> resXmlId",String.valueOf(resXmlId));
Log.d("ConfigurationActivity::onCreate --->> getIntent().getAction()", configFileName);
Log.d("ConfigurationActivity::onCreate --->> resXmlId", String.valueOf(resXmlId));
addPreferencesFromResource(resXmlId);
ViewGroup view = (ViewGroup) getWindow().getDecorView();
removeBackgroundRecursively(view);
view.setBackground(getResources().getDrawable(R.drawable.settings_background));
view.setBackground(ContextCompat.getDrawable(this, R.drawable.settings_background));
view.requestFocus();
}
@ -41,5 +44,4 @@ public class ConfigurationActivity extends WearPreferenceActivity {
parent.setBackground(null);
}
}

View file

@ -0,0 +1,44 @@
package info.nightscout.androidaps.interaction
import android.os.Bundle
import android.util.Log
import android.view.ViewGroup
import androidx.wear.tiles.TileService
import preference.WearPreferenceActivity
import info.nightscout.androidaps.tile.ActionsTileService
import info.nightscout.androidaps.tile.TempTargetTileService
var TAG = "ASTAG-config"
class TileConfigurationActivity : WearPreferenceActivity() {
private var configFileName: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
title = "Tile"
configFileName = intent.action
val resXmlId = resources.getIdentifier(configFileName, "xml", applicationContext.packageName)
Log.d("ConfigurationActivity::onCreate --->> getIntent().getAction()", configFileName!!)
Log.d("ConfigurationActivity::onCreate --->> resXmlId", resXmlId.toString())
addPreferencesFromResource(resXmlId)
val view = window.decorView as ViewGroup
view.requestFocus()
}
override fun onDestroy() {
super.onDestroy()
// Note that TileService updates are hard limited to once every 20 seconds.
if (configFileName === "tile_configuration_activity") {
Log.i(TAG, "onDestroy a: requestUpdate!!")
TileService.getUpdater(this)
.requestUpdate(ActionsTileService::class.java)
} else if (configFileName === "tile_configuration_tempt") {
Log.i(TAG, "onDestroy tt: requestUpdate!!")
TileService.getUpdater(this)
.requestUpdate(TempTargetTileService::class.java)
} else {
Log.i(TAG, "onDestroy : NO tile service available for $configFileName")
}
}
}

View file

@ -103,12 +103,9 @@ public class AcceptActivity extends ViewSelectorActivity {
} else {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ListenerService.confirmAction(AcceptActivity.this, actionstring);
finishAffinity();
}
confirmbutton.setOnClickListener((View v) -> {
ListenerService.confirmAction(AcceptActivity.this, actionstring);
finishAffinity();
});
container.addView(view);
return view;

View file

@ -0,0 +1,29 @@
package info.nightscout.androidaps.interaction.actions
import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import info.nightscout.androidaps.data.ListenerService
const val TAG = "QuickWizard"
class BackgroundActionActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val actionString = intent.extras?.getString("actionString")
Log.i(TAG, "QuickWizardActivity.onCreate: actionString=$actionString")
if (actionString != null) {
ListenerService.initiateAction(this, actionString)
val message = intent.extras?.getString("message")
if (message != null) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}
} else {
Log.e(TAG, "BackgroundActionActivity.onCreate extras 'actionString' required")
}
finishAffinity()
}
}

View file

@ -1,6 +1,8 @@
package info.nightscout.androidaps.interaction.actions;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.wearable.view.GridPagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
@ -14,19 +16,17 @@ import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
import info.nightscout.shared.SafeParse;
/**
* Created by adrian on 09/02/17.
*/
public class BolusActivity extends ViewSelectorActivity {
PlusMinusEditText editCarbs;
PlusMinusEditText editInsulin;
float maxBolus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setAdapter(new MyGridViewPagerAdapter());
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
maxBolus = sp.getFloat(getString(R.string.key_treatmentssafety_maxbolus), 3f);
}
@Override
@ -35,11 +35,10 @@ public class BolusActivity extends ViewSelectorActivity {
finish();
}
private class MyGridViewPagerAdapter extends GridPagerAdapter {
@Override
public int getColumnCount(int arg0) {
return 3;
return 2;
}
@Override
@ -56,35 +55,20 @@ public class BolusActivity extends ViewSelectorActivity {
if (editInsulin != null) {
def = SafeParse.stringToDouble(editInsulin.editText.getText().toString());
}
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 30d, 0.1d, new DecimalFormat("#0.0"), false);
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxBolus, 0.1d, new DecimalFormat("#0.0"),false);
setLabelToPlusMinusView(view, getString(R.string.action_insulin));
container.addView(view);
view.requestFocus();
return view;
} else if (col == 1) {
final View view = getInflatedPlusMinusView(container);
double def = 0;
if (editCarbs != null) {
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
}
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 150d, 1d, new DecimalFormat("0"), false);
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
container.addView(view);
return view;
} else {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "bolus " + SafeParse.stringToDouble(editInsulin.editText.getText().toString())
+ " " + SafeParse.stringToInt(editCarbs.editText.getText().toString());
ListenerService.initiateAction(BolusActivity.this, actionstring);
finishAffinity();
}
confirmbutton.setOnClickListener((View v) -> {
String actionstring = "bolus " + SafeParse.stringToDouble(editInsulin.editText.getText().toString())
+ " 0"; // Zero carbs
ListenerService.initiateAction(BolusActivity.this, actionstring);
confirmAction(BolusActivity.this, R.string.action_bolus_confirmation);
finishAffinity();
});
container.addView(view);
return view;
@ -93,8 +77,6 @@ public class BolusActivity extends ViewSelectorActivity {
@Override
public void destroyItem(ViewGroup container, int row, int col, Object view) {
// Handle this to get the data before the view is destroyed?
// Object should still be kept by this, just setup for reinit?
container.removeView((View) view);
}

View file

@ -89,18 +89,15 @@ public class CPPActivity extends ViewSelectorActivity {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
confirmbutton.setOnClickListener((View v) -> {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "cppset " + SafeParse.stringToInt(editTimeshift.editText.getText().toString())
+ " " + SafeParse.stringToInt(editPercentage.editText.getText().toString());
ListenerService.initiateAction(CPPActivity.this, actionstring);
finishAffinity();
}
String actionstring = "cppset " + SafeParse.stringToInt(editTimeshift.editText.getText().toString())
+ " " + SafeParse.stringToInt(editPercentage.editText.getText().toString());
ListenerService.initiateAction(CPPActivity.this, actionstring);
confirmAction(CPPActivity.this, R.string.action_cpp_confirmation);
finishAffinity();
});
container.addView(view);
return view;

View file

@ -1,6 +1,8 @@
package info.nightscout.androidaps.interaction.actions;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.wearable.view.GridPagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
@ -23,11 +25,14 @@ public class ECarbActivity extends ViewSelectorActivity {
PlusMinusEditText editCarbs;
PlusMinusEditText editStartTime;
PlusMinusEditText editDuration;
int maxCarbs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setAdapter(new MyGridViewPagerAdapter());
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
}
@Override
@ -56,7 +61,7 @@ public class ECarbActivity extends ViewSelectorActivity {
if (editCarbs != null) {
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
}
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 150d, 1d, new DecimalFormat("0"), true);
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxCarbs, 1d, new DecimalFormat("0"), true);
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
container.addView(view);
view.requestFocus();
@ -85,19 +90,18 @@ public class ECarbActivity extends ViewSelectorActivity {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
confirmbutton.setOnClickListener((View v) -> {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "ecarbs " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
+ " " + SafeParse.stringToInt(editStartTime.editText.getText().toString())
+ " " + SafeParse.stringToInt(editDuration.editText.getText().toString());
ListenerService.initiateAction(ECarbActivity.this, actionstring);
confirmAction(ECarbActivity.this, R.string.action_ecarb_confirmation);
finishAffinity();
String actionstring = "ecarbs " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
+ " " + SafeParse.stringToInt(editStartTime.editText.getText().toString())
+ " " + SafeParse.stringToInt(editDuration.editText.getText().toString());
ListenerService.initiateAction(ECarbActivity.this, actionstring);
finishAffinity();
}
});
container.addView(view);
return view;

View file

@ -63,17 +63,14 @@ public class FillActivity extends ViewSelectorActivity {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
confirmbutton.setOnClickListener((View v) -> {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "fill " + SafeParse.stringToDouble(editInsulin.editText.getText().toString());
ListenerService.initiateAction(FillActivity.this, actionstring);
confirmAction(FillActivity.this, R.string.action_fill_confirmation);
finishAffinity();
}
});
container.addView(view);
return view;

View file

@ -8,7 +8,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.DecimalFormat;
@ -32,6 +31,7 @@ public class TempTargetActivity extends ViewSelectorActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setAdapter(new MyGridViewPagerAdapter());
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
@ -61,8 +61,6 @@ public class TempTargetActivity extends ViewSelectorActivity {
if (col == 0) {
final View view = getInflatedPlusMinusView(container);
final TextView textView = view.findViewById(R.id.label);
textView.setText("duration");
if (time == null) {
time = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 60d, 0d, 24 * 60d, 5d, new DecimalFormat("0"), false);
} else {
@ -118,22 +116,19 @@ public class TempTargetActivity extends ViewSelectorActivity {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
confirmbutton.setOnClickListener((View v) -> {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "temptarget"
+ " " + isMGDL
+ " " + SafeParse.stringToInt(time.editText.getText().toString())
+ " " + SafeParse.stringToDouble(lowRange.editText.getText().toString())
+ " " + (isSingleTarget ? SafeParse.stringToDouble(lowRange.editText.getText().toString()) : SafeParse.stringToDouble(highRange.editText.getText().toString()));
String actionstring = "temptarget "
+ " " + isMGDL
+ " " + SafeParse.stringToInt(time.editText.getText().toString())
+ " " + SafeParse.stringToDouble(lowRange.editText.getText().toString())
+ " " + (isSingleTarget ? SafeParse.stringToDouble(lowRange.editText.getText().toString()) : SafeParse.stringToDouble(highRange.editText.getText().toString()));
ListenerService.initiateAction(TempTargetActivity.this, actionstring);
finishAffinity();
}
ListenerService.initiateAction(TempTargetActivity.this, actionstring);
confirmAction(TempTargetActivity.this, R.string.action_tempt_confirmation);
finishAffinity();
});
container.addView(view);
return view;

View file

@ -0,0 +1,112 @@
package info.nightscout.androidaps.interaction.actions;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.wearable.view.GridPagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.text.DecimalFormat;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.utils.PlusMinusEditText;
import info.nightscout.shared.SafeParse;
/**
* Created by adrian on 09/02/17.
*/
public class TreatmentActivity extends ViewSelectorActivity {
PlusMinusEditText editCarbs;
PlusMinusEditText editInsulin;
int maxCarbs;
float maxBolus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setAdapter(new MyGridViewPagerAdapter());
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
maxBolus = sp.getFloat(getString(R.string.key_treatmentssafety_maxbolus), 3f);
}
@Override
protected void onPause() {
super.onPause();
finish();
}
private class MyGridViewPagerAdapter extends GridPagerAdapter {
@Override
public int getColumnCount(int arg0) {
return 3;
}
@Override
public int getRowCount() {
return 1;
}
@Override
public Object instantiateItem(ViewGroup container, int row, int col) {
if (col == 0) {
final View view = getInflatedPlusMinusView(container);
double def = 0;
if (editInsulin != null) {
def = SafeParse.stringToDouble(editInsulin.editText.getText().toString());
}
editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double) maxBolus, 0.1d, new DecimalFormat("#0.0"),false);
setLabelToPlusMinusView(view, getString(R.string.action_insulin));
container.addView(view);
view.requestFocus();
return view;
} else if (col == 1) {
final View view = getInflatedPlusMinusView(container);
double def = 0;
if (editCarbs != null) {
def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
}
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxCarbs, 1d, new DecimalFormat("0"),false);
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
container.addView(view);
return view;
} else {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener((View v) -> {
//check if it can happen that the fagment is never created that hold data?
// (you have to swipe past them anyways - but still)
String actionstring = "bolus " + SafeParse.stringToDouble(editInsulin.editText.getText().toString())
+ " " + SafeParse.stringToInt(editCarbs.editText.getText().toString());
ListenerService.initiateAction(TreatmentActivity.this, actionstring);
confirmAction(TreatmentActivity.this, R.string.action_treatment_confirmation);
finishAffinity();
});
container.addView(view);
return view;
}
}
@Override
public void destroyItem(ViewGroup container, int row, int col, Object view) {
// Handle this to get the data before the view is destroyed?
// Object should still be kept by this, just setup for reinit?
container.removeView((View) view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
}

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.interaction.actions;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
@ -11,6 +12,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.wear.widget.CurvedTextView;
@ -62,9 +64,9 @@ public class ViewSelectorActivity extends Activity {
private void setTitleBasedOnScreenShape() {
// intents can inject dynamic titles, otherwise we'll use the default
String title = String.valueOf(getTitle());
if (getIntent().getExtras() != null)
if (getIntent().getExtras() != null) {
title = getIntent().getExtras().getString("title", title);
}
CurvedTextView titleViewCurved = findViewById(R.id.title_curved);
TextView titleView = findViewById(R.id.title);
if (this.getResources().getConfiguration().isScreenRound()) {
@ -96,8 +98,12 @@ public class ViewSelectorActivity extends Activity {
}
void setLabelToPlusMinusView(View view, String labelText) {
final TextView textView = view.findViewById(R.id.label);
textView.setText(labelText);
final TextView textView = view.findViewById(R.id.label);
textView.setText(labelText);
}
void confirmAction(Context context, int text) {
Toast.makeText(context, getString(text), Toast.LENGTH_LONG).show();
}
}

View file

@ -26,6 +26,8 @@ public class WizardActivity extends ViewSelectorActivity {
PlusMinusEditText editPercentage;
boolean hasPercentage;
int percentage;
int maxCarbs;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -33,6 +35,8 @@ public class WizardActivity extends ViewSelectorActivity {
setAdapter(new MyGridViewPagerAdapter());
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
hasPercentage = sp.getBoolean("wizardpercentage", false);
percentage = sp.getInt(getString(R.string.key_boluswizard_percentage), 100);
maxCarbs = sp.getInt(getString(R.string.key_treatmentssafety_maxcarbs), 48);
}
@Override
@ -58,10 +62,10 @@ public class WizardActivity extends ViewSelectorActivity {
if (col == 0) {
final View view = getInflatedPlusMinusView(container);
if (editCarbs == null) {
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 0d, 0d, 150d, 1d, new DecimalFormat("0"), false);
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 0d, 0d, (double)maxCarbs, 1d, new DecimalFormat("0"), false);
} else {
double def = SafeParse.stringToDouble(editCarbs.editText.getText().toString());
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 150d, 1d, new DecimalFormat("0"), false);
editCarbs = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, (double)maxCarbs, 1d, new DecimalFormat("0"),false);
}
setLabelToPlusMinusView(view, getString(R.string.action_carbs));
container.addView(view);
@ -70,7 +74,7 @@ public class WizardActivity extends ViewSelectorActivity {
} else if (col == 1 && hasPercentage) {
final View view = getInflatedPlusMinusView(container);
if (editPercentage == null) {
editPercentage = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, 100d, 50d, 150d, 1d, new DecimalFormat("0"), false);
editPercentage = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, (double)percentage, 50d, 150d, 1d, new DecimalFormat("0"), false);
} else {
double def = SafeParse.stringToDouble(editPercentage.editText.getText().toString());
editPercentage = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 50d, 150d, 1d, new DecimalFormat("0"), false);
@ -82,23 +86,16 @@ public class WizardActivity extends ViewSelectorActivity {
final View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.action_send_item, container, false);
final ImageView confirmbutton = view.findViewById(R.id.confirmbutton);
confirmbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// check if it can happen that the fragment is never created that hold data?
// (you have to swipe past them anyways - but still)
int percentage = 100;
if (editPercentage != null)
percentage = SafeParse.stringToInt(editPercentage.editText.getText().toString());
String actionstring = "wizard2 " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
+ " " + percentage;
ListenerService.initiateAction(WizardActivity.this, actionstring);
finishAffinity();
confirmbutton.setOnClickListener((View v) -> {
if (editPercentage != null) {
percentage = SafeParse.stringToInt(editPercentage.editText.getText().toString());
}
String actionstring = "wizard2 " + SafeParse.stringToInt(editCarbs.editText.getText().toString())
+ " " + percentage;
ListenerService.initiateAction(WizardActivity.this, actionstring);
confirmAction(WizardActivity.this, R.string.action_wizard_confirmation);
finishAffinity();
});
container.addView(view);
return view;

View file

@ -11,7 +11,7 @@ import java.util.List;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ListenerService;
import info.nightscout.androidaps.interaction.AAPSPreferences;
import info.nightscout.androidaps.interaction.actions.BolusActivity;
import info.nightscout.androidaps.interaction.actions.TreatmentActivity;
import info.nightscout.androidaps.interaction.actions.ECarbActivity;
import info.nightscout.androidaps.interaction.actions.TempTargetActivity;
import info.nightscout.androidaps.interaction.actions.WizardActivity;
@ -49,7 +49,7 @@ public class MainMenuActivity extends MenuListActivity {
if (showWizard) menuItems.add(new MenuItem(R.drawable.ic_calculator, getString(R.string.menu_wizard)));
menuItems.add(new MenuItem(R.drawable.ic_e_carbs, getString(R.string.menu_ecarb)));
menuItems.add(new MenuItem(R.drawable.ic_bolus, getString(R.string.menu_bolus)));
menuItems.add(new MenuItem(R.drawable.ic_treatment, getString(R.string.menu_treatment)));
menuItems.add(new MenuItem(R.drawable.ic_temptarget, getString(R.string.menu_tempt)));
menuItems.add(new MenuItem(R.drawable.ic_settings, getString(R.string.menu_settings)));
menuItems.add(new MenuItem(R.drawable.ic_status, getString(R.string.menu_status)));
@ -73,8 +73,8 @@ public class MainMenuActivity extends MenuListActivity {
intent = new Intent(this, TempTargetActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
} else if (getString(R.string.menu_bolus).equals(action)) {
intent = new Intent(this, BolusActivity.class);
} else if (getString(R.string.menu_treatment).equals(action)) {
intent = new Intent(this, TreatmentActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
} else if (getString(R.string.menu_wizard).equals(action)) {

View file

@ -32,7 +32,7 @@ public class PlusMinusEditText implements View.OnKeyListener,
Double minValue = 0d;
Double maxValue = 1d;
Double step = 1d;
NumberFormat formater;
NumberFormat formatter;
boolean allowZero = false;
boolean roundRobin;
@ -74,11 +74,11 @@ public class PlusMinusEditText implements View.OnKeyListener,
private static final int MSG_INC = 0;
private static final int MSG_DEC = 1;
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero) {
this(view, editTextID, plusID, minusID, initValue, minValue, maxValue, step, formater, allowZero, false);
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formatter, boolean allowZero) {
this(view, editTextID, plusID, minusID, initValue, minValue, maxValue, step, formatter, allowZero, false);
}
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, boolean roundRobin) {
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formatter, boolean allowZero, boolean roundRobin) {
editText = view.findViewById(editTextID);
minusImage = view.findViewById(minusID);
plusImage = view.findViewById(plusID);
@ -87,7 +87,7 @@ public class PlusMinusEditText implements View.OnKeyListener,
this.minValue = minValue;
this.maxValue = maxValue;
this.step = step;
this.formater = formater;
this.formatter = formatter;
this.allowZero = allowZero;
this.roundRobin = roundRobin;
@ -159,7 +159,7 @@ public class PlusMinusEditText implements View.OnKeyListener,
if (value == 0d && !allowZero)
editText.setText("");
else
editText.setText(formater.format(value));
editText.setText(formatter.format(value));
}
private void startUpdating(boolean inc) {

View file

@ -0,0 +1,63 @@
package info.nightscout.androidaps.tile
import android.content.res.Resources
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interaction.actions.BolusActivity
import info.nightscout.androidaps.interaction.actions.TreatmentActivity
import info.nightscout.androidaps.interaction.actions.ECarbActivity
import info.nightscout.androidaps.interaction.actions.TempTargetActivity
import info.nightscout.androidaps.interaction.actions.WizardActivity
object ActionSource : StaticTileSource() {
override val preferencePrefix = "tile_action_"
override fun getActions(resources: Resources): List<StaticAction> {
return listOf(
StaticAction(
settingName = "wizard",
buttonText = resources.getString(R.string.menu_wizard_short),
iconRes = R.drawable.ic_calculator_green,
activityClass = WizardActivity::class.java.name,
),
StaticAction(
settingName = "treatment",
buttonText = resources.getString(R.string.menu_treatment_short),
iconRes = R.drawable.ic_bolus_carbs,
activityClass = TreatmentActivity::class.java.name,
),
StaticAction(
settingName = "bolus",
buttonText = resources.getString(R.string.action_insulin),
iconRes = R.drawable.ic_bolus,
activityClass = BolusActivity::class.java.name,
),
StaticAction(
settingName = "carbs",
buttonText = resources.getString(R.string.action_carbs),
iconRes = R.drawable.ic_carbs_orange,
activityClass = ECarbActivity::class.java.name,
),
StaticAction(
settingName = "temp_target",
buttonText = resources.getString(R.string.menu_tempt),
iconRes = R.drawable.ic_temptarget_flat,
activityClass = TempTargetActivity::class.java.name,
)
)
}
override fun getResourceReferences(resources: Resources): List<Int> {
return getActions(resources).map { it.iconRes }
}
override fun getDefaultConfig(): Map<String, String> {
return mapOf(
"tile_action_1" to "wizard",
"tile_action_2" to "treatment",
"tile_action_3" to "carbs",
"tile_action_4" to "temp_target"
)
}
}

View file

@ -0,0 +1,6 @@
package info.nightscout.androidaps.tile
class ActionsTileService : TileBase() {
override val resourceVersion = "ActionsTileService"
override val source = ActionSource
}

View file

@ -0,0 +1,108 @@
package info.nightscout.androidaps.tile
import android.content.Context
import android.content.res.Resources
import android.util.Base64
import android.util.Log
import androidx.preference.PreferenceManager
import com.google.android.gms.wearable.DataMap
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
import java.util.*
object QuickWizardSource : TileSource {
override fun getSelectedActions(context: Context): List<Action> {
val quickList = mutableListOf<Action>()
val quickMap = getDataMap(context)
val sfm = secondsFromMidnight()
for (quick in quickMap) {
val validFrom = quick.getInt("from", 0)
val validTo = quick.getInt("to", 0)
val isActive = sfm in validFrom..validTo
val guid = quick.getString("guid", "")
if (isActive && guid != "") {
quickList.add(
Action(
buttonText = quick.getString("button_text", "?"),
buttonTextSub = "${quick.getInt("carbs", 0)} g",
iconRes = R.drawable.ic_quick_wizard,
activityClass = BackgroundActionActivity::class.java.name,
actionString = "quick_wizard $guid",
message = context.resources.getString(R.string.action_quick_wizard_confirmation),
)
)
Log.i(TAG, "getSelectedActions: active " + quick.getString("button_text", "?") + " guid=" + guid)
} else {
Log.i(TAG, "getSelectedActions: not active " + quick.getString("button_text", "?") + " guid=" + guid)
}
}
return quickList
}
override fun getValidFor(context: Context): Long? {
val quickMap = getDataMap(context)
if (quickMap.size == 0) {
return null
}
val sfm = secondsFromMidnight()
var validTill = 24 * 60 * 60
for (quick in quickMap) {
val validFrom = quick.getInt("from", 0)
val validTo = quick.getInt("to", 0)
val isActive = sfm in validFrom..validTo
val guid = quick.getString("guid", "")
Log.i(TAG, "valid: " + validFrom + "-" + validTo)
if (guid != "") {
if (isActive && validTill > validTo) {
validTill = validTo
}
if (validFrom > sfm && validTill > validFrom) {
validTill = validFrom
}
}
}
val validWithin = 60
val delta = (validTill - sfm + validWithin) * 1000L
Log.i(TAG, "getValidTill: sfm" + sfm + " till" + validTill + " d=" + delta)
return delta
}
private fun getDataMap(context: Context): ArrayList<DataMap> {
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
val key = context.resources.getString(R.string.key_quick_wizard_data_map)
if (sharedPrefs.contains(key)) {
val rawB64Data: String? = sharedPrefs.getString(key, null)
val rawData: ByteArray = Base64.decode(rawB64Data, Base64.DEFAULT)
try {
val map = DataMap.fromByteArray(rawData)
return map.getDataMapArrayList("quick_wizard")
} catch (ex: IllegalArgumentException) {
Log.e(TAG, "getSelectedActions: IllegalArgumentException ", ex)
}
}
return arrayListOf()
}
private fun secondsFromMidnight(): Int {
val c = Calendar.getInstance()
c.set(Calendar.HOUR_OF_DAY, 0)
c.set(Calendar.MINUTE, 0)
c.set(Calendar.SECOND, 0)
c.set(Calendar.MILLISECOND, 0)
val passed: Long = System.currentTimeMillis() - c.timeInMillis
return (passed / 1000).toInt()
}
override fun getResourceReferences(resources: Resources): List<Int> {
return listOf(R.drawable.ic_quick_wizard)
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.tile
const val TAG = "QuickWizard"
class QuickWizardTileService : TileBase() {
override val resourceVersion = "QuickWizardTileService"
override val source = QuickWizardSource
}

View file

@ -0,0 +1,62 @@
package info.nightscout.androidaps.tile
import android.content.Context
import android.content.SharedPreferences
import android.content.res.Resources
import androidx.annotation.DrawableRes
import androidx.preference.PreferenceManager
class StaticAction(
val settingName: String,
buttonText: String,
buttonTextSub: String? = null,
activityClass: String,
@DrawableRes iconRes: Int,
actionString: String? = null,
message: String? = null,
) : Action(buttonText, buttonTextSub, activityClass, iconRes, actionString, message)
abstract class StaticTileSource : TileSource {
abstract fun getActions(resources: Resources): List<StaticAction>
abstract val preferencePrefix: String
abstract fun getDefaultConfig(): Map<String, String>
override fun getSelectedActions(context: Context): List<Action> {
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
setDefaultSettings(sharedPrefs)
val actionList: MutableList<Action> = mutableListOf()
for (i in 1..4) {
val action = getActionFromPreference(context.resources, sharedPrefs, i)
if (action != null) {
actionList.add(action)
}
}
if (actionList.isEmpty()) {
return getActions(context.resources).take(4)
}
return actionList
}
override fun getValidFor(context: Context): Long? = null
private fun getActionFromPreference(resources: Resources, sharedPrefs: SharedPreferences, index: Int): Action? {
val actionPref = sharedPrefs.getString(preferencePrefix + index, "none")
return getActions(resources).find { action -> action.settingName == actionPref }
}
private fun setDefaultSettings(sharedPrefs: SharedPreferences) {
val defaults = getDefaultConfig()
val firstKey = defaults.firstNotNullOf { settings -> settings.key }
if (!sharedPrefs.contains(firstKey)) {
val editor = sharedPrefs.edit()
for ((key, value) in defaults) {
editor.putString(key, value)
}
editor.apply()
}
}
}

View file

@ -0,0 +1,71 @@
package info.nightscout.androidaps.tile
import android.content.res.Resources
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
import info.nightscout.androidaps.interaction.actions.TempTargetActivity
object TempTargetSource : StaticTileSource() {
override val preferencePrefix = "tile_tempt_"
override fun getActions(resources: Resources): List<StaticAction> {
val message = resources.getString(R.string.action_tempt_confirmation)
return listOf(
StaticAction(
settingName = "activity",
buttonText = resources.getString(R.string.temp_target_activity),
iconRes = R.drawable.ic_target_activity,
activityClass = BackgroundActionActivity::class.java.name,
message = message,
// actionString = "temptarget false 90 8.0 8.0",
actionString = "temptarget preset activity",
),
StaticAction(
settingName = "eating_soon",
buttonText = resources.getString(R.string.temp_target_eating_soon),
iconRes = R.drawable.ic_target_eatingsoon,
activityClass = BackgroundActionActivity::class.java.name,
message = message,
// actionString = "temptarget false 45 4.5 4.5",
actionString = "temptarget preset eating",
),
StaticAction(
settingName = "hypo",
buttonText = resources.getString(R.string.temp_target_hypo),
iconRes = R.drawable.ic_target_hypo,
activityClass = BackgroundActionActivity::class.java.name,
message = message,
// actionString = "temptarget false 45 7.0 7.0",
actionString = "temptarget preset hypo",
),
StaticAction(
settingName = "manual",
buttonText = resources.getString(R.string.temp_target_manual),
iconRes = R.drawable.ic_target_manual,
activityClass = TempTargetActivity::class.java.name,
),
StaticAction(
settingName = "cancel",
buttonText = resources.getString(R.string.generic_cancel),
iconRes = R.drawable.ic_target_cancel,
activityClass = BackgroundActionActivity::class.java.name,
message = message,
actionString = "temptarget cancel",
)
)
}
override fun getResourceReferences(resources: Resources): List<Int> {
return getActions(resources).map { it.iconRes }
}
override fun getDefaultConfig(): Map<String, String> {
return mapOf(
"tile_tempt_1" to "activity",
"tile_tempt_2" to "eating_soon",
"tile_tempt_3" to "hypo",
"tile_tempt_4" to "manual"
)
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.tile
class TempTargetTileService : TileBase() {
override val resourceVersion = "TempTargetTileService"
override val source = TempTargetSource;
}

View file

@ -0,0 +1,297 @@
package info.nightscout.androidaps.tile
import android.content.Context
import android.os.Build
import androidx.annotation.DrawableRes
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import androidx.wear.tiles.ActionBuilders
import androidx.wear.tiles.ColorBuilders.argb
import androidx.wear.tiles.DeviceParametersBuilders.SCREEN_SHAPE_ROUND
import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters
import androidx.wear.tiles.DimensionBuilders.SpProp
import androidx.wear.tiles.DimensionBuilders.dp
import androidx.wear.tiles.DimensionBuilders.sp
import androidx.wear.tiles.LayoutElementBuilders.*
import androidx.wear.tiles.ModifiersBuilders.Background
import androidx.wear.tiles.ModifiersBuilders.Clickable
import androidx.wear.tiles.ModifiersBuilders.Corner
import androidx.wear.tiles.ModifiersBuilders.Modifiers
import androidx.wear.tiles.ModifiersBuilders.Semantics
import androidx.wear.tiles.RequestBuilders
import androidx.wear.tiles.RequestBuilders.ResourcesRequest
import androidx.wear.tiles.ResourceBuilders.AndroidImageResourceByResId
import androidx.wear.tiles.ResourceBuilders.ImageResource
import androidx.wear.tiles.ResourceBuilders.Resources
import androidx.wear.tiles.TileBuilders.Tile
import androidx.wear.tiles.TileService
import androidx.wear.tiles.TimelineBuilders.Timeline
import androidx.wear.tiles.TimelineBuilders.TimelineEntry
import com.google.common.util.concurrent.ListenableFuture
import info.nightscout.androidaps.R
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.guava.future
import kotlin.math.sqrt
private const val SPACING_ACTIONS = 3f
private const val ICON_SIZE_FRACTION = 0.4f // Percentage of button diameter
private const val BUTTON_COLOR = R.color.gray_850
private const val LARGE_SCREEN_WIDTH_DP = 210
interface TileSource {
fun getResourceReferences(resources: android.content.res.Resources): List<Int>
fun getSelectedActions(context: Context): List<Action>
fun getValidFor(context: Context): Long?
}
open class Action(
val buttonText: String,
val buttonTextSub: String? = null,
val activityClass: String,
@DrawableRes val iconRes: Int,
val actionString: String? = null,
val message: String? = null,
)
enum class WearControl {
NO_DATA, ENABLED, DISABLED
}
abstract class TileBase : TileService() {
abstract val resourceVersion: String
abstract val source: TileSource
private val serviceJob = Job()
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
override fun onTileRequest(
requestParams: RequestBuilders.TileRequest
): ListenableFuture<Tile> = serviceScope.future {
val actionsSelected = getSelectedActions()
val wearControl = getWearControl()
val tile = Tile.Builder()
.setResourcesVersion(resourceVersion)
.setTimeline(
Timeline.Builder().addTimelineEntry(
TimelineEntry.Builder().setLayout(
Layout.Builder().setRoot(layout(wearControl, actionsSelected, requestParams.deviceParameters!!)).build()
).build()
).build()
)
val validFor = validFor()
if (validFor != null) {
tile.setFreshnessIntervalMillis(validFor)
}
tile.build()
}
private fun getSelectedActions(): List<Action> {
// TODO check why thi scan not be don in scope of the coroutine
return source.getSelectedActions(this)
}
private fun validFor(): Long? {
return source.getValidFor(this)
}
@RequiresApi(Build.VERSION_CODES.N)
override fun onResourcesRequest(
requestParams: ResourcesRequest
): ListenableFuture<Resources> = serviceScope.future {
Resources.Builder()
.setVersion(resourceVersion)
.apply {
source.getResourceReferences(resources).forEach { resourceId ->
addIdToImageMapping(
resourceId.toString(),
ImageResource.Builder()
.setAndroidResourceByResId(
AndroidImageResourceByResId.Builder()
.setResourceId(resourceId)
.build()
)
.build()
)
}
}
.build()
}
private fun layout(wearControl: WearControl, actions: List<Action>, deviceParameters: DeviceParameters): LayoutElement {
if (wearControl == WearControl.DISABLED) {
return Text.Builder()
.setText(resources.getString(R.string.wear_control_not_enabled))
.build()
} else if (wearControl == WearControl.NO_DATA) {
return Text.Builder()
.setText(resources.getString(R.string.wear_control_no_data))
.build()
}
if (actions.isNotEmpty()) {
with(Column.Builder()) {
if (actions.size == 1 || actions.size == 3) {
addContent(addRowSingle(actions[0], deviceParameters))
}
if (actions.size == 4 || actions.size == 2) {
addContent(addRowDouble(actions[0], actions[1], deviceParameters))
}
if (actions.size == 3) {
addContent(addRowDouble(actions[1], actions[2], deviceParameters))
}
if (actions.size == 4) {
addContent(Spacer.Builder().setHeight(dp(SPACING_ACTIONS)).build())
addContent(addRowDouble(actions[2], actions[3], deviceParameters))
}
return build()
}
}
return Text.Builder()
.setText(resources.getString(R.string.tile_no_config))
.build()
}
private fun addRowSingle(action: Action, deviceParameters: DeviceParameters): LayoutElement =
Row.Builder()
.addContent(action(action, deviceParameters))
.build()
private fun addRowDouble(action1: Action, action2: Action, deviceParameters: DeviceParameters): LayoutElement =
Row.Builder()
.addContent(action(action1, deviceParameters))
.addContent(Spacer.Builder().setWidth(dp(SPACING_ACTIONS)).build())
.addContent(action(action2, deviceParameters))
.build()
private fun doAction(action: Action): ActionBuilders.Action {
val builder = ActionBuilders.AndroidActivity.Builder()
.setClassName(action.activityClass)
.setPackageName(this.packageName)
if (action.actionString != null) {
val actionString = ActionBuilders.AndroidStringExtra.Builder().setValue(action.actionString).build()
builder.addKeyToExtraMapping("actionString", actionString)
}
if (action.message != null) {
val message = ActionBuilders.AndroidStringExtra.Builder().setValue(action.message).build()
builder.addKeyToExtraMapping("message", message)
}
return ActionBuilders.LaunchAction.Builder()
.setAndroidActivity(builder.build())
.build()
}
private fun action(action: Action, deviceParameters: DeviceParameters): LayoutElement {
val circleDiameter = circleDiameter(deviceParameters)
val text = action.buttonText
val textSub = action.buttonTextSub
return Box.Builder()
.setWidth(dp(circleDiameter))
.setHeight(dp(circleDiameter))
.setModifiers(
Modifiers.Builder()
.setBackground(
Background.Builder()
.setColor(
argb(ContextCompat.getColor(baseContext, BUTTON_COLOR))
)
.setCorner(
Corner.Builder().setRadius(dp(circleDiameter / 2)).build()
)
.build()
)
.setSemantics(
Semantics.Builder()
.setContentDescription("$text $textSub")
.build()
)
.setClickable(
Clickable.Builder()
.setOnClick(doAction(action))
.build()
)
.build()
)
.addContent(addTextContent(action, deviceParameters))
.build()
}
private fun addTextContent(action: Action, deviceParameters: DeviceParameters): LayoutElement {
val circleDiameter = circleDiameter(deviceParameters)
val iconSize = dp(circleDiameter * ICON_SIZE_FRACTION)
val text = action.buttonText
val textSub = action.buttonTextSub
val col = Column.Builder()
.addContent(
Image.Builder()
.setWidth(iconSize)
.setHeight(iconSize)
.setResourceId(action.iconRes.toString())
.build()
).addContent(
Text.Builder()
.setText(text)
.setFontStyle(
FontStyle.Builder()
.setWeight(FONT_WEIGHT_BOLD)
.setColor(
argb(ContextCompat.getColor(baseContext, R.color.white))
)
.setSize(buttonTextSize(deviceParameters, text))
.build()
)
.build()
)
if (textSub != null) {
col.addContent(
Text.Builder()
.setText(textSub)
.setFontStyle(
FontStyle.Builder()
.setColor(
argb(ContextCompat.getColor(baseContext, R.color.white))
)
.setSize(buttonTextSize(deviceParameters, textSub))
.build()
)
.build()
)
}
return col.build()
}
private fun circleDiameter(deviceParameters: DeviceParameters) = when (deviceParameters.screenShape) {
SCREEN_SHAPE_ROUND -> ((sqrt(2f) - 1) * deviceParameters.screenHeightDp) - (2 * SPACING_ACTIONS)
else -> 0.5f * deviceParameters.screenHeightDp - SPACING_ACTIONS
}
private fun buttonTextSize(deviceParameters: DeviceParameters, text: String): SpProp {
if (text.length > 6) {
return sp(if (isLargeScreen(deviceParameters)) 14f else 12f)
}
return sp(if (isLargeScreen(deviceParameters)) 16f else 14f)
}
private fun isLargeScreen(deviceParameters: DeviceParameters): Boolean {
return deviceParameters.screenWidthDp >= LARGE_SCREEN_WIDTH_DP
}
private fun getWearControl(): WearControl {
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)
if (!sharedPrefs.contains("wearcontrol")) {
return WearControl.NO_DATA
}
val wearControlPref = sharedPrefs.getBoolean("wearcontrol", false)
if (wearControlPref) {
return WearControl.ENABLED
}
return WearControl.DISABLED
}
}

View file

@ -71,6 +71,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
}
static IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
public final Point displaySize = new Point();
public TextView mTime, mHour, mMinute, mTimePeriod, mSgv, mDirection, mTimestamp, mUploaderBattery, mRigBattery, mDelta, mAvgDelta, mStatus, mBasalRate, mIOB1, mIOB2, mCOB1, mCOB2, mBgi, mLoop, mDay, mDayName, mMonth, isAAPSv2, mHighLight, mLowLight;
public ImageView mGlucoseDial, mDeltaGauge, mHourHand, mMinuteHand;
@ -111,7 +113,6 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
private Date mDateTime;
private String mLastSvg = "", mLastDirection = "";
private float mYOffset = 0;
private Intent mBatteryStatus;
@Override
public void onCreate() {
@ -145,10 +146,8 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
}
private void setupBatteryReceiver() {
IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
mBatteryStatus = this.registerReceiver(null, iFilter);
String setting = sharedPrefs.getString("simplify_ui", "off");
if (setting.equals("charging") || setting.equals("ambient_charging") && batteryReceiver == null) {
if ((setting.equals("charging") || setting.equals("ambient_charging")) && batteryReceiver == null) {
IntentFilter intentBatteryFilter = new IntentFilter();
intentBatteryFilter.addAction(BatteryManager.ACTION_CHARGING);
intentBatteryFilter.addAction(BatteryManager.ACTION_DISCHARGING);
@ -374,6 +373,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
}
private boolean isCharging() {
Intent mBatteryStatus = this.registerReceiver(null, iFilter);
int status = mBatteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
return status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
@ -658,7 +658,7 @@ public abstract class BaseWatchFace extends WatchFace implements SharedPreferenc
}
private boolean isLowRes(WatchMode watchMode) {
return (watchMode == WatchMode.LOW_BIT) || (watchMode == WatchMode.LOW_BIT_BURN_IN); // || (watchMode == WatchMode.LOW_BIT_BURN_IN);
return watchMode == WatchMode.LOW_BIT || watchMode == WatchMode.LOW_BIT_BURN_IN;
}
private boolean isSimpleUi() {

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="30"
android:viewportHeight="30">
<path
android:fillColor="@color/colorInsulinButton"
android:pathData="M 11.0749 4 z z z z M 26.86 10.0071 C 26.8429 9.9814 26.3726 10.4124 25.4387 11.2833 L 24.2053 12.433 L 23.6639 12.3028 C 22.0753 11.919 21.7909 11.8722 21.5282 11.9474 C 21.3643 11.9946 19.6083 13.6448 17.3331 15.8914 C 13.9148 19.2667 13.3973 19.7384 13.2404 19.6214 C 13.1416 19.5479 13.039 19.4354 13.0116 19.3721 C 12.9324 19.1878 12.3197 19.1442 12.0776 19.3051 C 11.855 19.4535 11.7498 19.7846 11.8228 20.1125 C 11.8445 20.2102 12.2379 20.6946 12.6971 21.1878 C 13.1565 21.6808 13.5284 22.1131 13.525 22.1347 C 13.5208 22.1629 13.1403 22.5459 12.6786 22.9849 C 11.8674 23.7558 11.8323 23.7757 11.6368 23.5821 C 11.1844 23.1325 10.8501 22.8615 10.7196 22.8435 C 10.6437 22.832 10.4456 22.9242 10.2806 23.0463 L 10.2806 23.0426 C 9.9533 23.285 9.8436 23.661 10.0145 23.9523 C 10.0742 24.054 10.6829 24.7423 11.367 25.4815 C 12.7141 26.9371 12.9469 27.0705 13.3892 26.6535 C 13.7821 26.2828 13.7627 26.0276 13.2962 25.4424 C 13.0188 25.0942 12.9096 24.8729 12.978 24.7894 C 13.2978 24.4008 14.4837 23.2905 14.5668 23.3049 C 14.6207 23.3129 15.0313 23.7191 15.4802 24.2071 C 16.396 25.2026 16.7206 25.3301 17.175 24.8769 C 17.4797 24.5732 17.4511 24.253 17.082 23.7979 L 16.8234 23.476 L 20.7748 19.5749 C 23.9348 16.4537 24.7341 15.6073 24.7727 15.3481 C 24.7992 15.1703 24.7332 14.4989 24.6257 13.8562 L 24.4304 12.6878 L 25.5596 11.4656 C 26.4397 10.5139 26.8771 10.0327 26.86 10.0071 z z z z M 21.7477 12.6544 C 21.9077 12.6477 22.1363 12.6739 22.5049 12.7288 C 23.7852 12.9195 23.8251 12.9544 24.0118 14.0626 C 24.0992 14.5803 24.1587 15.0866 24.1439 15.1863 C 24.129 15.286 22.3898 17.0747 20.2781 19.16 C 17.4902 21.9129 16.3959 22.927 16.2858 22.864 C 16.2032 22.8132 16.1137 22.7763 16.0904 22.7728 L 16.0885 22.7728 C 15.858 22.7385 16.4578 22.0648 18.3991 20.1758 C 19.6536 18.9551 20.6742 17.9205 20.665 17.8838 C 20.6566 17.8435 20.1946 17.3206 19.64 16.7211 C 19.0854 16.1213 18.6385 15.6004 18.6466 15.5546 C 18.6542 15.5136 18.7649 15.3763 18.894 15.2514 L 19.1284 15.0263 L 19.9004 15.8653 C 20.6119 16.6388 20.9137 16.8241 20.8827 16.4681 C 20.876 16.3905 20.5411 15.9743 20.1385 15.5453 L 19.4074 14.764 L 19.6772 14.4812 C 19.8266 14.3257 19.9717 14.2042 20.0009 14.2078 C 20.0291 14.212 20.3915 14.5847 20.8064 15.0356 C 21.5127 15.803 21.7448 15.9458 21.7906 15.6384 C 21.801 15.5685 21.4693 15.1528 21.0538 14.7156 C 20.4166 14.0444 20.3192 13.8928 20.4306 13.7426 C 20.7899 13.2597 20.8942 13.2949 21.6957 14.1724 C 22.114 14.6305 22.501 14.9828 22.557 14.9612 C 22.7901 14.8611 22.6611 14.6226 21.9877 13.912 C 21.597 13.499 21.2566 13.116 21.2324 13.0581 C 21.2082 13.0005 21.286 12.8728 21.4055 12.7753 C 21.4965 12.6997 21.5878 12.661 21.7477 12.6544 z z"
android:strokeWidth="3.77952719" />
<path
android:fillColor="@color/colorCarbsButton"
android:pathData="M 11.0749 4 L 10.3606 4.759 C 9.9634 5.1807 9.5534 5.7953 9.4378 6.1413 C 9.242 6.7278 9.197 6.7646 8.6769 6.7682 C 8.0127 6.7733 7.4924 7.3126 6.8891 8.6193 C 6.5038 9.4538 6.324 9.5945 6.0278 9.2983 C 5.7974 9.0679 4.9658 9.8529 4.4465 10.7903 C 4.0564 11.4946 4.0167 11.6886 4.0167 12.9464 C 4.0167 14.2631 4.0418 14.3728 4.5432 15.2737 C 4.8327 15.7937 5.0375 16.3162 4.9972 16.4365 C 4.9568 16.5564 4.6934 16.8686 4.413 17.1304 C 3.9176 17.5919 3.9117 17.6123 4.1656 17.8931 C 4.3093 18.053 4.4581 18.1833 4.4967 18.1833 C 4.5354 18.1833 4.8498 17.9203 5.1962 17.601 L 5.8269 17.0206 L 6.8482 17.5545 C 7.731 18.0154 8.0377 18.0977 9.0936 18.1535 C 10.1662 18.2093 10.4121 18.1731 11.101 17.8578 C 11.5328 17.66 12.1312 17.2823 12.4311 17.0188 C 12.867 16.6361 12.9677 16.4535 12.9334 16.1072 C 12.888 15.6485 12.88 15.6573 13.9827 15.1268 C 14.9072 14.682 15.75 13.8443 15.5844 13.5343 C 15.4024 13.1943 15.5476 13.0433 16.4551 12.6265 C 16.8951 12.4243 17.5055 12.0047 17.8113 11.6944 L 18.3656 11.1307 L 17.9564 10.7903 C 17.7307 10.6024 17.2025 10.2233 16.7825 9.9476 C 16.3624 9.6719 16.0179 9.3738 16.0179 9.2853 C 16.0179 9.1967 16.286 8.8328 16.6132 8.4779 C 17.3978 7.6267 17.7921 6.6976 17.8782 5.4939 C 17.9466 4.538 17.9378 4.5037 17.601 4.4893 C 16.0894 4.4041 15.108 4.7039 13.9454 5.6055 C 13.4853 5.9624 13.0258 6.2548 12.9241 6.2548 C 12.8224 6.2548 12.6234 6.0386 12.4813 5.7748 C 12.3393 5.5109 11.9635 5.0034 11.6479 4.6474 L 11.0749 4 z M 16.6169 5.3487 C 17.1699 5.3911 17.1783 5.9135 16.6616 6.9505 C 16.2409 7.7947 15.6446 8.3606 14.7826 8.7346 C 13.5801 9.2561 13.2181 9.2115 13.2181 8.5374 C 13.2181 7.4338 14.5929 5.8491 15.8821 5.466 C 16.1882 5.3751 16.4326 5.3346 16.6169 5.3487 z M 11.0545 5.4752 C 11.1016 5.4774 11.149 5.4903 11.194 5.5143 C 11.6052 5.7344 12.1435 6.9854 12.2023 7.8547 C 12.2468 8.513 12.1848 8.7962 11.847 9.4545 C 11.3078 10.5055 10.9215 10.5892 10.4926 9.7485 C 9.9937 8.7706 9.854 7.6818 10.1131 6.7905 C 10.3526 5.967 10.7241 5.4604 11.0545 5.4752 z M 8.4369 8.0332 C 8.67 8.05 8.9126 8.3433 9.2053 8.9169 C 9.8187 10.1195 9.6732 11.7804 8.8816 12.6302 L 8.8816 12.632 C 8.5102 13.0282 8.3691 13.0254 8.1021 12.6171 C 7.318 11.4186 7.1699 9.9486 7.7207 8.8109 C 7.9793 8.277 8.2039 8.0164 8.4369 8.0332 z z M 14.5296 10.0722 C 15.3097 10.1137 16.0775 10.385 16.6374 10.8759 C 17.0571 11.2439 16.9317 11.4856 16.1276 11.86 L 16.1276 11.8563 C 15.069 12.3529 13.9019 12.342 12.7809 11.8302 C 11.83 11.3962 11.7174 11.0895 12.3455 10.6489 C 12.9565 10.2203 13.7495 10.0307 14.5296 10.0722 z M 5.825 10.6917 C 6.3961 10.6917 6.9173 11.8691 6.9226 13.1734 C 6.9262 14.0567 6.8699 14.288 6.5245 14.8105 C 5.9099 15.7402 5.4346 15.5722 4.9878 14.2691 C 4.5182 12.8995 5.0346 10.6917 5.825 10.6917 z M 11.6665 12.6265 C 12.6082 12.6265 14.0677 13.2007 14.2357 13.6385 C 14.3671 13.981 13.6639 14.4951 12.8181 14.6766 L 12.8181 14.6784 C 11.8262 14.8908 11.4179 14.8713 10.6191 14.5761 C 9.5702 14.1885 9.2225 13.9007 9.4136 13.5771 C 9.7248 13.0513 10.7329 12.6265 11.6665 12.6265 z z M 9.1178 15.1677 C 10.3208 15.2292 11.8132 15.9616 11.6089 16.4941 C 11.5563 16.6313 11.2336 16.8625 10.8926 17.0094 C 10.5516 17.1559 10.0434 17.307 9.7634 17.348 C 8.6093 17.5109 6.7087 16.856 6.7087 16.2951 C 6.7087 15.9196 7.7775 15.3014 8.6267 15.1844 C 8.781 15.1633 8.946 15.1589 9.1178 15.1677 z"
android:strokeWidth="3.77952719" />
</vector>

View file

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#67E86A"
android:pathData="M17.625,15.345h-4.083c-0.063,0 -0.113,0.051 -0.113,0.113v1.292c0,0.063 0.051,0.113 0.113,0.113h4.083c0.063,0 0.113,-0.051 0.113,-0.113v-1.292C17.738,15.396 17.688,15.345 17.625,15.345z" />
<path
android:fillColor="#67E86A"
android:pathData="M16.343,14.036c0,-0.063 -0.051,-0.113 -0.113,-0.113h-1.292c-0.063,0 -0.113,0.051 -0.113,0.113v1.016h1.519V14.036z" />
<path
android:fillColor="#67E86A"
android:pathData="M14.824,18.119c0,0.063 0.051,0.113 0.113,0.113h1.292c0.063,0 0.113,-0.051 0.113,-0.113v-1.017h-1.519V18.119z" />
<path
android:fillColor="#67E86A"
android:pathData="M19.836,1.96h-15.1c-0.344,0 -0.624,0.279 -0.624,0.624v18.375c0,0.345 0.279,0.624 0.624,0.624h15.1c0.345,0 0.624,-0.279 0.624,-0.624V2.583C20.46,2.239 20.181,1.96 19.836,1.96zM19.212,20.334H5.36V7.04h13.852V20.334zM19.212,5.793H5.36V3.207h13.852V5.793z" />
<path
android:fillColor="#67E86A"
android:pathData="M13.542,11.363h4.083c0.063,0 0.113,-0.051 0.113,-0.113V9.958c0,-0.063 -0.051,-0.113 -0.113,-0.113h-4.083c-0.063,0 -0.113,0.051 -0.113,0.113v1.292C13.429,11.313 13.479,11.363 13.542,11.363z" />
<path
android:fillColor="#67E86A"
android:pathData="M7.042,11.363h1.283v1.282c0,0.063 0.051,0.113 0.113,0.113h1.292c0.063,0 0.113,-0.051 0.113,-0.113v-1.282h1.283c0.063,0 0.113,-0.051 0.113,-0.113V9.958c0,-0.063 -0.051,-0.113 -0.113,-0.113H9.842V8.563c0,-0.063 -0.051,-0.113 -0.113,-0.113H8.438c-0.063,0 -0.113,0.051 -0.113,0.113v1.283H7.042c-0.063,0 -0.113,0.051 -0.113,0.113v1.292C6.928,11.313 6.979,11.363 7.042,11.363z" />
<path
android:fillColor="#67E86A"
android:pathData="M10.157,16.078l0.907,-0.907c0.021,-0.021 0.033,-0.05 0.033,-0.08s-0.012,-0.059 -0.033,-0.08l-0.914,-0.913c-0.044,-0.045 -0.116,-0.045 -0.16,0l-0.907,0.907l-0.907,-0.907c-0.044,-0.045 -0.116,-0.045 -0.16,0l-0.913,0.913c-0.044,0.044 -0.044,0.116 0,0.16l0.907,0.907l-0.907,0.907c-0.044,0.044 -0.044,0.116 0,0.16l0.913,0.914c0.021,0.021 0.05,0.033 0.08,0.033s0.059,-0.012 0.08,-0.033l0.907,-0.907l0.907,0.907c0.021,0.021 0.05,0.033 0.08,0.033s0.059,-0.012 0.08,-0.033l0.914,-0.914c0.044,-0.044 0.044,-0.116 0,-0.16L10.157,16.078z" />
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="6.35"
android:viewportHeight="6.3500004">
<path
android:fillColor="@color/colorCarbsButton"
android:pathData="m0.07296,6.18173c-0.11224,-0.12403 -0.10912,-0.13361 0.10984,-0.33755 0.12395,-0.11545 0.23996,-0.2533 0.25781,-0.30635 0.01785,-0.053 -0.07223,-0.28451 -0.20017,-0.51436 -0.22165,-0.3982 -0.23262,-0.44673 -0.23262,-1.02872 0,-0.55596 0.01701,-0.64151 0.18944,-0.95278 0.22952,-0.41433 0.59748,-0.76138 0.6993,-0.65956 0.13093,0.13093 0.21005,0.0684 0.38036,-0.30044 0.26666,-0.57755 0.49667,-0.81559 0.79028,-0.81787 0.2299,-0.002 0.24962,-0.0181 0.33616,-0.27725 0.05109,-0.15301 0.23231,-0.42442 0.40784,-0.61081l0.3159,-0.33544 0.25358,0.28625c0.13947,0.15744 0.30496,0.38166 0.36776,0.49829 0.0628,0.11662 0.15097,0.21203 0.19592,0.21203 0.04495,0 0.24814,-0.12905 0.45152,-0.28678 0.51384,-0.3985 0.94794,-0.53103 1.6161,-0.49339 0.14888,0.008 0.1524,0.0212 0.12218,0.44366 -0.03807,0.53204 -0.21229,0.9432 -0.55908,1.31942 -0.1446,0.15688 -0.26291,0.31727 -0.26291,0.35643 0,0.0392 0.1519,0.17085 0.33755,0.29265 0.18565,0.1218 0.41917,0.2894 0.51892,0.37247l0.18137,0.15102 -0.24567,0.24913c-0.13512,0.13703 -0.4048,0.32226 -0.59929,0.41164 -0.40112,0.18432 -0.46482,0.2508 -0.38439,0.40109 0.07321,0.13678 -0.29996,0.50766 -0.70863,0.70428 -0.48739,0.23449 -0.48332,0.23068 -0.46326,0.43341 0.01515,0.15308 -0.02944,0.23403 -0.2221,0.40318 -0.13258,0.11641 -0.39723,0.28315 -0.5881,0.37054 -0.30449,0.13941 -0.4133,0.1554 -0.88737,0.13052 -0.46672,-0.0245 -0.60186,-0.0605 -0.99207,-0.26433l-0.45174,-0.23597 -0.27839,0.25662c-0.15311,0.14114 -0.29237,0.25661 -0.30946,0.25661 -0.01709,0 -0.08305,-0.0574 -0.14659,-0.12764zM3.04651,5.79095c0.15071,-0.0649 0.29301,-0.16746 0.31623,-0.22796 0.10323,-0.26902 -0.77255,-0.65358 -1.31812,-0.5788 -0.37535,0.0515 -0.84735,0.32482 -0.84735,0.49076 0,0.24793 0.84009,0.5377 1.3502,0.46571 0.12377,-0.0175 0.34834,-0.0848 0.49905,-0.14971zM1.11599,4.81897c0.15268,-0.23095 0.17746,-0.33287 0.17587,-0.72332 -0.00236,-0.57649 -0.23257,-1.09745 -0.48498,-1.09745 -0.34938,0 -0.57808,0.97634 -0.37051,1.58171 0.19749,0.57597 0.40794,0.64999 0.67962,0.23906zM3.89797,4.76028c0.37387,-0.0802 0.68406,-0.30762 0.62598,-0.45898 -0.07426,-0.19351 -0.7192,-0.44794 -1.13545,-0.44794 -0.41266,0 -0.85838,0.18827 -0.99593,0.42069 -0.08449,0.14275 0.06918,0.27006 0.53279,0.4414 0.35307,0.1305 0.53422,0.13884 0.97261,0.0448zM2.15803,3.85532c0.34991,-0.37558 0.41361,-1.10931 0.14245,-1.64082 -0.25871,-0.50712 -0.42704,-0.51919 -0.65561,-0.047 -0.24344,0.50288 -0.17855,1.15285 0.16799,1.68264 0.11803,0.18046 0.18101,0.18141 0.34517,0.005zM5.36038,3.51489c0.35541,-0.16547 0.41056,-0.27201 0.22503,-0.43468 -0.49497,-0.43399 -1.35656,-0.47981 -1.89671,-0.10086 -0.27763,0.19477 -0.2274,0.33089 0.19289,0.52273 0.49552,0.22618 1.01089,0.23064 1.47879,0.0128zM3.46831,2.45169c0.14931,-0.29099 0.17721,-0.41624 0.15753,-0.70724 -0.02598,-0.38422 -0.2646,-0.93731 -0.44636,-1.03458 -0.15905,-0.0851 -0.35661,0.14839 -0.47756,0.56444 -0.11452,0.39395 -0.0528,0.87509 0.1677,1.3073 0.18957,0.3716 0.36037,0.33453 0.59868,-0.12992zM4.76565,2.13351c0.38101,-0.16525 0.6449,-0.41584 0.83084,-0.78896 0.30455,-0.61116 0.19648,-0.81689 -0.34467,-0.65619 -0.56982,0.16922 -1.17734,0.8697 -1.17734,1.35748 0,0.29794 0.15966,0.31819 0.69117,0.0877z"
android:strokeWidth="1" />
</vector>

View file

@ -0,0 +1,12 @@
<vector
android:height="48dp"
android:width="48dp"
android:viewportHeight="24"
android:viewportWidth="24"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FEAF05" android:pathData="M10.751,6.59c-0.561,0.69 -0.796,1.057 -1.25,1.797c-2.517,0.238 -3.932,2.751 -3.379,4.664c0.244,0.843 0.779,1.476 1.498,1.958c2.348,1.573 6.243,1.429 8.487,-0.306c1.187,-0.918 1.723,-2.084 1.334,-3.576c-0.412,-1.58 -1.445,-2.585 -3.039,-2.87c-1.112,-0.199 -1.973,0.37 -2.558,1.313c-0.494,0.796 -0.72,1.616 -1.628,2.345c-0.389,-0.431 -0.458,-0.961 -0.483,-1.481c-0.12,-2.486 2.019,-4.439 4.595,-4.213c2.365,0.207 4.466,1.956 5.114,4.256c0.611,2.172 -0.226,4.432 -2.19,5.909c-2.995,2.253 -7.895,2.327 -10.943,0.165c-2.057,-1.459 -2.88,-3.881 -2.099,-6.18C5.023,7.978 7.368,6.304 9.77,6.4C10.072,6.412 10.365,6.459 10.751,6.59z"/>
<path android:fillColor="#FEAF06" android:pathData="M7.141,13.406c0.526,-0.103 1.178,-0.22 1.665,-0.322c1.522,-0.319 2.625,-1.229 3.273,-2.678c0.289,-0.647 0.702,-1.125 1.448,-1.42c0.418,0.811 0.454,1.641 0.223,2.493c-0.284,1.049 -0.889,1.863 -1.819,2.429c-0.616,0.376 -1.284,0.638 -1.966,0.867C8.814,15.163 7.797,14.773 7.141,13.406z"/>
<path android:fillColor="#FEAF06" android:pathData="M12.313,14.203c0.734,-0.537 1.25,-1.089 1.469,-1.612c0.894,0.159 1.92,0.314 2.804,0.471C16.036,14.799 13.922,15.203 12.313,14.203z"/>
<path android:fillColor="#FEAF06" android:pathData="M2.377,13.882c0.179,-0.123 0.756,-0.189 1.192,-0.123c0.259,0.631 0.587,1.225 1.108,1.923c-0.572,0.116 -1.037,0.253 -1.567,0.224c-0.493,-0.027 -0.993,-0.353 -1.063,-0.989C2.013,14.61 2.047,14.109 2.377,13.882z"/>
<path android:fillColor="#FEAF06" android:pathData="M19.143,15.22c0.196,-0.497 0.362,-0.961 0.561,-1.411c0.235,-0.531 0.618,-0.76 1.121,-0.681c0.419,0.066 0.575,0.376 0.644,0.756c0.098,0.541 -0.078,0.989 -0.529,1.213C20.38,15.377 19.787,15.293 19.143,15.22z"/>
</vector>

View file

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M18.253,15.869c1.19,0 2.158,-1.02 2.158,-2.274c0,-1.254 -0.968,-2.275 -2.158,-2.275c-1.19,0 -2.158,1.02 -2.158,2.275C16.095,14.849 17.063,15.869 18.253,15.869zM18.253,12.018c0.824,0 1.496,0.707 1.496,1.576c0,0.869 -0.671,1.576 -1.496,1.576s-1.496,-0.707 -1.496,-1.576C16.757,12.725 17.429,12.018 18.253,12.018z"
android:fillColor="@color/exercise"/>
<path
android:pathData="M21.442,18.522c-0.03,-0.043 -0.745,-1.039 -1.801,-1.039c-0.785,0 -1.295,0.514 -1.746,0.969c-0.399,0.402 -0.744,0.75 -1.226,0.75h-0.001c-0.393,0 -0.714,-0.242 -1.034,-0.538l1.665,-1.325l-4.553,-6.356l-4.394,3.496c-0.259,0.242 -0.627,0.87 -0.164,1.515c0.214,0.298 0.463,0.387 0.635,0.41c0.409,0.053 0.738,-0.217 0.765,-0.24l2.759,-2.195l0.676,0.943l-3.964,3.153c-0.371,-0.351 -0.791,-0.637 -1.305,-0.637H7.753c-0.788,0 -1.457,0.64 -2.048,1.205c-0.352,0.337 -0.752,0.72 -0.973,0.72c-0.428,0 -0.982,-0.647 -1.142,-0.874c-0.109,-0.154 -0.316,-0.186 -0.464,-0.071c-0.147,0.115 -0.178,0.333 -0.069,0.488c0.083,0.119 0.837,1.155 1.674,1.155c0.477,0 0.913,-0.417 1.418,-0.9c0.502,-0.48 1.071,-1.024 1.603,-1.024h0c0.469,0 0.879,0.45 1.313,0.927c0.482,0.529 0.981,1.077 1.659,1.077c0.647,0 1.193,-0.472 1.722,-0.929c0.494,-0.427 1.005,-0.868 1.542,-0.868c0.321,0.001 0.622,0.293 0.97,0.631c0.453,0.439 0.965,0.936 1.71,0.936h0.001c0.748,0 1.245,-0.501 1.684,-0.943c0.413,-0.416 0.769,-0.776 1.287,-0.776c0.719,0 1.264,0.751 1.269,0.759c0.11,0.155 0.317,0.184 0.464,0.07C21.52,18.894 21.551,18.677 21.442,18.522zM12.027,18.661c-0.459,0.396 -0.892,0.771 -1.301,0.771c-0.395,-0.001 -0.777,-0.42 -1.181,-0.862c-0.002,-0.003 -0.005,-0.005 -0.007,-0.008l4.415,-3.512l-1.475,-2.059L9.18,15.614c-0.022,0.019 -0.161,0.12 -0.276,0.096c-0.024,-0.003 -0.097,-0.012 -0.186,-0.136c-0.195,-0.273 0.01,-0.509 0.055,-0.555l3.844,-3.058l3.754,5.241l-1.24,0.986c-0.332,-0.301 -0.69,-0.554 -1.143,-0.554C13.214,17.635 12.584,18.18 12.027,18.661z"
android:fillColor="@color/exercise"/>
<path
android:pathData="M5.453,9.325c-0.003,0 -0.006,0 -0.01,0C5.031,9.317 4.661,8.827 4.43,7.979C4.261,7.361 4.108,6.716 3.96,6.092C3.867,5.701 3.774,5.31 3.677,4.924l-0.064,-0.26C3.394,3.77 3.168,2.847 2.577,2.743C2.509,2.731 2.463,2.665 2.475,2.595c0.012,-0.07 0.077,-0.114 0.146,-0.104c0.752,0.133 0.999,1.138 1.237,2.11l0.064,0.259c0.097,0.388 0.19,0.78 0.283,1.172c0.147,0.622 0.3,1.264 0.468,1.878C4.864,8.61 5.168,9.064 5.448,9.069c0.001,0 0.003,0 0.005,0c0.263,0 0.537,-0.394 0.753,-1.083C6.317,7.63 6.413,7.247 6.505,6.877l0.074,-0.293C6.66,6.262 6.737,5.935 6.815,5.609C6.973,4.94 7.137,4.248 7.336,3.608c0.221,-0.71 0.551,-1.103 0.928,-1.106c0.002,0 0.003,0 0.005,0c0.379,0 0.717,0.39 0.951,1.1c0.165,0.5 0.305,1.039 0.439,1.56l0.105,0.403c0.087,0.332 0.171,0.668 0.255,1.004c0.143,0.574 0.29,1.169 0.456,1.729c0.136,0.462 0.367,0.757 0.603,0.769c0.211,0.026 0.432,-0.218 0.6,-0.625c0.161,-0.391 0.309,-0.847 0.451,-1.393c0.198,-0.76 0.385,-1.53 0.572,-2.3c0.086,-0.355 0.173,-0.711 0.26,-1.065c0.167,-0.676 0.481,-1.066 0.961,-1.191c0.066,-0.017 0.136,0.024 0.154,0.092c0.017,0.068 -0.023,0.138 -0.091,0.156c-0.387,0.101 -0.634,0.421 -0.779,1.005c-0.087,0.354 -0.174,0.709 -0.26,1.064c-0.188,0.771 -0.375,1.543 -0.573,2.304c-0.145,0.557 -0.297,1.024 -0.462,1.426c-0.289,0.703 -0.651,0.793 -0.846,0.782c-0.35,-0.018 -0.661,-0.374 -0.832,-0.951c-0.167,-0.565 -0.315,-1.163 -0.459,-1.74c-0.083,-0.335 -0.166,-0.67 -0.253,-1.001L9.415,5.226C9.282,4.709 9.143,4.174 8.981,3.682c-0.192,-0.58 -0.458,-0.926 -0.712,-0.926c-0.001,0 -0.001,0 -0.002,0c-0.252,0.002 -0.51,0.349 -0.69,0.928C7.38,4.316 7.217,5.004 7.06,5.668C6.982,5.996 6.905,6.324 6.823,6.647L6.75,6.939C6.656,7.314 6.56,7.701 6.446,8.063C6.121,9.103 5.728,9.325 5.453,9.325z"
android:fillColor="@color/inrange"/>
<path
android:pathData="M13.949,6.338h-2.831c-0.232,0 -0.421,-0.193 -0.421,-0.431V4.19H5.856l0,1.717c0,0.238 -0.188,0.431 -0.42,0.431h-2.84c-0.232,0 -0.42,-0.193 -0.42,-0.431c0,-0.238 0.188,-0.431 0.42,-0.431h2.42l0,-1.717c0,-0.238 0.188,-0.431 0.42,-0.431h5.682c0.232,0 0.421,0.193 0.421,0.431v1.717h2.411c0.232,0 0.421,0.193 0.421,0.431C14.37,6.145 14.181,6.338 13.949,6.338z"
android:fillColor="@color/tempTargetConfirmation"/>
</vector>

View file

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M16.954,15.325l3.851,-3.85c0.314,-0.314 0.314,-0.821 0.001,-1.134c-0.315,-0.315 -0.82,-0.314 -1.134,-0.001l-3.851,3.851l-3.851,-3.851c-0.315,-0.313 -0.821,-0.314 -1.134,0.001c-0.313,0.313 -0.313,0.82 0.001,1.134l3.851,3.85l-3.851,3.851c-0.314,0.313 -0.314,0.82 -0.001,1.133c0.157,0.156 0.362,0.235 0.567,0.235s0.41,-0.078 0.567,-0.235l3.851,-3.85l3.851,3.85c0.157,0.156 0.362,0.235 0.567,0.235c0.205,0 0.411,-0.078 0.567,-0.235c0.313,-0.313 0.313,-0.82 -0.001,-1.133L16.954,15.325z"
android:fillColor="@color/tempTargetConfirmation"/>
<path
android:pathData="M5.453,9.325c-0.003,0 -0.006,0 -0.01,0C5.031,9.317 4.661,8.827 4.43,7.979C4.261,7.361 4.108,6.716 3.96,6.092C3.867,5.701 3.774,5.31 3.677,4.924l-0.064,-0.26C3.394,3.77 3.168,2.847 2.577,2.743C2.509,2.731 2.463,2.665 2.475,2.595c0.012,-0.07 0.077,-0.114 0.146,-0.104c0.752,0.133 0.999,1.138 1.237,2.11l0.064,0.259c0.097,0.388 0.19,0.78 0.283,1.172c0.147,0.622 0.3,1.264 0.468,1.878C4.864,8.61 5.168,9.064 5.448,9.069c0.001,0 0.003,0 0.005,0c0.263,0 0.537,-0.394 0.753,-1.083C6.317,7.63 6.413,7.247 6.505,6.877l0.074,-0.293C6.66,6.262 6.737,5.935 6.815,5.609C6.973,4.94 7.137,4.248 7.336,3.608c0.221,-0.71 0.551,-1.103 0.928,-1.106c0.002,0 0.003,0 0.005,0c0.379,0 0.717,0.39 0.951,1.1c0.165,0.5 0.305,1.039 0.439,1.56l0.105,0.403c0.087,0.332 0.171,0.668 0.255,1.004c0.143,0.574 0.29,1.169 0.456,1.729c0.136,0.462 0.367,0.757 0.603,0.769c0.211,0.026 0.432,-0.218 0.6,-0.625c0.161,-0.391 0.309,-0.847 0.451,-1.393c0.198,-0.76 0.385,-1.53 0.572,-2.3c0.086,-0.355 0.173,-0.711 0.26,-1.065c0.167,-0.676 0.481,-1.066 0.961,-1.191c0.066,-0.017 0.136,0.024 0.154,0.092c0.017,0.068 -0.023,0.138 -0.091,0.156c-0.387,0.101 -0.634,0.421 -0.779,1.005c-0.087,0.354 -0.174,0.709 -0.26,1.064c-0.188,0.771 -0.375,1.543 -0.573,2.304c-0.145,0.557 -0.297,1.024 -0.462,1.426c-0.289,0.703 -0.651,0.793 -0.846,0.782c-0.35,-0.018 -0.661,-0.374 -0.832,-0.951c-0.167,-0.565 -0.315,-1.163 -0.459,-1.74c-0.083,-0.335 -0.166,-0.67 -0.253,-1.001L9.415,5.226C9.282,4.709 9.143,4.174 8.981,3.682c-0.192,-0.58 -0.458,-0.926 -0.712,-0.926c-0.001,0 -0.001,0 -0.002,0c-0.252,0.002 -0.51,0.349 -0.69,0.928C7.38,4.316 7.217,5.004 7.06,5.668C6.982,5.996 6.905,6.324 6.823,6.647L6.75,6.939C6.656,7.314 6.56,7.701 6.446,8.063C6.121,9.103 5.728,9.325 5.453,9.325z"
android:fillColor="@color/inrange"/>
<path
android:pathData="M13.949,6.338H2.595c-0.232,0 -0.42,-0.193 -0.42,-0.431c0,-0.238 0.188,-0.431 0.42,-0.431h11.354c0.232,0 0.421,0.193 0.421,0.431C14.37,6.145 14.181,6.338 13.949,6.338z"
android:fillColor="@color/tempTargetConfirmation"/>
</vector>

View file

@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M21.107,18.396h-0.515c-0.23,-3.231 -2.587,-5.897 -5.66,-6.605c-0.089,-0.819 -0.777,-1.462 -1.62,-1.462c-0.843,0 -1.531,0.642 -1.62,1.462c-3.073,0.708 -5.429,3.374 -5.66,6.605H5.518c-0.221,0 -0.4,0.179 -0.4,0.4c0,0.221 0.179,0.4 0.4,0.4h15.59c0.221,0 0.4,-0.179 0.4,-0.4C21.507,18.575 21.328,18.396 21.107,18.396zM13.313,10.943c0.461,0 0.836,0.311 0.964,0.73c-0.317,-0.043 -0.637,-0.072 -0.964,-0.072c-0.327,0 -0.648,0.03 -0.965,0.072C12.477,11.254 12.852,10.943 13.313,10.943zM13.313,12.401c3.391,0 6.212,2.654 6.479,5.995H6.834C7.101,15.056 9.922,12.401 13.313,12.401z"
android:fillColor="@color/carbs"/>
<path
android:pathData="M15.428,13.489c-0.588,-0.271 -1.415,-0.457 -2.268,-0.509c-0.221,-0.014 -0.411,0.154 -0.424,0.375c-0.014,0.221 0.154,0.411 0.375,0.424c0.746,0.046 1.487,0.209 1.981,0.437c0.047,0.021 0.095,0.033 0.143,0.036c0.16,0.01 0.317,-0.078 0.388,-0.232C15.717,13.82 15.629,13.582 15.428,13.489z"
android:fillColor="@color/carbs"/>
<path
android:pathData="M8.051,17.801c-0.029,0.001 -0.061,-0.003 -0.095,-0.011c-0.188,-0.047 -0.304,-0.239 -0.257,-0.427c0.43,-1.726 1.665,-3.196 3.304,-3.933c0.043,-0.019 0.088,-0.029 0.135,-0.031c0.143,-0.004 0.273,0.078 0.331,0.208c0.039,0.086 0.042,0.182 0.008,0.271c-0.034,0.088 -0.099,0.158 -0.185,0.196c-1.444,0.649 -2.531,1.942 -2.909,3.458C8.346,17.687 8.209,17.797 8.051,17.801z"
android:fillColor="@color/carbs"/>
<path
android:pathData="M5.453,9.325c-0.003,0 -0.006,0 -0.01,0C5.031,9.317 4.661,8.827 4.43,7.979C4.261,7.361 4.108,6.716 3.96,6.092C3.867,5.701 3.774,5.31 3.677,4.924l-0.064,-0.26C3.394,3.77 3.168,2.847 2.577,2.743C2.509,2.731 2.463,2.665 2.475,2.595c0.012,-0.07 0.077,-0.114 0.146,-0.104c0.752,0.133 0.999,1.138 1.237,2.11l0.064,0.259c0.097,0.388 0.19,0.78 0.283,1.172c0.147,0.622 0.3,1.264 0.468,1.878C4.864,8.61 5.168,9.064 5.448,9.069c0.001,0 0.003,0 0.005,0c0.263,0 0.537,-0.394 0.753,-1.083C6.317,7.63 6.413,7.247 6.505,6.877l0.074,-0.293C6.66,6.262 6.737,5.935 6.815,5.609C6.973,4.94 7.137,4.248 7.336,3.608c0.221,-0.71 0.551,-1.103 0.928,-1.106c0.002,0 0.003,0 0.005,0c0.379,0 0.717,0.39 0.951,1.1c0.165,0.5 0.305,1.039 0.439,1.56l0.105,0.403c0.087,0.332 0.171,0.668 0.255,1.004c0.143,0.574 0.29,1.169 0.456,1.729c0.136,0.462 0.367,0.757 0.603,0.769c0.211,0.026 0.432,-0.218 0.6,-0.625c0.161,-0.391 0.309,-0.847 0.451,-1.393c0.198,-0.76 0.385,-1.53 0.572,-2.3c0.086,-0.355 0.173,-0.711 0.26,-1.065c0.167,-0.676 0.481,-1.066 0.961,-1.191c0.066,-0.017 0.136,0.024 0.154,0.092c0.017,0.068 -0.023,0.138 -0.091,0.156c-0.387,0.101 -0.634,0.421 -0.779,1.005c-0.087,0.354 -0.174,0.709 -0.26,1.064c-0.188,0.771 -0.375,1.543 -0.573,2.304c-0.145,0.557 -0.297,1.024 -0.462,1.426c-0.289,0.703 -0.651,0.793 -0.846,0.782c-0.35,-0.018 -0.661,-0.374 -0.832,-0.951c-0.167,-0.565 -0.315,-1.163 -0.459,-1.74c-0.083,-0.335 -0.166,-0.67 -0.253,-1.001L9.415,5.226C9.282,4.709 9.143,4.174 8.981,3.682c-0.192,-0.58 -0.458,-0.926 -0.712,-0.926c-0.001,0 -0.001,0 -0.002,0c-0.252,0.002 -0.51,0.349 -0.69,0.928C7.38,4.316 7.217,5.004 7.06,5.668C6.982,5.996 6.905,6.324 6.823,6.647L6.75,6.939C6.656,7.314 6.56,7.701 6.446,8.063C6.121,9.103 5.728,9.325 5.453,9.325z"
android:fillColor="@color/inrange"/>
<path
android:pathData="M11.122,8.486H5.436c-0.232,0 -0.42,-0.193 -0.42,-0.431l0,-1.717h-2.42c-0.232,0 -0.42,-0.193 -0.42,-0.431c0,-0.238 0.188,-0.431 0.42,-0.431h2.84c0.232,0 0.42,0.193 0.42,0.431l0,1.717h4.845V5.907c0,-0.238 0.188,-0.431 0.421,-0.431h2.827c0.232,0 0.421,0.193 0.421,0.431c0,0.238 -0.188,0.431 -0.421,0.431h-2.407v1.717C11.542,8.293 11.354,8.486 11.122,8.486z"
android:fillColor="@color/tempTargetConfirmation"/>
</vector>

View file

@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M8.822,17.137c-0.016,-0.28 0.022,-0.543 0.363,-0.583c0.313,-0.037 0.426,0.189 0.462,0.448c0.135,0.983 0.67,1.563 1.668,1.692c0.292,0.038 0.514,0.167 0.459,0.498c-0.051,0.305 -0.324,0.337 -0.568,0.336C10.03,19.526 8.835,18.321 8.822,17.137z"
android:fillColor="@color/low"/>
<path
android:pathData="M15.21,16.109c-0.631,-2.484 -3.383,-6.32 -3.773,-6.32s-3.151,3.845 -3.779,6.324c-0.42,1.658 0.111,3.081 1.577,4.049c1.43,0.944 2.973,0.929 4.402,-0.013C15.106,19.18 15.634,17.779 15.21,16.109zM13.255,19.568c-0.603,0.397 -1.221,0.599 -1.835,0.599c-0.607,0 -1.213,-0.197 -1.802,-0.586c-1.206,-0.796 -1.639,-1.906 -1.287,-3.298c0.489,-1.929 2.895,-5.336 3.105,-5.336s2.609,3.403 3.1,5.333C14.889,17.668 14.458,18.774 13.255,19.568z"
android:fillColor="@color/low"/>
<path
android:pathData="M19.522,16.771v-6.712h-1.423v6.712h-2.135l2.846,3.82l2.846,-3.82H19.522z"
android:fillColor="@color/low"/>
<path
android:pathData="M5.453,9.325c-0.003,0 -0.006,0 -0.01,0C5.031,9.317 4.661,8.827 4.43,7.979C4.261,7.361 4.108,6.716 3.96,6.092C3.867,5.701 3.774,5.31 3.677,4.924l-0.064,-0.26C3.394,3.77 3.168,2.847 2.577,2.743C2.509,2.731 2.463,2.665 2.475,2.595c0.012,-0.07 0.077,-0.114 0.146,-0.104c0.752,0.133 0.999,1.138 1.237,2.11l0.064,0.259c0.097,0.388 0.19,0.78 0.283,1.172c0.147,0.622 0.3,1.264 0.468,1.878C4.864,8.61 5.168,9.064 5.448,9.069c0.001,0 0.003,0 0.005,0c0.263,0 0.537,-0.394 0.753,-1.083C6.317,7.63 6.413,7.247 6.505,6.877l0.074,-0.293C6.66,6.262 6.737,5.935 6.815,5.609C6.973,4.94 7.137,4.248 7.336,3.608c0.221,-0.71 0.551,-1.103 0.928,-1.106c0.002,0 0.003,0 0.005,0c0.379,0 0.717,0.39 0.951,1.1c0.165,0.5 0.305,1.039 0.439,1.56l0.105,0.403c0.087,0.332 0.171,0.668 0.255,1.004c0.143,0.574 0.29,1.169 0.456,1.729c0.136,0.462 0.367,0.757 0.603,0.769c0.211,0.026 0.432,-0.218 0.6,-0.625c0.161,-0.391 0.309,-0.847 0.451,-1.393c0.198,-0.76 0.385,-1.53 0.572,-2.3c0.086,-0.355 0.173,-0.711 0.26,-1.065c0.167,-0.676 0.481,-1.066 0.961,-1.191c0.066,-0.017 0.136,0.024 0.154,0.092c0.017,0.068 -0.023,0.138 -0.091,0.156c-0.387,0.101 -0.634,0.421 -0.779,1.005c-0.087,0.354 -0.174,0.709 -0.26,1.064c-0.188,0.771 -0.375,1.543 -0.573,2.304c-0.145,0.557 -0.297,1.024 -0.462,1.426c-0.289,0.703 -0.651,0.793 -0.846,0.782c-0.35,-0.018 -0.661,-0.374 -0.832,-0.951c-0.167,-0.565 -0.315,-1.163 -0.459,-1.74c-0.083,-0.335 -0.166,-0.67 -0.253,-1.001L9.415,5.226C9.282,4.709 9.143,4.174 8.981,3.682c-0.192,-0.58 -0.458,-0.926 -0.712,-0.926c-0.001,0 -0.001,0 -0.002,0c-0.252,0.002 -0.51,0.349 -0.69,0.928C7.38,4.316 7.217,5.004 7.06,5.668C6.982,5.996 6.905,6.324 6.823,6.647L6.75,6.939C6.656,7.314 6.56,7.701 6.446,8.063C6.121,9.103 5.728,9.325 5.453,9.325z"
android:fillColor="@color/inrange"/>
<path
android:pathData="M13.949,6.338h-2.831c-0.232,0 -0.421,-0.193 -0.421,-0.431V4.19H5.856l0,1.717c0,0.238 -0.188,0.431 -0.42,0.431h-2.84c-0.232,0 -0.42,-0.193 -0.42,-0.431c0,-0.238 0.188,-0.431 0.42,-0.431h2.42l0,-1.717c0,-0.238 0.188,-0.431 0.42,-0.431h5.682c0.232,0 0.421,0.193 0.421,0.431v1.717h2.411c0.232,0 0.421,0.193 0.421,0.431C14.37,6.145 14.181,6.338 13.949,6.338z"
android:fillColor="@color/tempTargetConfirmation"/>
</vector>

View file

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M16.438,8.901L9.729,15.61c-0.054,0.054 -0.09,0.122 -0.103,0.196L8.825,20.15c-0.022,0.121 0.016,0.245 0.103,0.332s0.211,0.126 0.332,0.103l4.343,-0.801c0.074,-0.014 0.143,-0.05 0.196,-0.103l6.709,-6.709c0.391,-0.391 0.39,-1.029 -0.002,-1.421l-2.648,-2.648C17.467,8.511 16.829,8.51 16.438,8.901zM12.907,18.755c0.085,0.085 0.116,0.211 0.08,0.326c-0.016,0.051 -0.044,0.096 -0.08,0.132c-0.046,0.046 -0.106,0.078 -0.173,0.09l-2.164,0.382c-0.215,-0.007 -0.428,-0.091 -0.592,-0.255c-0.164,-0.164 -0.248,-0.377 -0.255,-0.591l0.382,-2.164c0.021,-0.119 0.107,-0.216 0.222,-0.253c0.115,-0.036 0.241,-0.005 0.326,0.08L12.907,18.755zM19.949,12.025c0.124,0.124 0.124,0.324 0,0.447l-5.929,5.929c-0.124,0.124 -0.324,0.124 -0.447,0l-0.233,-0.233c-0.124,-0.124 -0.124,-0.324 0,-0.447l5.929,-5.929c0.124,-0.124 0.324,-0.124 0.447,0L19.949,12.025zM18.793,10.85c0.124,0.124 0.124,0.324 0,0.447l-5.929,5.929c-0.124,0.124 -0.324,0.124 -0.447,0l-0.233,-0.233c-0.124,-0.124 -0.124,-0.324 0,-0.447l5.929,-5.929c0.124,-0.124 0.324,-0.124 0.447,0L18.793,10.85zM17.637,9.675c0.124,0.124 0.124,0.324 0,0.447l-5.929,5.929c-0.124,0.124 -0.324,0.124 -0.447,0l-0.233,-0.233c-0.124,-0.124 -0.124,-0.324 0,-0.447l5.929,-5.929c0.124,-0.124 0.324,-0.124 0.447,0L17.637,9.675z"
android:fillColor="@color/tempTargetConfirmation"/>
<path
android:pathData="M5.453,9.325c-0.003,0 -0.006,0 -0.01,0C5.031,9.317 4.661,8.827 4.43,7.979C4.261,7.361 4.108,6.716 3.96,6.092C3.867,5.701 3.774,5.31 3.677,4.924l-0.064,-0.26C3.394,3.77 3.168,2.847 2.577,2.743C2.509,2.731 2.463,2.665 2.475,2.595c0.012,-0.07 0.077,-0.114 0.146,-0.104c0.752,0.133 0.999,1.138 1.237,2.11l0.064,0.259c0.097,0.388 0.19,0.78 0.283,1.172c0.147,0.622 0.3,1.264 0.468,1.878C4.864,8.61 5.168,9.064 5.448,9.069c0.001,0 0.003,0 0.005,0c0.263,0 0.537,-0.394 0.753,-1.083C6.317,7.63 6.413,7.247 6.505,6.877l0.074,-0.293C6.66,6.262 6.737,5.935 6.815,5.609C6.973,4.94 7.137,4.248 7.336,3.608c0.221,-0.71 0.551,-1.103 0.928,-1.106c0.002,0 0.003,0 0.005,0c0.379,0 0.717,0.39 0.951,1.1c0.165,0.5 0.305,1.039 0.439,1.56l0.105,0.403c0.087,0.332 0.171,0.668 0.255,1.004c0.143,0.574 0.29,1.169 0.456,1.729c0.136,0.462 0.367,0.757 0.603,0.769c0.211,0.026 0.432,-0.218 0.6,-0.625c0.161,-0.391 0.309,-0.847 0.451,-1.393c0.198,-0.76 0.385,-1.53 0.572,-2.3c0.086,-0.355 0.173,-0.711 0.26,-1.065c0.167,-0.676 0.481,-1.066 0.961,-1.191c0.066,-0.017 0.136,0.024 0.154,0.092c0.017,0.068 -0.023,0.138 -0.091,0.156c-0.387,0.101 -0.634,0.421 -0.779,1.005c-0.087,0.354 -0.174,0.709 -0.26,1.064c-0.188,0.771 -0.375,1.543 -0.573,2.304c-0.145,0.557 -0.297,1.024 -0.462,1.426c-0.289,0.703 -0.651,0.793 -0.846,0.782c-0.35,-0.018 -0.661,-0.374 -0.832,-0.951c-0.167,-0.565 -0.315,-1.163 -0.459,-1.74c-0.083,-0.335 -0.166,-0.67 -0.253,-1.001L9.415,5.226C9.282,4.709 9.143,4.174 8.981,3.682c-0.192,-0.58 -0.458,-0.926 -0.712,-0.926c-0.001,0 -0.001,0 -0.002,0c-0.252,0.002 -0.51,0.349 -0.69,0.928C7.38,4.316 7.217,5.004 7.06,5.668C6.982,5.996 6.905,6.324 6.823,6.647L6.75,6.939C6.656,7.314 6.56,7.701 6.446,8.063C6.121,9.103 5.728,9.325 5.453,9.325z"
android:fillColor="@color/inrange"/>
<path
android:pathData="M13.949,6.338h-2.831c-0.232,0 -0.421,-0.193 -0.421,-0.431V4.19H5.856l0,1.717c0,0.238 -0.188,0.431 -0.42,0.431h-2.84c-0.232,0 -0.42,-0.193 -0.42,-0.431c0,-0.238 0.188,-0.431 0.42,-0.431h2.42l0,-1.717c0,-0.238 0.188,-0.431 0.42,-0.431h5.682c0.232,0 0.421,0.193 0.421,0.431v1.717h2.411c0.232,0 0.421,0.193 0.421,0.431C14.37,6.145 14.181,6.338 13.949,6.338z"
android:fillColor="@color/tempTargetConfirmation"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/inrange"
android:pathData="M7.242,17.689c-0.005,0 -0.011,0 -0.017,0c-0.695,-0.013 -1.318,-0.829 -1.709,-2.24c-0.285,-1.029 -0.542,-2.103 -0.792,-3.141c-0.156,-0.65 -0.313,-1.301 -0.476,-1.945L4.14,9.929c-0.369,-1.486 -0.75,-3.024 -1.746,-3.197c-0.116,-0.02 -0.193,-0.13 -0.173,-0.246s0.129,-0.189 0.246,-0.173C3.735,6.534 4.15,8.208 4.552,9.827l0.108,0.432c0.164,0.646 0.321,1.298 0.478,1.951c0.249,1.035 0.506,2.104 0.789,3.127c0.322,1.163 0.834,1.92 1.307,1.929c0.002,0 0.005,0 0.008,0c0.443,0 0.905,-0.656 1.269,-1.804c0.188,-0.592 0.349,-1.229 0.504,-1.847l0.124,-0.487c0.138,-0.536 0.268,-1.08 0.398,-1.624c0.267,-1.114 0.542,-2.265 0.878,-3.332c0.373,-1.182 0.928,-1.836 1.565,-1.842c0.003,0 0.005,0 0.008,0c0.639,0 1.208,0.65 1.603,1.832c0.278,0.833 0.514,1.729 0.74,2.598l0.177,0.671c0.147,0.553 0.288,1.112 0.43,1.672c0.24,0.956 0.489,1.945 0.769,2.879c0.229,0.77 0.619,1.26 1.017,1.28c0.356,0.043 0.729,-0.362 1.011,-1.041c0.271,-0.651 0.521,-1.41 0.761,-2.318c0.333,-1.265 0.648,-2.547 0.964,-3.829c0.146,-0.592 0.291,-1.184 0.438,-1.773c0.281,-1.125 0.812,-1.774 1.62,-1.983c0.111,-0.028 0.229,0.04 0.259,0.153c0.029,0.114 -0.039,0.229 -0.153,0.259c-0.652,0.168 -1.069,0.7 -1.313,1.674c-0.147,0.589 -0.293,1.181 -0.438,1.772c-0.316,1.284 -0.633,2.568 -0.966,3.836c-0.245,0.928 -0.5,1.704 -0.779,2.374c-0.487,1.17 -1.097,1.32 -1.426,1.302c-0.59,-0.03 -1.114,-0.622 -1.402,-1.584c-0.281,-0.941 -0.531,-1.936 -0.773,-2.896c-0.14,-0.558 -0.28,-1.115 -0.427,-1.666l-0.178,-0.673c-0.225,-0.861 -0.458,-1.751 -0.731,-2.57c-0.323,-0.966 -0.772,-1.541 -1.201,-1.541c-0.001,0 -0.002,0 -0.004,0c-0.425,0.003 -0.86,0.581 -1.164,1.544c-0.331,1.052 -0.605,2.196 -0.87,3.303c-0.131,0.546 -0.262,1.092 -0.399,1.63l-0.124,0.486c-0.158,0.623 -0.32,1.268 -0.512,1.871C8.367,17.32 7.706,17.689 7.242,17.689z" />
<path
android:fillColor="@color/tempTargetConfirmation"
android:pathData="M21.563,12.709H2.424c-0.392,0 -0.708,-0.317 -0.708,-0.709s0.317,-0.708 0.708,-0.708h19.139c0.392,0 0.709,0.317 0.709,0.708S21.954,12.709 21.563,12.709z" />
</vector>

File diff suppressed because one or more lines are too long

View file

@ -1,8 +1,7 @@
<androidx.wear.widget.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="15dp">
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.wear.widget.CurvedTextView
android:id="@+id/title_curved"
@ -32,6 +33,7 @@
android:id="@+id/page_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom" />
android:layout_gravity="center_horizontal|bottom"
app:dotFadeOutDelay="100000"/>
</FrameLayout>

View file

@ -49,7 +49,7 @@
<item>@string/menu_default</item>
<item>@string/menu_menu</item>
<item>@string/menu_wizard</item>
<item>@string/menu_bolus</item>
<item>@string/menu_treatment</item>
<item>@string/menu_ecarb</item>
<item>@string/menu_status</item>
<item>@string/menu_none</item>
@ -79,4 +79,40 @@
<item>ambient_charging</item>
</string-array>
<string-array name="tile_action_names">
<item>@string/menu_wizard</item>
<item>@string/menu_treatment</item>
<item>@string/menu_bolus</item>
<item>@string/menu_ecarb</item>
<item>@string/menu_tempt</item>
<item>@string/tile_none</item>
</string-array>
<string-array name="tile_action_values">
<item>wizard</item>
<item>treatment</item>
<item>bolus</item>
<item>carbs</item>
<item>temp_target</item>
<item>none</item>
</string-array>
<string-array name="tile_tempt_names">
<item>@string/temp_target_activity</item>
<item>@string/temp_target_eating_soon</item>
<item>@string/temp_target_hypo</item>
<item>@string/temp_target_manual</item>
<item>@string/temp_target_cancel</item>
<item>@string/tile_none</item>
</string-array>
<string-array name="tile_tempt_values">
<item>activity</item>
<item>eating_soon</item>
<item>hypo</item>
<item>manual</item>
<item>cancel</item>
<item>none</item>
</string-array>
</resources>

View file

@ -46,6 +46,13 @@
<color name="colorTemptButton">#CF8BFE</color>
<color name="colorPrimeButton">#FBC02D</color>
<color name="inrange">#00FF00</color>
<color name="exercise">#67DFE8</color>
<color name="carbs">#FFFB8C00</color>
<color name="low">#FF0000</color>
<color name="tempTargetConfirmation">#77dd77</color>
<!-- Material Design - Color Palette -->
<!-- https://designguidelines.withgoogle.com/wearos/style/color.html#color-dark-color-palette-for-wear-os -->
<!-- https://material.io/design/color/the-color-system.html#tools-for-picking-colors -->
@ -157,13 +164,16 @@
<color name="brown_900">#3E2723</color>
<!-- Gray / Grey -->
<!-- @ToDo Replace all usage from grey to gray, because that's the official color name in https://material.io/deign/color/ -->
<!-- @ToDo Replace all usage from grey to gray, because that's the official color name in https://material.io/deign/color/ -->
<color name="grey_50">#FAFAFA</color>
<color name="gray_100">#F5F5F5</color>
<color name="grey_300">#E0E0E0</color>
<color name="grey_500">#9E9E9E</color>
<color name="gray_500">#9E9E9E</color> <!-- needed because rICTxWF01 generate color-names as grAy -->
<color name="gray_500">#9E9E9E
</color> <!-- needed because rICTxWF01 generate color-names as grAy -->
<color name="gray_700">#616161</color>
<color name="gray_800">#424242</color>
<color name="gray_850">#313131</color>
<color name="gray_900">#212121</color>
<color name="grey_steampunk">#333333</color>

View file

@ -14,6 +14,9 @@
<string name="label_xdrip_steampunk">AAPS(Steampunk)</string>
<string name="label_digitalstyle">AAPS(DigitalStyle)</string>
<string name="label_actions_tile">AAPS(Actions)</string>
<string name="label_temp_target_tile">AAPS(Temp Target)</string>
<string name="label_quick_wizard_tile">AAPS(Quick Wizard)</string>
<string name="label_warning_sync">No data!</string>
<string name="label_warning_old">Old data!</string>
@ -60,21 +63,23 @@
<string name="pref_ring_history">Ring History</string>
<string name="pref_light_ring_history">Light Ring History</string>
<string name="pref_animations">Animations</string>
<string name="pref_wizard_in_menu">Wizard in Menu</string>
<string name="pref_wizard_in_menu">Calculator in Menu</string>
<string name="pref_prime_in_menu">Prime in Menu</string>
<string name="pref_single_target">Single Target</string>
<string name="pref_wizard_percentage">Wizard Percentage</string>
<string name="pref_wizard_percentage">Calculator Percentage</string>
<string name="pref_complication_tap_action">Complication Tap Action</string>
<string name="pref_unicode_in_complications">Unicode in Complications</string>
<string name="pref_version">Version:</string>
<string name="pref_moreWatchfaceSettings">more Watchface settings</string>
<string name="pref_lookInYourWatchfaceConfiguration">Look into Watchface configuration, please.</string>
<string name="menu_tempt">TempT</string>
<string name="menu_wizard">Wizard</string>
<string name="menu_wizard">Calculator</string>
<string name="menu_wizard_short">Calc</string>
<string name="menu_treatment">Treatment</string>
<string name="menu_treatment_short">Treat</string>
<string name="menu_bolus">Bolus</string>
<string name="menu_ecarb">eCarb</string>
<string name="menu_ecarb">Carbs</string>
<string name="menu_settings">Settings</string>
<string name="menu_status">Status</string>
<string name="menu_resync">Re-Sync</string>
@ -82,23 +87,32 @@
<string name="menu_none">None</string>
<string name="menu_default">Default</string>
<string name="menu_menu">Menu</string>
<string name="quick_wizard_short">XL</string>
<string name="action_duration">duration</string>
<string name="action_target" comment="In temp target menu, single target value">target</string>
<string name="action_low" comment="In temp target menu, lower value from range">low</string>
<string name="action_high" comment="In temp target menu, higher value from range">high</string>
<string name="action_carbs">carbs</string>
<string name="action_percentage">percentage</string>
<string name="action_start_min">start [min]</string>
<string name="action_duration_h">duration [h]</string>
<string name="action_insulin">insulin</string>
<string name="action_duration">Duration</string>
<string name="action_tempt_confirmation">Temp Target Requested</string>
<string name="action_quick_wizard_confirmation">Quick Wizard Requested</string>
<string name="action_treatment_confirmation">Treatment Requested</string>
<string name="action_bolus_confirmation">Bolus Requested</string>
<string name="action_wizard_confirmation">Calculation Requested</string>
<string name="action_fill_confirmation">Fill Requested</string>
<string name="action_ecarb_confirmation">Carbs Requested</string>
<string name="action_cpp_confirmation">CPP Requested</string>
<string name="action_target" comment="In temp target menu, single target value">Target</string>
<string name="action_low" comment="In temp target menu, lower value from range">Low</string>
<string name="action_high" comment="In temp target menu, higher value from range">High</string>
<string name="action_carbs">Carbs</string>
<string name="action_percentage">Percentage</string>
<string name="action_start_min">Start [min]</string>
<string name="action_duration_h">Duration [h]</string>
<string name="action_insulin">Insulin</string>
<string name="action_preset_1">Preset 1</string>
<string name="action_preset_2">Preset 2</string>
<string name="action_preset_3">Preset 3</string>
<string name="action_free_amount" comment="In prime/fill menu, allows to enter any amount to be used for priming/filling">Free amount</string>
<string name="action_confirm">CONFIRM</string>
<string name="action_timeshift">timeshift</string>
<string name="action_bolus">bolus</string>
<string name="action_bolus">Bolus</string>
<string name="bolus_progress">Bolus Progress</string>
<string name="press_to_cancel">press to cancel</string>
@ -113,7 +127,6 @@
<string name="activity_IOB">IOB</string>
<string name="activity_no_status">no status</string>
<string name="color_name_red">red</string>
<string name="color_name_pink">pink</string>
<string name="color_name_purple">purple</string>
@ -139,7 +152,6 @@
<string name="pref_simplify_ui">Simplify UI</string>
<string name="pref_simplify_ui_sum">Only show time and BG</string>
<string name="pref_vibrate_hourly">Vibrate hourly</string>
<string name="pref_show_weeknumber">Show Week number</string>
@ -156,10 +168,25 @@
<string name="bolus_progress_silent_channel_name">AAPS Bolus Progress Silent</string>
<string name="bolus_progress_channel_description">Bolus progress and cancel</string>
<string name="bolus_progress_silent_channel_description">Bolus progress and cancel with less vibrations</string>
<string name="key_quickwizard" translatable="false">QuickWizard</string>
<string name="key_wear_control" translatable="false">wearcontrol</string>
<string name="key_units_mgdl" translatable="false">units_mgdl</string>
<string name="key_boluswizard_percentage" translatable="false">boluswizard_percentage</string>
<string name="key_treatmentssafety_maxcarbs" translatable="false">treatmentssafety_maxcarbs</string>
<string name="key_treatmentssafety_maxbolus" translatable="false">treatmentssafety_maxbolus</string>
<string name="simple_ui_off">Off</string>
<string name="simple_ui_charging">During Charging</string>
<string name="simple_ui_always_on">Always On Mode</string>
<string name="simple_ui_always_on_charging">Always On and Charging</string>
<string name="temp_target_eating_soon">Eating</string>
<string name="temp_target_hypo">Hypo</string>
<string name="temp_target_activity">Activity</string>
<string name="temp_target_manual">Manual</string>
<string name="temp_target_cancel">Cancel</string>
<string name="tile_none">None</string>
<string name="tile_no_config">No config available</string>
<string name="wear_control_not_enabled">Wear controls disabled</string>
<string name="wear_control_no_data">No data available</string>
<string name="key_quick_wizard_data_map" translatable="false">quick_wizard_data_map</string>
</resources>

View file

@ -101,15 +101,6 @@
android:summary="Chart Timeframe"
android:title="@string/pref_chart_timeframe" />
<CheckBoxPreference
android:defaultValue="true"
android:key="units_mgdl"
android:summaryOff="mmol/l"
android:summaryOn="mg/dl"
android:title="@string/pref_units_for_actions"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />
<ListPreference
android:defaultValue="1"
android:entries="@array/input_design"
@ -121,7 +112,7 @@
<CheckBoxPreference
android:defaultValue="true"
android:key="showWizard"
android:summary="Wizard from watch possible"
android:summary="Calculator from watch possible"
android:title="@string/pref_wizard_in_menu"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ListPreference
android:key="tile_action_1"
android:title="Action 1"
android:defaultValue="wizard"
android:entries="@array/tile_action_names"
android:entryValues="@array/tile_action_values"/>
<ListPreference
android:key="tile_action_2"
android:title="Action 2"
android:defaultValue="treatment"
android:entries="@array/tile_action_names"
android:entryValues="@array/tile_action_values"/>
<ListPreference
android:key="tile_action_3"
android:title="Action 3"
android:defaultValue="carbs"
android:entries="@array/tile_action_names"
android:entryValues="@array/tile_action_values"/>
<ListPreference
android:key="tile_action_4"
android:title="Action 4"
android:defaultValue="temp_target"
android:entries="@array/tile_action_names"
android:entryValues="@array/tile_action_values"/>
</PreferenceScreen>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ListPreference
android:key="tile_tempt_1"
android:title="Target 1"
android:defaultValue="activity"
android:entries="@array/tile_tempt_names"
android:entryValues="@array/tile_tempt_values"/>
<ListPreference
android:key="tile_tempt_2"
android:title="Target 2"
android:defaultValue="eating_soon"
android:entries="@array/tile_tempt_names"
android:entryValues="@array/tile_tempt_values"/>
<ListPreference
android:key="tile_tempt_3"
android:title="Target 3"
android:defaultValue="hypo"
android:entries="@array/tile_tempt_names"
android:entryValues="@array/tile_tempt_values"/>
<ListPreference
android:key="tile_tempt_4"
android:title="Target 4"
android:defaultValue="manual"
android:entries="@array/tile_tempt_names"
android:entryValues="@array/tile_tempt_values"/>
</PreferenceScreen>