Merge pull request #1362 from Andries-Smit/feat/toolbar-treatment
Feature toolbar with options menu in Treatments
This commit is contained in:
commit
c0dbe41899
34 changed files with 1359 additions and 791 deletions
|
@ -1,13 +1,13 @@
|
||||||
package info.nightscout.androidaps.activities
|
package info.nightscout.androidaps.activities
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentTransaction
|
import androidx.fragment.app.FragmentTransaction
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.activities.fragments.*
|
import info.nightscout.androidaps.activities.fragments.*
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding
|
import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -23,40 +23,60 @@ class TreatmentsActivity : NoSplashAppCompatActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = TreatmentsFragmentBinding.inflate(layoutInflater)
|
binding = TreatmentsFragmentBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
//binding.tempBasals.visibility = buildHelper.isEngineeringMode().toVisibility()
|
//binding.tempBasals.visibility = buildHelper.isEngineeringMode().toVisibility()
|
||||||
//binding.extendedBoluses.visibility = (buildHelper.isEngineeringMode() && !activePlugin.activePump.isFakingTempsByExtendedBoluses).toVisibility()
|
//binding.extendedBoluses.visibility = (buildHelper.isEngineeringMode() && !activePlugin.activePump.isFakingTempsByExtendedBoluses).toVisibility()
|
||||||
|
|
||||||
binding.treatments.setOnClickListener {
|
binding.treatments.setOnClickListener {
|
||||||
setFragment(TreatmentsBolusCarbsFragment())
|
setFragment(TreatmentsBolusCarbsFragment())
|
||||||
setBackgroundColorOnSelected(it)
|
setBackgroundColorOnSelected(it)
|
||||||
|
supportActionBar?.title = rh.gs(R.string.carbs_and_bolus)
|
||||||
}
|
}
|
||||||
binding.extendedBoluses.setOnClickListener {
|
binding.extendedBoluses.setOnClickListener {
|
||||||
setFragment(TreatmentsExtendedBolusesFragment())
|
setFragment(TreatmentsExtendedBolusesFragment())
|
||||||
setBackgroundColorOnSelected(it)
|
setBackgroundColorOnSelected(it)
|
||||||
|
supportActionBar?.title = rh.gs(R.string.extended_bolus)
|
||||||
}
|
}
|
||||||
binding.tempBasals.setOnClickListener {
|
binding.tempBasals.setOnClickListener {
|
||||||
setFragment(TreatmentsTemporaryBasalsFragment())
|
setFragment(TreatmentsTemporaryBasalsFragment())
|
||||||
setBackgroundColorOnSelected(it)
|
setBackgroundColorOnSelected(it)
|
||||||
|
supportActionBar?.title = rh.gs(R.string.tempbasal_label)
|
||||||
}
|
}
|
||||||
binding.tempTargets.setOnClickListener {
|
binding.tempTargets.setOnClickListener {
|
||||||
setFragment(TreatmentsTempTargetFragment())
|
setFragment(TreatmentsTempTargetFragment())
|
||||||
setBackgroundColorOnSelected(it)
|
setBackgroundColorOnSelected(it)
|
||||||
|
supportActionBar?.title = rh.gs(R.string.tempt_targets)
|
||||||
}
|
}
|
||||||
binding.profileSwitches.setOnClickListener {
|
binding.profileSwitches.setOnClickListener {
|
||||||
setFragment(TreatmentsProfileSwitchFragment())
|
setFragment(TreatmentsProfileSwitchFragment())
|
||||||
setBackgroundColorOnSelected(it)
|
setBackgroundColorOnSelected(it)
|
||||||
|
supportActionBar?.title = rh.gs(R.string.profile_changes)
|
||||||
}
|
}
|
||||||
binding.careportal.setOnClickListener {
|
binding.careportal.setOnClickListener {
|
||||||
setFragment(TreatmentsCareportalFragment())
|
setFragment(TreatmentsCareportalFragment())
|
||||||
setBackgroundColorOnSelected(it)
|
setBackgroundColorOnSelected(it)
|
||||||
|
supportActionBar?.title = rh.gs(R.string.careportal)
|
||||||
}
|
}
|
||||||
binding.userentry.setOnClickListener {
|
binding.userentry.setOnClickListener {
|
||||||
setFragment(TreatmentsUserEntryFragment())
|
setFragment(TreatmentsUserEntryFragment())
|
||||||
setBackgroundColorOnSelected(it)
|
setBackgroundColorOnSelected(it)
|
||||||
|
supportActionBar?.title = rh.gs(R.string.user_action)
|
||||||
}
|
}
|
||||||
setFragment(TreatmentsBolusCarbsFragment())
|
setFragment(TreatmentsBolusCarbsFragment())
|
||||||
setBackgroundColorOnSelected(binding.treatments)
|
setBackgroundColorOnSelected(binding.treatments)
|
||||||
|
setSupportActionBar(binding.toolbar)
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
supportActionBar?.title = rh.gs(R.string.carbs_and_bolus)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
android.R.id.home -> {
|
||||||
|
finish()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setFragment(selectedFragment: Fragment) {
|
private fun setFragment(selectedFragment: Fragment) {
|
||||||
|
|
|
@ -3,9 +3,13 @@ package info.nightscout.androidaps.activities.fragments
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.util.Log
|
||||||
import android.view.View
|
import android.util.SparseArray
|
||||||
import android.view.ViewGroup
|
import android.view.*
|
||||||
|
import android.widget.CompoundButton
|
||||||
|
import android.view.ActionMode
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
@ -67,6 +71,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
@Inject lateinit var activePlugin: ActivePlugin
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
|
|
||||||
|
private var _binding: TreatmentsBolusCarbsFragmentBinding? = null
|
||||||
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
class MealLink(
|
class MealLink(
|
||||||
val bolus: Bolus? = null,
|
val bolus: Bolus? = null,
|
||||||
val carbs: Carbs? = null,
|
val carbs: Carbs? = null,
|
||||||
|
@ -74,14 +82,12 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
)
|
)
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
private val millsToThePast = T.days(30).msecs()
|
private val millsToThePast = T.days(30).msecs()
|
||||||
|
|
||||||
private var _binding: TreatmentsBolusCarbsFragmentBinding? = null
|
private var selectedItems: SparseArray<MealLink> = SparseArray()
|
||||||
|
private var showInvalidated = false
|
||||||
// This property is only valid between onCreateView and
|
private var removeActionMode: ActionMode? = null
|
||||||
// onDestroyView.
|
private var toolbar: Toolbar? = null
|
||||||
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 =
|
||||||
TreatmentsBolusCarbsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsBolusCarbsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
@ -89,92 +95,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
@SuppressLint("CheckResult")
|
@SuppressLint("CheckResult")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
toolbar = activity?.findViewById(R.id.toolbar)
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
|
||||||
binding.refreshFromNightscout.setOnClickListener {
|
|
||||||
activity?.let { activity ->
|
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") {
|
|
||||||
uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments)
|
|
||||||
disposable +=
|
|
||||||
Completable.fromAction {
|
|
||||||
repository.deleteAllBolusCalculatorResults()
|
|
||||||
repository.deleteAllBoluses()
|
|
||||||
repository.deleteAllCarbs()
|
|
||||||
}
|
|
||||||
.subscribeOn(aapsSchedulers.io)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribeBy(
|
|
||||||
onError = { aapsLogger.error("Error removing entries", it) },
|
|
||||||
onComplete = {
|
|
||||||
rxBus.send(EventTreatmentChange())
|
|
||||||
rxBus.send(EventNewHistoryData(0, false))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
rxBus.send(EventNSClientRestart())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.deleteFutureTreatments.setOnClickListener {
|
|
||||||
activity?.let { activity ->
|
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.overview_treatment_label), rh.gs(R.string.deletefuturetreatments) + "?", Runnable {
|
|
||||||
uel.log(Action.DELETE_FUTURE_TREATMENTS, Sources.Treatments)
|
|
||||||
repository
|
|
||||||
.getBolusesDataFromTime(dateUtil.now(), false)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe { list ->
|
|
||||||
list.forEach { bolus ->
|
|
||||||
disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id))
|
|
||||||
.subscribe(
|
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") } },
|
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repository
|
|
||||||
.getCarbsDataFromTimeNotExpanded(dateUtil.now(), false)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe { list ->
|
|
||||||
list.forEach { carb ->
|
|
||||||
if (carb.duration == 0L)
|
|
||||||
disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(carb.id))
|
|
||||||
.subscribe(
|
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } },
|
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) }
|
|
||||||
)
|
|
||||||
else {
|
|
||||||
disposable += repository.runTransactionForResult(CutCarbsTransaction(carb.id, dateUtil.now()))
|
|
||||||
.subscribe(
|
|
||||||
{ result ->
|
|
||||||
result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") }
|
|
||||||
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated (cut end) carbs $it") }
|
|
||||||
},
|
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repository
|
|
||||||
.getBolusCalculatorResultsDataFromTime(dateUtil.now(), false)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe { list ->
|
|
||||||
list.forEach { bolusCalc ->
|
|
||||||
disposable += repository.runTransactionForResult(InvalidateBolusCalculatorResultTransaction(bolusCalc.id))
|
|
||||||
.subscribe(
|
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolusCalculatorResult $it") } },
|
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating bolusCalculatorResult", it) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.deleteFutureTreatments.visibility = View.GONE
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_insulin, false) || !sp.getBoolean(R.string.key_ns_receive_carbs, false) || !buildHelper.isEngineeringMode()
|
|
||||||
if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.GONE
|
|
||||||
binding.showInvalidated.setOnCheckedChangeListener { _, _ ->
|
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bolusMealLinksWithInvalid(now: Long) = repository
|
private fun bolusMealLinksWithInvalid(now: Long) = repository
|
||||||
|
@ -204,8 +128,9 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
|
||||||
if (binding.showInvalidated.isChecked)
|
disposable +=
|
||||||
disposable += carbsMealLinksWithInvalid(now)
|
if (showInvalidated)
|
||||||
|
carbsMealLinksWithInvalid(now)
|
||||||
.zipWith(bolusMealLinksWithInvalid(now)) { first, second -> first + second }
|
.zipWith(bolusMealLinksWithInvalid(now)) { first, second -> first + second }
|
||||||
.zipWith(calcResultMealLinksWithInvalid(now)) { first, second -> first + second }
|
.zipWith(calcResultMealLinksWithInvalid(now)) { first, second -> first + second }
|
||||||
.map { ml ->
|
.map { ml ->
|
||||||
|
@ -217,10 +142,9 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe { list ->
|
.subscribe { list ->
|
||||||
binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true)
|
binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true)
|
||||||
binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility()
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
disposable += carbsMealLinks(now)
|
carbsMealLinks(now)
|
||||||
.zipWith(bolusMealLinks(now)) { first, second -> first + second }
|
.zipWith(bolusMealLinks(now)) { first, second -> first + second }
|
||||||
.zipWith(calcResultMealLinks(now)) { first, second -> first + second }
|
.zipWith(calcResultMealLinks(now)) { first, second -> first + second }
|
||||||
.map { ml ->
|
.map { ml ->
|
||||||
|
@ -232,7 +156,6 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe { list ->
|
.subscribe { list ->
|
||||||
binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true)
|
binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true)
|
||||||
binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -267,13 +190,14 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
removeActionMode?.let { it.finish() }
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun timestamp(ml: MealLink): Long = ml.bolusCalculatorResult?.let { it.timestamp } ?: ml.bolus?.let { it.timestamp } ?: ml.carbs?.let { it.timestamp } ?: 0L
|
private fun timestamp(ml: MealLink): Long = ml.bolusCalculatorResult?.timestamp ?: ml.bolus?.timestamp ?: ml.carbs?.timestamp ?: 0L
|
||||||
|
|
||||||
inner class RecyclerViewAdapter internal constructor(var mealLinks: List<MealLink>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() {
|
inner class RecyclerViewAdapter internal constructor(private var mealLinks: List<MealLink>) : RecyclerView.Adapter<RecyclerViewAdapter.MealLinkLoadedViewHolder>() {
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder =
|
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder =
|
||||||
MealLinkLoadedViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_bolus_carbs_item, viewGroup, false))
|
MealLinkLoadedViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_bolus_carbs_item, viewGroup, false))
|
||||||
|
@ -287,13 +211,13 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
holder.binding.date.text = dateUtil.dateString(timestamp(ml))
|
holder.binding.date.text = dateUtil.dateString(timestamp(ml))
|
||||||
|
|
||||||
// Metadata
|
// Metadata
|
||||||
holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || binding.showInvalidated.isChecked)).toVisibility()
|
holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || showInvalidated)).toVisibility()
|
||||||
ml.bolusCalculatorResult?.let { bolusCalculatorResult ->
|
ml.bolusCalculatorResult?.let { bolusCalculatorResult ->
|
||||||
holder.binding.calcTime.text = dateUtil.timeString(bolusCalculatorResult.timestamp)
|
holder.binding.calcTime.text = dateUtil.timeString(bolusCalculatorResult.timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bolus
|
// Bolus
|
||||||
holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus.isValid || binding.showInvalidated.isChecked)).toVisibility()
|
holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus.isValid || showInvalidated)).toVisibility()
|
||||||
ml.bolus?.let { bolus ->
|
ml.bolus?.let { bolus ->
|
||||||
holder.binding.bolusTime.text = dateUtil.timeString(bolus.timestamp)
|
holder.binding.bolusTime.text = dateUtil.timeString(bolus.timestamp)
|
||||||
holder.binding.insulin.text = rh.gs(R.string.formatinsulinunits, bolus.amount)
|
holder.binding.insulin.text = rh.gs(R.string.formatinsulinunits, bolus.amount)
|
||||||
|
@ -321,7 +245,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Carbs
|
// Carbs
|
||||||
holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || binding.showInvalidated.isChecked)).toVisibility()
|
holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || showInvalidated)).toVisibility()
|
||||||
ml.carbs?.let { carbs ->
|
ml.carbs?.let { carbs ->
|
||||||
holder.binding.carbsTime.text = dateUtil.timeString(carbs.timestamp)
|
holder.binding.carbsTime.text = dateUtil.timeString(carbs.timestamp)
|
||||||
holder.binding.carbs.text = rh.gs(R.string.format_carbs, carbs.amount.toInt())
|
holder.binding.carbs.text = rh.gs(R.string.format_carbs, carbs.amount.toInt())
|
||||||
|
@ -330,19 +254,28 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
holder.binding.carbsPump.visibility = (carbs.interfaceIDs.pumpId != null).toVisibility()
|
holder.binding.carbsPump.visibility = (carbs.interfaceIDs.pumpId != null).toVisibility()
|
||||||
holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility()
|
holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility()
|
||||||
}
|
}
|
||||||
|
holder.binding.cbBolusRemove.visibility = (ml.bolus?.isValid == true && removeActionMode != null).toVisibility()
|
||||||
holder.binding.bolusRemove.visibility = (ml.bolus?.isValid == true).toVisibility()
|
holder.binding.cbCarbsRemove.visibility = (ml.carbs?.isValid == true && removeActionMode != null).toVisibility()
|
||||||
holder.binding.carbsRemove.visibility = (ml.carbs?.isValid == true).toVisibility()
|
if (removeActionMode != null) {
|
||||||
holder.binding.bolusRemove.tag = ml
|
val onChange = CompoundButton.OnCheckedChangeListener { _, value ->
|
||||||
holder.binding.carbsRemove.tag = ml
|
if (value) {
|
||||||
|
selectedItems.put(position, ml)
|
||||||
|
} else {
|
||||||
|
selectedItems.remove(position)
|
||||||
|
}
|
||||||
|
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
}
|
||||||
|
holder.binding.cbBolusRemove.setOnCheckedChangeListener(onChange)
|
||||||
|
holder.binding.cbBolusRemove.isChecked = selectedItems.get(position) != null
|
||||||
|
holder.binding.cbCarbsRemove.setOnCheckedChangeListener(onChange)
|
||||||
|
holder.binding.cbCarbsRemove.isChecked = selectedItems.get(position) != null
|
||||||
|
}
|
||||||
holder.binding.calculation.tag = ml
|
holder.binding.calculation.tag = ml
|
||||||
val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L
|
val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount() = mealLinks.size
|
||||||
return mealLinks.size
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class MealLinkLoadedViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) {
|
inner class MealLinkLoadedViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) {
|
||||||
|
|
||||||
|
@ -359,35 +292,199 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.calculation.paintFlags = binding.calculation.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
binding.calculation.paintFlags = binding.calculation.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
||||||
binding.bolusRemove.setOnClickListener { ml ->
|
}
|
||||||
val bolus = (ml.tag as MealLink?)?.bolus ?: return@setOnClickListener
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
inflater.inflate(R.menu.menu_treatments_carbs_bolus, menu)
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_insulin, false) || !sp.getBoolean(R.string.key_ns_receive_carbs, false) || !buildHelper.isEngineeringMode()
|
||||||
|
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
||||||
|
val hasItems = (binding.recyclerview.adapter?.itemCount ?: 0) > 0
|
||||||
|
menu.findItem(R.id.nav_delete_future)?.isVisible = hasItems
|
||||||
|
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.nav_remove_items -> {
|
||||||
|
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_show_invalidated -> {
|
||||||
|
showInvalidated = true
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_hide_invalidated -> {
|
||||||
|
showInvalidated = false
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_delete_future -> {
|
||||||
|
deleteFutureTreatments()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_refresh_ns -> {
|
||||||
|
refreshFromNightscout()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshFromNightscout() {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
val text = rh.gs(R.string.configbuilder_insulin) + ": " +
|
OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") {
|
||||||
rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" +
|
uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments)
|
||||||
|
disposable +=
|
||||||
|
Completable.fromAction {
|
||||||
|
repository.deleteAllBolusCalculatorResults()
|
||||||
|
repository.deleteAllBoluses()
|
||||||
|
repository.deleteAllCarbs()
|
||||||
|
}
|
||||||
|
.subscribeOn(aapsSchedulers.io)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribeBy(
|
||||||
|
onError = { aapsLogger.error("Error removing entries", it) },
|
||||||
|
onComplete = {
|
||||||
|
rxBus.send(EventTreatmentChange())
|
||||||
|
rxBus.send(EventNewHistoryData(0, false))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
rxBus.send(EventNSClientRestart())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteFutureTreatments() {
|
||||||
|
activity?.let { activity ->
|
||||||
|
OKDialog.showConfirmation(activity, rh.gs(R.string.overview_treatment_label), rh.gs(R.string.deletefuturetreatments) + "?", Runnable {
|
||||||
|
uel.log(Action.DELETE_FUTURE_TREATMENTS, Sources.Treatments)
|
||||||
|
disposable += repository
|
||||||
|
.getBolusesDataFromTime(dateUtil.now(), false)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe { list ->
|
||||||
|
list.forEach { bolus ->
|
||||||
|
disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id))
|
||||||
|
.subscribe(
|
||||||
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") } },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disposable += repository
|
||||||
|
.getCarbsDataFromTimeNotExpanded(dateUtil.now(), false)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe { list ->
|
||||||
|
list.forEach { carb ->
|
||||||
|
if (carb.duration == 0L)
|
||||||
|
disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(carb.id))
|
||||||
|
.subscribe(
|
||||||
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) }
|
||||||
|
)
|
||||||
|
else {
|
||||||
|
disposable += repository.runTransactionForResult(CutCarbsTransaction(carb.id, dateUtil.now()))
|
||||||
|
.subscribe(
|
||||||
|
{ result ->
|
||||||
|
result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") }
|
||||||
|
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated (cut end) carbs $it") }
|
||||||
|
},
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disposable += repository
|
||||||
|
.getBolusCalculatorResultsDataFromTime(dateUtil.now(), false)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe { list ->
|
||||||
|
list.forEach { bolusCalc ->
|
||||||
|
disposable += repository.runTransactionForResult(InvalidateBolusCalculatorResultTransaction(bolusCalc.id))
|
||||||
|
.subscribe(
|
||||||
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolusCalculatorResult $it") } },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating bolusCalculatorResult", it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class RemoveActionModeCallback : ActionMode.Callback {
|
||||||
|
|
||||||
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
||||||
|
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
||||||
|
selectedItems.clear()
|
||||||
|
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
||||||
|
|
||||||
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.remove_selected -> {
|
||||||
|
removeSelected()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||||
|
removeActionMode = null
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getConfirmationText(): String {
|
||||||
|
if (selectedItems.size() == 1) {
|
||||||
|
val mealLink = selectedItems.valueAt(0)
|
||||||
|
val bolus = mealLink.bolus
|
||||||
|
if (bolus != null)
|
||||||
|
return rh.gs(R.string.configbuilder_insulin) + ": " + rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" +
|
||||||
rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(bolus.timestamp)
|
rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(bolus.timestamp)
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), text, Runnable {
|
val carbs = mealLink.carbs
|
||||||
|
if (carbs != null)
|
||||||
|
return rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs.amount.toInt()) + "\n" +
|
||||||
|
rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(carbs.timestamp)
|
||||||
|
}
|
||||||
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeSelected() {
|
||||||
|
if (selectedItems.size() > 0)
|
||||||
|
activity?.let { activity ->
|
||||||
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
||||||
|
selectedItems.forEach {key, ml ->
|
||||||
|
ml.bolus?.let { bolus ->
|
||||||
uel.log(
|
uel.log(
|
||||||
Action.BOLUS_REMOVED, Sources.Treatments,
|
Action.BOLUS_REMOVED, Sources.Treatments,
|
||||||
ValueWithUnit.Timestamp(bolus.timestamp),
|
ValueWithUnit.Timestamp(bolus.timestamp),
|
||||||
ValueWithUnit.Insulin(bolus.amount)
|
ValueWithUnit.Insulin(bolus.amount)
|
||||||
//ValueWithUnit.Gram(mealLinkLoaded.carbs.toInt())
|
|
||||||
)
|
)
|
||||||
disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id))
|
disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") } },
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") } },
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it) }
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it) }
|
||||||
)
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
ml.carbs?.let { carb ->
|
||||||
binding.bolusRemove.paintFlags = binding.bolusRemove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
|
||||||
binding.carbsRemove.setOnClickListener { ml ->
|
|
||||||
val carb = (ml.tag as MealLink?)?.carbs ?: return@setOnClickListener
|
|
||||||
activity?.let { activity ->
|
|
||||||
val text = rh.gs(R.string.carbs) + ": " +
|
|
||||||
rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carb.amount.toInt()) + "\n" +
|
|
||||||
rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(carb.timestamp)
|
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), text, Runnable {
|
|
||||||
uel.log(
|
uel.log(
|
||||||
Action.CARBS_REMOVED, Sources.Treatments,
|
Action.CARBS_REMOVED, Sources.Treatments,
|
||||||
ValueWithUnit.Timestamp(carb.timestamp),
|
ValueWithUnit.Timestamp(carb.timestamp),
|
||||||
|
@ -398,11 +495,12 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } },
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } },
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) }
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) }
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeActionMode?.finish()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
binding.carbsRemove.paintFlags = binding.carbsRemove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
removeActionMode?.finish()
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
package info.nightscout.androidaps.activities.fragments
|
package info.nightscout.androidaps.activities.fragments
|
||||||
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.util.SparseArray
|
||||||
import android.view.View
|
import android.view.*
|
||||||
import android.view.ViewGroup
|
import android.view.ActionMode
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
@ -57,24 +58,30 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
|
||||||
|
|
||||||
private val millsToThePast = T.days(30).msecs()
|
|
||||||
|
|
||||||
private var _binding: TreatmentsCareportalFragmentBinding? = null
|
private var _binding: TreatmentsCareportalFragmentBinding? = null
|
||||||
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// This property is only valid between onCreateView and
|
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
private val disposable = CompositeDisposable()
|
||||||
|
private val millsToThePast = T.days(30).msecs()
|
||||||
|
private var selectedItems: SparseArray<TherapyEvent> = SparseArray()
|
||||||
|
private var showInvalidated = false
|
||||||
|
private var toolbar: Toolbar? = null
|
||||||
|
private var removeActionMode: ActionMode? = null
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsCareportalFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsCareportalFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
toolbar = activity?.findViewById(R.id.toolbar)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
binding.refreshFromNightscout.setOnClickListener {
|
}
|
||||||
|
|
||||||
|
private fun refreshFromNightscout() {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.refresheventsfromnightscout) + " ?", Runnable {
|
OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.refresheventsfromnightscout) + " ?", Runnable {
|
||||||
uel.log(Action.CAREPORTAL_NS_REFRESH, Sources.Treatments)
|
uel.log(Action.CAREPORTAL_NS_REFRESH, Sources.Treatments)
|
||||||
|
@ -88,30 +95,24 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.removeAndroidapsStartedEvents.setOnClickListener {
|
|
||||||
|
private fun removeStartedEvents() {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.careportal_removestartedevents), Runnable {
|
OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.careportal_removestartedevents), Runnable {
|
||||||
uel.log(Action.RESTART_EVENTS_REMOVED, Sources.Treatments)
|
uel.log(Action.RESTART_EVENTS_REMOVED, Sources.Treatments)
|
||||||
repository.runTransactionForResult(InvalidateAAPSStartedTherapyEventTransaction(rh.gs(R.string.androidaps_start)))
|
disposable += repository.runTransactionForResult(InvalidateAAPSStartedTherapyEventTransaction(rh.gs(R.string.androidaps_start)))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } },
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } },
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
|
||||||
)
|
)
|
||||||
}, null)
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || !buildHelper.isEngineeringMode()
|
|
||||||
if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.GONE
|
|
||||||
binding.showInvalidated.setOnCheckedChangeListener { _, _ ->
|
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
disposable +=
|
disposable +=
|
||||||
if (binding.showInvalidated.isChecked)
|
if (showInvalidated)
|
||||||
repository
|
repository
|
||||||
.getTherapyEventDataIncludingInvalidFromTime(now - millsToThePast, false)
|
.getTherapyEventDataIncludingInvalidFromTime(now - millsToThePast, false)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
|
@ -148,6 +149,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
removeActionMode?.let { it.finish() }
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -170,42 +172,137 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh)
|
holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh)
|
||||||
holder.binding.note.text = therapyEvent.note
|
holder.binding.note.text = therapyEvent.note
|
||||||
holder.binding.type.text = translator.translate(therapyEvent.type)
|
holder.binding.type.text = translator.translate(therapyEvent.type)
|
||||||
holder.binding.remove.tag = therapyEvent
|
holder.binding.cbRemove.visibility = (therapyEvent.isValid && removeActionMode != null).toVisibility()
|
||||||
|
if (removeActionMode != null) {
|
||||||
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
|
if (value) {
|
||||||
|
selectedItems.put(position, therapyEvent)
|
||||||
|
} else {
|
||||||
|
selectedItems.remove(position)
|
||||||
|
}
|
||||||
|
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
||||||
|
}
|
||||||
val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L
|
val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount() = therapyList.size
|
||||||
return therapyList.size
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class TherapyEventsViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
inner class TherapyEventsViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||||
|
|
||||||
val binding = TreatmentsCareportalItemBinding.bind(view)
|
val binding = TreatmentsCareportalItemBinding.bind(view)
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
}
|
||||||
binding.remove.setOnClickListener { v: View ->
|
|
||||||
val therapyEvent = v.tag as TherapyEvent
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
activity?.let { activity ->
|
inflater.inflate(R.menu.menu_treatments_careportal, menu)
|
||||||
val text = rh.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type) + "\n" +
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
rh.gs(R.string.notes_label) + ": " + (therapyEvent.note
|
}
|
||||||
?: "") + "\n" +
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || !buildHelper.isEngineeringMode()
|
||||||
|
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
||||||
|
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.nav_remove_items -> {
|
||||||
|
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_show_invalidated -> {
|
||||||
|
showInvalidated = true
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_hide_invalidated -> {
|
||||||
|
showInvalidated = false
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_remove_started_events -> {
|
||||||
|
removeStartedEvents()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_refresh_ns -> {
|
||||||
|
refreshFromNightscout()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class RemoveActionModeCallback : ActionMode.Callback {
|
||||||
|
|
||||||
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
||||||
|
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
||||||
|
selectedItems.clear()
|
||||||
|
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
||||||
|
|
||||||
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.remove_selected -> {
|
||||||
|
removeSelected()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||||
|
removeActionMode = null
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getConfirmationText(): String {
|
||||||
|
if (selectedItems.size() == 1) {
|
||||||
|
val therapyEvent = selectedItems.valueAt(0)
|
||||||
|
return rh.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type) + "\n" +
|
||||||
|
rh.gs(R.string.notes_label) + ": " + (therapyEvent.note ?: "") + "\n" +
|
||||||
rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(therapyEvent.timestamp)
|
rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(therapyEvent.timestamp)
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), text, Runnable {
|
}
|
||||||
uel.log(Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note ,
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeSelected() {
|
||||||
|
if (selectedItems.size() > 0)
|
||||||
|
activity?.let { activity ->
|
||||||
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
||||||
|
selectedItems.forEach { _, therapyEvent ->
|
||||||
|
uel.log(
|
||||||
|
Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note,
|
||||||
ValueWithUnit.Timestamp(therapyEvent.timestamp),
|
ValueWithUnit.Timestamp(therapyEvent.timestamp),
|
||||||
ValueWithUnit.TherapyEventType(therapyEvent.type))
|
ValueWithUnit.TherapyEventType(therapyEvent.type)
|
||||||
|
)
|
||||||
disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id))
|
disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } },
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } },
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
|
||||||
)
|
)
|
||||||
}, null)
|
|
||||||
}
|
}
|
||||||
|
removeActionMode?.finish()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
else
|
||||||
}
|
removeActionMode?.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
package info.nightscout.androidaps.activities.fragments
|
package info.nightscout.androidaps.activities.fragments
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.util.SparseArray
|
||||||
import android.view.View
|
import android.view.*
|
||||||
import android.view.ViewGroup
|
import android.view.ActionMode
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
@ -27,16 +27,17 @@ import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.activities.fragments.TreatmentsExtendedBolusesFragment.RecyclerViewAdapter.ExtendedBolusesViewHolder
|
import info.nightscout.androidaps.activities.fragments.TreatmentsExtendedBolusesFragment.RecyclerViewAdapter.ExtendedBolusesViewHolder
|
||||||
|
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxkotlin.plusAssign
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -60,23 +61,27 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
|
||||||
private var _binding: TreatmentsExtendedbolusFragmentBinding? = null
|
private var _binding: TreatmentsExtendedbolusFragmentBinding? = null
|
||||||
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// This property is only valid between onCreateView and
|
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
private var selectedItems: SparseArray<ExtendedBolus> = SparseArray()
|
||||||
savedInstanceState: Bundle?): View =
|
private var showInvalidated = false
|
||||||
|
private var removeActionMode: ActionMode? = null
|
||||||
|
private var toolbar: Toolbar? = null
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsExtendedbolusFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsExtendedbolusFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
toolbar = activity?.findViewById(R.id.toolbar)
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
if (binding.showInvalidated.isChecked)
|
disposable += if (showInvalidated)
|
||||||
repository
|
repository
|
||||||
.getExtendedBolusDataIncludingInvalidFromTime(now - millsToThePast, false)
|
.getExtendedBolusDataIncludingInvalidFromTime(now - millsToThePast, false)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
|
@ -109,6 +114,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
removeActionMode?.let { it.finish() }
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -125,7 +131,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility()
|
holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility()
|
||||||
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility()
|
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility()
|
||||||
holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility()
|
holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility()
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(extendedBolus.timestamp, extendedBolusList[position-1].timestamp)
|
val sameDayPrevious = position > 0 && dateUtil.isSameDay(extendedBolus.timestamp, extendedBolusList[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(extendedBolus.timestamp)
|
holder.binding.date.text = dateUtil.dateString(extendedBolus.timestamp)
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
|
@ -143,41 +149,125 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
holder.binding.iob.text = rh.gs(R.string.formatinsulinunits, iob.iob)
|
holder.binding.iob.text = rh.gs(R.string.formatinsulinunits, iob.iob)
|
||||||
holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate)
|
holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate)
|
||||||
if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor)
|
if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor)
|
||||||
holder.binding.remove.tag = extendedBolus
|
holder.binding.cbRemove.visibility = (extendedBolus.isValid && removeActionMode != null).toVisibility()
|
||||||
|
if (removeActionMode != null) {
|
||||||
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
|
if (value) {
|
||||||
|
selectedItems.put(position, extendedBolus)
|
||||||
|
} else {
|
||||||
|
selectedItems.remove(position)
|
||||||
|
}
|
||||||
|
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
||||||
|
}
|
||||||
val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L
|
val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(extendedBolus.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDay(extendedBolus.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = extendedBolusList.size
|
override fun getItemCount() = extendedBolusList.size
|
||||||
|
|
||||||
inner class ExtendedBolusesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class ExtendedBolusesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
val binding = TreatmentsExtendedbolusItemBinding.bind(itemView)
|
val binding = TreatmentsExtendedbolusItemBinding.bind(itemView)
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
}
|
||||||
binding.remove.setOnClickListener { v: View ->
|
|
||||||
val extendedBolus = v.tag as ExtendedBolus
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
context?.let { context ->
|
inflater.inflate(R.menu.menu_treatments_extended_bolus, menu)
|
||||||
OKDialog.showConfirmation(context, rh.gs(R.string.removerecord),
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
"""
|
}
|
||||||
${rh.gs(R.string.extended_bolus)}
|
|
||||||
${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(extendedBolus.timestamp)}
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
""".trimIndent(), { _: DialogInterface, _: Int ->
|
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
uel.log(Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
|
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.nav_remove_items -> {
|
||||||
|
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_show_invalidated -> {
|
||||||
|
showInvalidated = true
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_hide_invalidated -> {
|
||||||
|
showInvalidated = false
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class RemoveActionModeCallback : ActionMode.Callback {
|
||||||
|
|
||||||
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
||||||
|
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
||||||
|
selectedItems.clear()
|
||||||
|
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
||||||
|
|
||||||
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.remove_selected -> {
|
||||||
|
removeSelected()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||||
|
removeActionMode = null
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getConfirmationText(): String {
|
||||||
|
if (selectedItems.size() == 1) {
|
||||||
|
val bolus = selectedItems.valueAt(0)
|
||||||
|
return rh.gs(R.string.extended_bolus) + "\n" +
|
||||||
|
"${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(bolus.timestamp)}"
|
||||||
|
}
|
||||||
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeSelected() {
|
||||||
|
if (selectedItems.size() > 0)
|
||||||
|
activity?.let { activity ->
|
||||||
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
||||||
|
selectedItems.forEach { _, extendedBolus ->
|
||||||
|
uel.log(
|
||||||
|
Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
|
||||||
ValueWithUnit.Timestamp(extendedBolus.timestamp),
|
ValueWithUnit.Timestamp(extendedBolus.timestamp),
|
||||||
ValueWithUnit.Insulin(extendedBolus.amount),
|
ValueWithUnit.Insulin(extendedBolus.amount),
|
||||||
ValueWithUnit.UnitPerHour(extendedBolus.rate),
|
ValueWithUnit.UnitPerHour(extendedBolus.rate),
|
||||||
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt()))
|
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt())
|
||||||
|
)
|
||||||
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
|
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
|
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
|
||||||
}, null)
|
|
||||||
}
|
}
|
||||||
|
removeActionMode?.finish()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
else
|
||||||
}
|
removeActionMode?.finish()
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,9 +2,11 @@ package info.nightscout.androidaps.activities.fragments
|
||||||
|
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.util.SparseArray
|
||||||
import android.view.View
|
import android.view.*
|
||||||
import android.view.ViewGroup
|
import android.view.ActionMode
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
@ -61,24 +63,29 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
|
||||||
private var _binding: TreatmentsProfileswitchFragmentBinding? = null
|
private var _binding: TreatmentsProfileswitchFragmentBinding? = null
|
||||||
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
private val millsToThePast = T.days(30).msecs()
|
private val millsToThePast = T.days(30).msecs()
|
||||||
|
private var selectedItems: SparseArray<ProfileSealed> = SparseArray()
|
||||||
|
private var showInvalidated = false
|
||||||
|
private var removeActionMode: ActionMode? = null
|
||||||
|
private var toolbar: Toolbar? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
|
||||||
// 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 =
|
||||||
TreatmentsProfileswitchFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsProfileswitchFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
toolbar = activity?.findViewById(R.id.toolbar)
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
}
|
||||||
|
|
||||||
binding.refreshFromNightscout.setOnClickListener {
|
private fun refreshFromNightscout() {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") {
|
OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") {
|
||||||
uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments)
|
uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments)
|
||||||
|
@ -101,11 +108,6 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!sp.getBoolean(R.string.key_ns_receive_profile_switch, false) || !buildHelper.isEngineeringMode()) binding.refreshFromNightscout.visibility = View.GONE
|
|
||||||
binding.showInvalidated.setOnCheckedChangeListener { _, _ ->
|
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun profileSwitchWithInvalid(now: Long) = repository
|
private fun profileSwitchWithInvalid(now: Long) = repository
|
||||||
.getProfileSwitchDataIncludingInvalidFromTime(now - millsToThePast, false)
|
.getProfileSwitchDataIncludingInvalidFromTime(now - millsToThePast, false)
|
||||||
|
@ -126,8 +128,9 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
|
||||||
if (binding.showInvalidated.isChecked)
|
disposable +=
|
||||||
disposable += profileSwitchWithInvalid(now)
|
if (showInvalidated)
|
||||||
|
profileSwitchWithInvalid(now)
|
||||||
.zipWith(effectiveProfileSwitchWithInvalid(now)) { first, second -> first + second }
|
.zipWith(effectiveProfileSwitchWithInvalid(now)) { first, second -> first + second }
|
||||||
.map { ml -> ml.sortedByDescending { it.timestamp } }
|
.map { ml -> ml.sortedByDescending { it.timestamp } }
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
|
@ -135,14 +138,13 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
|
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
disposable += profileSwitches(now)
|
profileSwitches(now)
|
||||||
.zipWith(effectiveProfileSwitches(now)) { first, second -> first + second }
|
.zipWith(effectiveProfileSwitches(now)) { first, second -> first + second }
|
||||||
.map { ml -> ml.sortedByDescending { it.timestamp } }
|
.map { ml -> ml.sortedByDescending { it.timestamp } }
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe { list ->
|
.subscribe { list ->
|
||||||
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
|
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -168,6 +170,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
removeActionMode?.let { it.finish() }
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -186,16 +189,27 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
holder.binding.date.text = dateUtil.dateString(profileSwitch.timestamp)
|
holder.binding.date.text = dateUtil.dateString(profileSwitch.timestamp)
|
||||||
holder.binding.time.text = dateUtil.timeString(profileSwitch.timestamp)
|
holder.binding.time.text = dateUtil.timeString(profileSwitch.timestamp)
|
||||||
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins())
|
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins())
|
||||||
holder.binding.name.text = if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName() else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else ""
|
holder.binding.name.text = if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName()
|
||||||
|
else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else ""
|
||||||
if (profileSwitch.isInProgress(dateUtil)) holder.binding.date.setTextColor(rh.gc(R.color.colorActive))
|
if (profileSwitch.isInProgress(dateUtil)) holder.binding.date.setTextColor(rh.gc(R.color.colorActive))
|
||||||
else holder.binding.date.setTextColor(holder.binding.duration.currentTextColor)
|
else holder.binding.date.setTextColor(holder.binding.duration.currentTextColor)
|
||||||
holder.binding.remove.tag = profileSwitch
|
|
||||||
holder.binding.clone.tag = profileSwitch
|
holder.binding.clone.tag = profileSwitch
|
||||||
holder.binding.name.tag = profileSwitch
|
holder.binding.name.tag = profileSwitch
|
||||||
holder.binding.date.tag = profileSwitch
|
holder.binding.date.tag = profileSwitch
|
||||||
holder.binding.invalid.visibility = profileSwitch.isValid.not().toVisibility()
|
holder.binding.invalid.visibility = profileSwitch.isValid.not().toVisibility()
|
||||||
holder.binding.duration.visibility = (profileSwitch.duration != 0L && profileSwitch.duration != null).toVisibility()
|
holder.binding.duration.visibility = (profileSwitch.duration != 0L && profileSwitch.duration != null).toVisibility()
|
||||||
holder.binding.remove.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
holder.binding.cbRemove.visibility = (removeActionMode != null && profileSwitch is ProfileSealed.PS).toVisibility()
|
||||||
|
if (removeActionMode != null) {
|
||||||
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
|
if (value) {
|
||||||
|
selectedItems.put(position, profileSwitch)
|
||||||
|
} else {
|
||||||
|
selectedItems.remove(position)
|
||||||
|
}
|
||||||
|
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
||||||
|
}
|
||||||
holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
||||||
holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
||||||
holder.binding.root.setBackgroundColor(rh.gc(if (profileSwitch is ProfileSealed.PS) R.color.defaultbackground else R.color.list_delimiter))
|
holder.binding.root.setBackgroundColor(rh.gc(if (profileSwitch is ProfileSealed.PS) R.color.defaultbackground else R.color.list_delimiter))
|
||||||
|
@ -203,47 +217,39 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(profileSwitch.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDay(profileSwitch.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount() = profileSwitchList.size
|
||||||
return profileSwitchList.size
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ProfileSwitchViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class ProfileSwitchViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
val binding = TreatmentsProfileswitchItemBinding.bind(itemView)
|
val binding = TreatmentsProfileswitchItemBinding.bind(itemView)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
binding.remove.setOnClickListener { view ->
|
|
||||||
val profileSwitch = view.tag as ProfileSealed.PS
|
|
||||||
activity?.let { activity ->
|
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord),
|
|
||||||
rh.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName +
|
|
||||||
"\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp), Runnable {
|
|
||||||
uel.log(Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName,
|
|
||||||
ValueWithUnit.Timestamp(profileSwitch.timestamp))
|
|
||||||
disposable += repository.runTransactionForResult(InvalidateProfileSwitchTransaction(profileSwitch.id))
|
|
||||||
.subscribe(
|
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") } },
|
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) }
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.clone.setOnClickListener {
|
binding.clone.setOnClickListener {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
val profileSwitch = (it.tag as ProfileSealed.PS).value
|
val profileSwitch = (it.tag as ProfileSealed.PS).value
|
||||||
val profileSealed = it.tag as ProfileSealed
|
val profileSealed = it.tag as ProfileSealed
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.careportal_profileswitch), rh.gs(R.string.copytolocalprofile) + "\n" + profileSwitch.getCustomizedName() + "\n" + dateUtil.dateAndTimeString(profileSwitch.timestamp), Runnable {
|
OKDialog.showConfirmation(
|
||||||
uel.log(Action.PROFILE_SWITCH_CLONED, Sources.Treatments,
|
activity,
|
||||||
|
rh.gs(R.string.careportal_profileswitch),
|
||||||
|
rh.gs(R.string.copytolocalprofile) + "\n" + profileSwitch.getCustomizedName() + "\n" + dateUtil.dateAndTimeString(profileSwitch.timestamp),
|
||||||
|
Runnable {
|
||||||
|
uel.log(
|
||||||
|
Action.PROFILE_SWITCH_CLONED, Sources.Treatments,
|
||||||
profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"),
|
profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"),
|
||||||
ValueWithUnit.Timestamp(profileSwitch.timestamp),
|
ValueWithUnit.Timestamp(profileSwitch.timestamp),
|
||||||
ValueWithUnit.SimpleString(profileSwitch.profileName))
|
ValueWithUnit.SimpleString(profileSwitch.profileName)
|
||||||
|
)
|
||||||
val nonCustomized = profileSealed.convertToNonCustomizedProfile(dateUtil)
|
val nonCustomized = profileSealed.convertToNonCustomizedProfile(dateUtil)
|
||||||
localProfilePlugin.addProfile(localProfilePlugin.copyFrom(nonCustomized, profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_")))
|
localProfilePlugin.addProfile(
|
||||||
|
localProfilePlugin.copyFrom(
|
||||||
|
nonCustomized,
|
||||||
|
profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_")
|
||||||
|
)
|
||||||
|
)
|
||||||
rxBus.send(EventLocalProfileChanged())
|
rxBus.send(EventLocalProfileChanged())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
|
||||||
binding.clone.paintFlags = binding.clone.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
binding.clone.paintFlags = binding.clone.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
||||||
binding.name.setOnClickListener {
|
binding.name.setOnClickListener {
|
||||||
ProfileViewerDialog().also { pvd ->
|
ProfileViewerDialog().also { pvd ->
|
||||||
|
@ -266,4 +272,104 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
inflater.inflate(R.menu.menu_treatments_profile_switch, menu)
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_profile_switch, false) || !buildHelper.isEngineeringMode()
|
||||||
|
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
||||||
|
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.nav_remove_items -> {
|
||||||
|
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_show_invalidated -> {
|
||||||
|
showInvalidated = true
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_hide_invalidated -> {
|
||||||
|
showInvalidated = false
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_refresh_ns -> {
|
||||||
|
refreshFromNightscout()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class RemoveActionModeCallback : ActionMode.Callback {
|
||||||
|
|
||||||
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
||||||
|
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
||||||
|
selectedItems.clear()
|
||||||
|
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
||||||
|
|
||||||
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.remove_selected -> {
|
||||||
|
removeSelected()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||||
|
removeActionMode = null
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getConfirmationText(): String {
|
||||||
|
if (selectedItems.size() == 1) {
|
||||||
|
val profileSwitch = selectedItems.valueAt(0)
|
||||||
|
return rh.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp)
|
||||||
|
}
|
||||||
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeSelected() {
|
||||||
|
if (selectedItems.size() > 0)
|
||||||
|
activity?.let { activity ->
|
||||||
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
||||||
|
selectedItems.forEach { _, profileSwitch ->
|
||||||
|
uel.log(
|
||||||
|
Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName,
|
||||||
|
ValueWithUnit.Timestamp(profileSwitch.timestamp)
|
||||||
|
)
|
||||||
|
disposable += repository.runTransactionForResult(InvalidateProfileSwitchTransaction(profileSwitch.id))
|
||||||
|
.subscribe(
|
||||||
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") } },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
removeActionMode?.finish()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else
|
||||||
|
removeActionMode?.finish()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
package info.nightscout.androidaps.activities.fragments
|
package info.nightscout.androidaps.activities.fragments
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.util.SparseArray
|
||||||
import android.view.View
|
import android.view.*
|
||||||
import android.view.ViewGroup
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
@ -30,6 +29,8 @@ import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
||||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||||
import info.nightscout.androidaps.activities.fragments.TreatmentsTempTargetFragment.RecyclerViewAdapter.TempTargetsViewHolder
|
import info.nightscout.androidaps.activities.fragments.TreatmentsTempTargetFragment.RecyclerViewAdapter.TempTargetsViewHolder
|
||||||
|
import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged
|
||||||
|
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
@ -40,6 +41,7 @@ import info.nightscout.androidaps.extensions.friendlyDescription
|
||||||
import info.nightscout.androidaps.extensions.highValueToUnitsToString
|
import info.nightscout.androidaps.extensions.highValueToUnitsToString
|
||||||
import info.nightscout.androidaps.extensions.lowValueToUnitsToString
|
import info.nightscout.androidaps.extensions.lowValueToUnitsToString
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
@ -65,48 +67,55 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
|
||||||
|
|
||||||
private val millsToThePast = T.days(30).msecs()
|
|
||||||
|
|
||||||
private var _binding: TreatmentsTemptargetFragmentBinding? = null
|
private var _binding: TreatmentsTemptargetFragmentBinding? = null
|
||||||
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// This property is only valid between onCreateView and
|
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
private val disposable = CompositeDisposable()
|
||||||
|
private val millsToThePast = T.days(30).msecs()
|
||||||
|
private var selectedItems: SparseArray<TemporaryTarget> = SparseArray()
|
||||||
|
private var showInvalidated = false
|
||||||
|
private var toolbar: Toolbar? = null
|
||||||
|
private var removeActionMode: ActionMode? = null
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsTemptargetFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsTemptargetFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
|
toolbar = activity?.findViewById(R.id.toolbar)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
binding.refreshFromNightscout.setOnClickListener {
|
}
|
||||||
context?.let { context ->
|
|
||||||
OKDialog.showConfirmation(context, rh.gs(R.string.refresheventsfromnightscout) + " ?", {
|
private fun refreshFromNightscout() {
|
||||||
uel.log(Action.TT_NS_REFRESH, Sources.Treatments)
|
activity?.let { activity ->
|
||||||
disposable += Completable.fromAction { repository.deleteAllTempTargetEntries() }
|
OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") {
|
||||||
|
uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments)
|
||||||
|
disposable +=
|
||||||
|
Completable.fromAction {
|
||||||
|
repository.deleteAllEffectiveProfileSwitches()
|
||||||
|
repository.deleteAllProfileSwitches()
|
||||||
|
}
|
||||||
.subscribeOn(aapsSchedulers.io)
|
.subscribeOn(aapsSchedulers.io)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribeBy(
|
.subscribeBy(
|
||||||
onError = { aapsLogger.error("Error removing entries", it) },
|
onError = { aapsLogger.error("Error removing entries", it) },
|
||||||
onComplete = { rxBus.send(EventTempTargetChange()) }
|
onComplete = {
|
||||||
|
rxBus.send(EventProfileSwitchChanged())
|
||||||
|
rxBus.send(EventEffectiveProfileSwitchChanged(0L))
|
||||||
|
rxBus.send(EventNewHistoryData(0, false))
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
rxBus.send(EventNSClientRestart())
|
rxBus.send(EventNSClientRestart())
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_temp_target, false) || !buildHelper.isEngineeringMode()
|
|
||||||
if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.INVISIBLE
|
|
||||||
binding.showInvalidated.setOnCheckedChangeListener { _, _ ->
|
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
if (binding.showInvalidated.isChecked)
|
disposable +=
|
||||||
|
if (showInvalidated)
|
||||||
repository
|
repository
|
||||||
.getTemporaryTargetDataIncludingInvalidFromTime(now - millsToThePast, false)
|
.getTemporaryTargetDataIncludingInvalidFromTime(now - millsToThePast, false)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
|
@ -145,6 +154,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
removeActionMode?.let { it.finish() }
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -163,8 +173,19 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
val tempTarget = tempTargetList[position]
|
val tempTarget = tempTargetList[position]
|
||||||
holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
|
holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
|
||||||
holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
|
holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
|
||||||
holder.binding.remove.visibility = tempTarget.isValid.toVisibility()
|
holder.binding.cbRemove.visibility = (tempTarget.isValid && removeActionMode != null).toVisibility()
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position-1].timestamp)
|
if (removeActionMode != null) {
|
||||||
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
|
if (value) {
|
||||||
|
selectedItems.put(position, tempTarget)
|
||||||
|
} else {
|
||||||
|
selectedItems.remove(position)
|
||||||
|
}
|
||||||
|
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
||||||
|
}
|
||||||
|
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(tempTarget.timestamp)
|
holder.binding.date.text = dateUtil.dateString(tempTarget.timestamp)
|
||||||
holder.binding.time.text = dateUtil.timeRangeString(tempTarget.timestamp, tempTarget.end)
|
holder.binding.time.text = dateUtil.timeRangeString(tempTarget.timestamp, tempTarget.end)
|
||||||
|
@ -177,43 +198,123 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
tempTarget.id == currentlyActiveTarget?.id -> rh.gc(R.color.colorActive)
|
tempTarget.id == currentlyActiveTarget?.id -> rh.gc(R.color.colorActive)
|
||||||
tempTarget.timestamp > dateUtil.now() -> rh.gc(R.color.colorScheduled)
|
tempTarget.timestamp > dateUtil.now() -> rh.gc(R.color.colorScheduled)
|
||||||
else -> holder.binding.reasonColon.currentTextColor
|
else -> holder.binding.reasonColon.currentTextColor
|
||||||
})
|
}
|
||||||
holder.binding.remove.tag = tempTarget
|
)
|
||||||
val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L
|
val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempTarget.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempTarget.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = tempTargetList.size
|
override fun getItemCount() = tempTargetList.size
|
||||||
|
|
||||||
inner class TempTargetsViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
inner class TempTargetsViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||||
|
|
||||||
val binding = TreatmentsTemptargetItemBinding.bind(view)
|
val binding = TreatmentsTemptargetItemBinding.bind(view)
|
||||||
|
|
||||||
init {
|
}
|
||||||
binding.remove.setOnClickListener { v: View ->
|
}
|
||||||
val tempTarget = v.tag as TemporaryTarget
|
|
||||||
context?.let { context ->
|
private fun removeSelected() {
|
||||||
OKDialog.showConfirmation(context, rh.gs(R.string.removerecord),
|
if (selectedItems.size() > 0)
|
||||||
"""
|
activity?.let { activity ->
|
||||||
${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)}
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
||||||
${dateUtil.dateAndTimeString(tempTarget.timestamp)}
|
selectedItems.forEach { _, tempTarget ->
|
||||||
""".trimIndent(),
|
uel.log(
|
||||||
{ _: DialogInterface?, _: Int ->
|
Action.TT_REMOVED, Sources.Treatments,
|
||||||
uel.log(Action.TT_REMOVED, Sources.Treatments,
|
|
||||||
ValueWithUnit.Timestamp(tempTarget.timestamp),
|
ValueWithUnit.Timestamp(tempTarget.timestamp),
|
||||||
ValueWithUnit.TherapyEventTTReason(tempTarget.reason),
|
ValueWithUnit.TherapyEventTTReason(tempTarget.reason),
|
||||||
ValueWithUnit.Mgdl(tempTarget.lowTarget),
|
ValueWithUnit.Mgdl(tempTarget.lowTarget),
|
||||||
ValueWithUnit.Mgdl(tempTarget.highTarget).takeIf { tempTarget.lowTarget != tempTarget.highTarget },
|
ValueWithUnit.Mgdl(tempTarget.highTarget).takeIf { tempTarget.lowTarget != tempTarget.highTarget },
|
||||||
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tempTarget.duration).toInt()))
|
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tempTarget.duration).toInt())
|
||||||
|
)
|
||||||
disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id))
|
disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ aapsLogger.debug(LTag.DATABASE, "Removed temp target $tempTarget") },
|
{ aapsLogger.debug(LTag.DATABASE, "Removed temp target $tempTarget") },
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it) })
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it) })
|
||||||
}, null)
|
}
|
||||||
|
removeActionMode?.finish()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else
|
||||||
|
removeActionMode?.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
inflater.inflate(R.menu.menu_treatments_temp_target, menu)
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_temp_target, false) || !buildHelper.isEngineeringMode()
|
||||||
|
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
||||||
|
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.nav_remove_items -> {
|
||||||
|
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_show_invalidated -> {
|
||||||
|
showInvalidated = true
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_hide_invalidated -> {
|
||||||
|
showInvalidated = false
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_refresh_ns -> {
|
||||||
|
refreshFromNightscout()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class RemoveActionModeCallback : ActionMode.Callback {
|
||||||
|
|
||||||
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
||||||
|
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
||||||
|
selectedItems.clear()
|
||||||
|
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
||||||
|
|
||||||
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.remove_selected -> {
|
||||||
|
removeSelected()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
|
||||||
|
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||||
|
removeActionMode = null
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getConfirmationText(): String {
|
||||||
|
if (selectedItems.size() == 1) {
|
||||||
|
val tempTarget = selectedItems.valueAt(0)
|
||||||
|
return "${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)}\n" +
|
||||||
|
dateUtil.dateAndTimeString(tempTarget.timestamp)
|
||||||
}
|
}
|
||||||
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package info.nightscout.androidaps.activities.fragments
|
package info.nightscout.androidaps.activities.fragments
|
||||||
|
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.util.Log
|
||||||
import android.view.View
|
import android.util.SparseArray
|
||||||
import android.view.ViewGroup
|
import android.view.*
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
@ -36,6 +36,7 @@ import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.activities.fragments.TreatmentsTemporaryBasalsFragment.RecyclerViewAdapter.TempBasalsViewHolder
|
import info.nightscout.androidaps.activities.fragments.TreatmentsTemporaryBasalsFragment.RecyclerViewAdapter.TempBasalsViewHolder
|
||||||
|
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
@ -64,18 +65,22 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
|
||||||
private var _binding: TreatmentsTempbasalsFragmentBinding? = null
|
private var _binding: TreatmentsTempbasalsFragmentBinding? = null
|
||||||
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val millsToThePast = T.days(30).msecs()
|
private val millsToThePast = T.days(30).msecs()
|
||||||
|
private var selectedItems: SparseArray<TemporaryBasal> = SparseArray()
|
||||||
// This property is only valid between onCreateView and
|
private var showInvalidated = false
|
||||||
// onDestroyView.
|
private var toolbar: Toolbar? = null
|
||||||
private val binding get() = _binding!!
|
private var removeActionMode: ActionMode? = null
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsTempbasalsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsTempbasalsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
toolbar = activity?.findViewById(R.id.toolbar)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
}
|
}
|
||||||
|
@ -98,7 +103,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
disposable +=
|
disposable +=
|
||||||
if (activePlugin.activePump.isFakingTempsByExtendedBoluses) {
|
if (activePlugin.activePump.isFakingTempsByExtendedBoluses) {
|
||||||
if (binding.showInvalidated.isChecked)
|
if (showInvalidated)
|
||||||
tempBasalsWithInvalid(now)
|
tempBasalsWithInvalid(now)
|
||||||
.zipWith(extendedBolusesWithInvalid(now)) { first, second -> first + second }
|
.zipWith(extendedBolusesWithInvalid(now)) { first, second -> first + second }
|
||||||
.map { list -> list.filterNotNull() }
|
.map { list -> list.filterNotNull() }
|
||||||
|
@ -113,7 +118,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
|
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
|
||||||
} else {
|
} else {
|
||||||
if (binding.showInvalidated.isChecked)
|
if (showInvalidated)
|
||||||
tempBasalsWithInvalid(now)
|
tempBasalsWithInvalid(now)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
|
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
|
||||||
|
@ -150,6 +155,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
removeActionMode?.let { it.finish() }
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -164,7 +170,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
holder.binding.ns.visibility = (tempBasal.interfaceIDs.nightscoutId != null).toVisibility()
|
holder.binding.ns.visibility = (tempBasal.interfaceIDs.nightscoutId != null).toVisibility()
|
||||||
holder.binding.invalid.visibility = tempBasal.isValid.not().toVisibility()
|
holder.binding.invalid.visibility = tempBasal.isValid.not().toVisibility()
|
||||||
holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility()
|
holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility()
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position-1].timestamp)
|
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(tempBasal.timestamp)
|
holder.binding.date.text = dateUtil.dateString(tempBasal.timestamp)
|
||||||
if (tempBasal.isInProgress) {
|
if (tempBasal.isInProgress) {
|
||||||
|
@ -187,62 +193,147 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
holder.binding.emulatedSuspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.EMULATED_PUMP_SUSPEND).toVisibility()
|
holder.binding.emulatedSuspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.EMULATED_PUMP_SUSPEND).toVisibility()
|
||||||
holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility()
|
holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility()
|
||||||
if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor)
|
if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor)
|
||||||
holder.binding.remove.tag = tempBasal
|
holder.binding.cbRemove.visibility = (tempBasal.isValid && removeActionMode != null).toVisibility()
|
||||||
|
if (removeActionMode != null) {
|
||||||
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
|
if (value) {
|
||||||
|
selectedItems.put(position, tempBasal)
|
||||||
|
} else {
|
||||||
|
selectedItems.remove(position)
|
||||||
|
}
|
||||||
|
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
||||||
|
}
|
||||||
val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L
|
val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempBasal.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempBasal.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = tempBasalList.size
|
override fun getItemCount() = tempBasalList.size
|
||||||
|
|
||||||
inner class TempBasalsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class TempBasalsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
val binding = TreatmentsTempbasalsItemBinding.bind(itemView)
|
val binding = TreatmentsTempbasalsItemBinding.bind(itemView)
|
||||||
|
|
||||||
init {
|
}
|
||||||
binding.remove.setOnClickListener { v: View ->
|
|
||||||
val tempBasal = v.tag as TemporaryBasal
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
inflater.inflate(R.menu.menu_treatments_temp_basal, menu)
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.nav_remove_items -> {
|
||||||
|
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_show_invalidated -> {
|
||||||
|
showInvalidated = true
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_hide_invalidated -> {
|
||||||
|
showInvalidated = false
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class RemoveActionModeCallback : ActionMode.Callback {
|
||||||
|
|
||||||
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
||||||
|
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
||||||
|
selectedItems.clear()
|
||||||
|
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
||||||
|
|
||||||
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.remove_selected -> {
|
||||||
|
removeSelected()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||||
|
removeActionMode = null
|
||||||
|
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getConfirmationText(): String {
|
||||||
|
if (selectedItems.size() == 1) {
|
||||||
|
val tempBasal = selectedItems.valueAt(0)
|
||||||
|
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
|
||||||
|
val profile = profileFunction.getProfile(dateUtil.now())
|
||||||
|
if (profile != null)
|
||||||
|
return "${if (isFakeExtended) rh.gs(R.string.extended_bolus) else rh.gs(R.string.tempbasal_label)}: ${tempBasal.toStringFull(profile, dateUtil)}\n" +
|
||||||
|
"${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(tempBasal.timestamp)}"
|
||||||
|
}
|
||||||
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeSelected() {
|
||||||
|
if (selectedItems.size() > 0)
|
||||||
|
activity?.let { activity ->
|
||||||
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
||||||
|
selectedItems.forEach {_, tempBasal ->
|
||||||
var extendedBolus: ExtendedBolus? = null
|
var extendedBolus: ExtendedBolus? = null
|
||||||
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
|
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
|
||||||
if (isFakeExtended) {
|
if (isFakeExtended) {
|
||||||
val eb = repository.getExtendedBolusActiveAt(tempBasal.timestamp).blockingGet()
|
val eb = repository.getExtendedBolusActiveAt(tempBasal.timestamp).blockingGet()
|
||||||
extendedBolus = if (eb is ValueWrapper.Existing) eb.value else null
|
extendedBolus = if (eb is ValueWrapper.Existing) eb.value else null
|
||||||
}
|
}
|
||||||
val profile = profileFunction.getProfile(dateUtil.now())
|
|
||||||
?: return@setOnClickListener
|
|
||||||
context?.let {
|
|
||||||
OKDialog.showConfirmation(it, rh.gs(R.string.removerecord),
|
|
||||||
"""
|
|
||||||
${if (isFakeExtended) rh.gs(R.string.extended_bolus) else rh.gs(R.string.tempbasal_label)}: ${tempBasal.toStringFull(profile, dateUtil)}
|
|
||||||
${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(tempBasal.timestamp)}
|
|
||||||
""".trimIndent(),
|
|
||||||
{ _: DialogInterface?, _: Int ->
|
|
||||||
if (isFakeExtended && extendedBolus != null) {
|
if (isFakeExtended && extendedBolus != null) {
|
||||||
uel.log(Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
|
uel.log(
|
||||||
|
Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
|
||||||
ValueWithUnit.Timestamp(extendedBolus.timestamp),
|
ValueWithUnit.Timestamp(extendedBolus.timestamp),
|
||||||
ValueWithUnit.Insulin(extendedBolus.amount),
|
ValueWithUnit.Insulin(extendedBolus.amount),
|
||||||
ValueWithUnit.UnitPerHour(extendedBolus.rate),
|
ValueWithUnit.UnitPerHour(extendedBolus.rate),
|
||||||
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt()))
|
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt())
|
||||||
|
)
|
||||||
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
|
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
|
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
|
||||||
} else if (!isFakeExtended) {
|
} else if (!isFakeExtended) {
|
||||||
uel.log(Action.TEMP_BASAL_REMOVED, Sources.Treatments,
|
uel.log(
|
||||||
|
Action.TEMP_BASAL_REMOVED, Sources.Treatments,
|
||||||
ValueWithUnit.Timestamp(tempBasal.timestamp),
|
ValueWithUnit.Timestamp(tempBasal.timestamp),
|
||||||
if (tempBasal.isAbsolute) ValueWithUnit.UnitPerHour(tempBasal.rate) else ValueWithUnit.Percent(tempBasal.rate.toInt()),
|
if (tempBasal.isAbsolute) ValueWithUnit.UnitPerHour(tempBasal.rate) else ValueWithUnit.Percent(tempBasal.rate.toInt()),
|
||||||
ValueWithUnit.Minute(T.msecs(tempBasal.duration).mins().toInt()))
|
ValueWithUnit.Minute(T.msecs(tempBasal.duration).mins().toInt())
|
||||||
|
)
|
||||||
disposable += repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(tempBasal.id))
|
disposable += repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(tempBasal.id))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ aapsLogger.debug(LTag.DATABASE, "Removed temporary basal $tempBasal") },
|
{ aapsLogger.debug(LTag.DATABASE, "Removed temporary basal $tempBasal") },
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) })
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) })
|
||||||
}
|
}
|
||||||
}, null)
|
|
||||||
}
|
}
|
||||||
|
removeActionMode?.finish()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
else
|
||||||
}
|
removeActionMode?.finish()
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
package info.nightscout.androidaps.activities.fragments
|
package info.nightscout.androidaps.activities.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.*
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
@ -30,6 +28,7 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -51,11 +50,10 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
|
|
||||||
private val millsToThePastFiltered = T.days(30).msecs()
|
private val millsToThePastFiltered = T.days(30).msecs()
|
||||||
private val millsToThePastUnFiltered = T.days(3).msecs()
|
private val millsToThePastUnFiltered = T.days(3).msecs()
|
||||||
|
private var showLoop = false
|
||||||
private var _binding: TreatmentsUserEntryFragmentBinding? = null
|
private var _binding: TreatmentsUserEntryFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
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 =
|
||||||
|
@ -63,9 +61,12 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
binding.ueExportToXml.setOnClickListener {
|
}
|
||||||
|
|
||||||
|
fun exportUserEnteries() {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.ue_export_to_csv) + "?") {
|
OKDialog.showConfirmation(activity, rh.gs(R.string.ue_export_to_csv) + "?") {
|
||||||
uel.log(Action.EXPORT_CSV, Sources.Treatments)
|
uel.log(Action.EXPORT_CSV, Sources.Treatments)
|
||||||
|
@ -73,25 +74,20 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.showLoop.setOnCheckedChangeListener { _, _ ->
|
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
if (binding.showLoop.isChecked)
|
disposable +=
|
||||||
disposable.add( repository
|
if (showLoop)
|
||||||
|
repository
|
||||||
.getUserEntryDataFromTime(now - millsToThePastUnFiltered)
|
.getUserEntryDataFromTime(now - millsToThePastUnFiltered)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) }
|
.subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) }
|
||||||
)
|
|
||||||
else
|
else
|
||||||
disposable.add( repository
|
repository
|
||||||
.getUserEntryFilteredDataFromTime(now - millsToThePastFiltered)
|
.getUserEntryFilteredDataFromTime(now - millsToThePastFiltered)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) }
|
.subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) }
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -99,15 +95,15 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
swapAdapter()
|
swapAdapter()
|
||||||
|
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventPreferenceChange::class.java)
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException))
|
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventTreatmentUpdateGui::class.java)
|
.toObservable(EventTreatmentUpdateGui::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
.debounce(1L, TimeUnit.SECONDS)
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException))
|
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -132,7 +128,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) {
|
||||||
val current = entries[position]
|
val current = entries[position]
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(current.timestamp, entries[position-1].timestamp)
|
val sameDayPrevious = position > 0 && dateUtil.isSameDay(current.timestamp, entries[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(current.timestamp)
|
holder.binding.date.text = dateUtil.dateString(current.timestamp)
|
||||||
holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp)
|
holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp)
|
||||||
|
@ -152,7 +148,40 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
val binding = TreatmentsUserEntryItemBinding.bind(itemView)
|
val binding = TreatmentsUserEntryItemBinding.bind(itemView)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = entries.size
|
override fun getItemCount() = entries.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
inflater.inflate(R.menu.menu_treatments_user_entry, menu)
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
menu.findItem(R.id.nav_hide_loop)?.isVisible = showLoop
|
||||||
|
menu.findItem(R.id.nav_show_loop)?.isVisible = !showLoop
|
||||||
|
|
||||||
|
return super.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.nav_show_loop -> {
|
||||||
|
showLoop = true
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_hide_loop -> {
|
||||||
|
showLoop = false
|
||||||
|
rxBus.send(EventTreatmentUpdateGui())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.nav_export -> {
|
||||||
|
exportUserEnteries()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,54 +1,10 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsBolusCarbsFragment">
|
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsBolusCarbsFragment">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.SingleClickButton
|
|
||||||
android:id="@+id/refresh_from_nightscout"
|
|
||||||
style="?android:attr/buttonStyle"
|
|
||||||
android:layout_width="0px"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawableStart="@drawable/ic_refresh"
|
|
||||||
android:text="@string/nav_refreshtreatments" />
|
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.SingleClickButton
|
|
||||||
android:id="@+id/delete_future_treatments"
|
|
||||||
style="?android:attr/buttonStyle"
|
|
||||||
android:layout_width="0px"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawableStart="@drawable/ic_remove"
|
|
||||||
android:text="@string/deletefuturetreatments" />
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/show_invalidated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end|center_vertical"
|
|
||||||
android:checked="false"
|
|
||||||
android:paddingEnd="5dp"
|
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:contentDescription="@string/show_removed"
|
|
||||||
app:srcCompat="@drawable/ic_visibility" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerview"
|
android:id="@+id/recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -161,14 +161,12 @@
|
||||||
android:text="@string/invalid"
|
android:text="@string/invalid"
|
||||||
android:textColor="@android:color/holo_red_light" />
|
android:textColor="@android:color/holo_red_light" />
|
||||||
|
|
||||||
<TextView
|
<CheckBox
|
||||||
android:id="@+id/bolus_remove"
|
android:id="@+id/cb_bolus_remove"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:contentDescription="@string/select_for_removal"
|
||||||
android:text="@string/remove_button"
|
android:visibility="gone" />
|
||||||
android:textAlignment="viewEnd"
|
|
||||||
android:textColor="@android:color/holo_orange_light" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -257,13 +255,21 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/carbs_remove"
|
android:id="@+id/carbs_remove"
|
||||||
|
android:visibility="gone"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
|
|
||||||
android:text="@string/remove_button"
|
android:text="@string/remove_button"
|
||||||
android:textAlignment="viewEnd"
|
android:textAlignment="viewEnd"
|
||||||
android:textColor="@android:color/holo_orange_light" />
|
android:textColor="@android:color/holo_orange_light" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/cb_carbs_remove"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -1,54 +1,10 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsCareportalFragment">
|
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsCareportalFragment">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.SingleClickButton
|
|
||||||
android:id="@+id/refresh_from_nightscout"
|
|
||||||
style="?android:attr/buttonStyle"
|
|
||||||
android:layout_width="0px"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawableStart="@drawable/ic_refresh"
|
|
||||||
android:text="@string/nav_refreshtreatments" />
|
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.SingleClickButton
|
|
||||||
android:id="@+id/remove_androidaps_started_events"
|
|
||||||
style="?android:attr/buttonStyle"
|
|
||||||
android:layout_width="0px"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawableStart="@drawable/ic_remove"
|
|
||||||
android:text="@string/careportal_removestartedevents" />
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/show_invalidated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end|center_vertical"
|
|
||||||
android:checked="false"
|
|
||||||
android:paddingEnd="5dp"
|
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:contentDescription="@string/show_removed"
|
|
||||||
app:srcCompat="@drawable/ic_visibility" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerview"
|
android:id="@+id/recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -112,14 +112,12 @@
|
||||||
android:text="Activity"
|
android:text="Activity"
|
||||||
tools:ignore="HardcodedText,RtlSymmetry" />
|
tools:ignore="HardcodedText,RtlSymmetry" />
|
||||||
|
|
||||||
<TextView
|
<CheckBox
|
||||||
android:id="@+id/remove"
|
android:id="@+id/cb_remove"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="10dp"
|
android:contentDescription="@string/select_for_removal"
|
||||||
android:text="@string/remove_button"
|
android:visibility="gone" />
|
||||||
android:textAlignment="viewEnd"
|
|
||||||
android:textColor="@android:color/holo_orange_light" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
@ -1,34 +1,10 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsExtendedBolusesFragment">
|
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsExtendedBolusesFragment">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/show_invalidated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end|center_vertical"
|
|
||||||
android:checked="false"
|
|
||||||
android:paddingEnd="5dp"
|
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
app:srcCompat="@drawable/ic_visibility"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:contentDescription="@string/show_removed" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerview"
|
android:id="@+id/recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -153,14 +153,12 @@
|
||||||
android:text="@string/invalid"
|
android:text="@string/invalid"
|
||||||
android:textColor="@android:color/holo_red_light" />
|
android:textColor="@android:color/holo_red_light" />
|
||||||
|
|
||||||
<TextView
|
<CheckBox
|
||||||
android:id="@+id/remove"
|
android:id="@+id/cb_remove"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:contentDescription="@string/select_for_removal"
|
||||||
android:text="@string/remove_button"
|
android:visibility="gone" />
|
||||||
android:textAlignment="viewEnd"
|
|
||||||
android:textColor="@android:color/holo_orange_light" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -6,6 +6,13 @@
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="info.nightscout.androidaps.activities.TreatmentsActivity">
|
tools:context="info.nightscout.androidaps.activities.TreatmentsActivity">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:minHeight="?attr/actionBarSize"
|
||||||
|
app:titleTextColor="@android:color/white" />
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -1,44 +1,10 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsProfileSwitchFragment">
|
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsProfileSwitchFragment">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.SingleClickButton
|
|
||||||
android:id="@+id/refresh_from_nightscout"
|
|
||||||
style="?android:attr/buttonStyle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawableStart="@drawable/ic_refresh"
|
|
||||||
android:text="@string/refresheventsfromnightscout" />
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/show_invalidated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end|center_vertical"
|
|
||||||
android:checked="false"
|
|
||||||
android:paddingEnd="5dp"
|
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:contentDescription="@string/show_removed"
|
|
||||||
app:srcCompat="@drawable/ic_visibility" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerview"
|
android:id="@+id/recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -124,15 +124,12 @@
|
||||||
android:textAlignment="viewEnd"
|
android:textAlignment="viewEnd"
|
||||||
android:textColor="@android:color/holo_blue_light" />
|
android:textColor="@android:color/holo_blue_light" />
|
||||||
|
|
||||||
<TextView
|
<CheckBox
|
||||||
android:id="@+id/remove"
|
android:id="@+id/cb_remove"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="10dp"
|
android:contentDescription="@string/select_for_removal"
|
||||||
android:paddingEnd="5dp"
|
android:visibility="gone" />
|
||||||
android:text="@string/remove_button"
|
|
||||||
android:textAlignment="viewEnd"
|
|
||||||
android:textColor="@android:color/holo_orange_light" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,10 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsTemporaryBasalsFragment">
|
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsTemporaryBasalsFragment">
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/show_invalidated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end|center_vertical"
|
|
||||||
android:checked="false"
|
|
||||||
android:paddingEnd="5dp"
|
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:contentDescription="@string/show_removed"
|
|
||||||
app:srcCompat="@drawable/ic_visibility" />
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerview"
|
android:id="@+id/recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -172,15 +172,12 @@
|
||||||
android:text="@string/invalid"
|
android:text="@string/invalid"
|
||||||
android:textColor="@android:color/holo_red_light" />
|
android:textColor="@android:color/holo_red_light" />
|
||||||
|
|
||||||
<TextView
|
<CheckBox
|
||||||
android:id="@+id/remove"
|
android:id="@+id/cb_remove"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:contentDescription="@string/select_for_removal"
|
||||||
android:visibility="gone"
|
android:visibility="gone" />
|
||||||
android:text="@string/remove_button"
|
|
||||||
android:textAlignment="viewEnd"
|
|
||||||
android:textColor="@android:color/holo_orange_light" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -1,45 +1,10 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsTempTargetFragment">
|
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsTempTargetFragment">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.SingleClickButton
|
|
||||||
android:id="@+id/refresh_from_nightscout"
|
|
||||||
style="?android:attr/buttonStyle"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawableStart="@drawable/ic_refresh"
|
|
||||||
android:text="@string/refresheventsfromnightscout"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/show_invalidated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end|center_vertical"
|
|
||||||
android:checked="false"
|
|
||||||
android:paddingEnd="5dp"
|
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:contentDescription="@string/show_removed"
|
|
||||||
app:srcCompat="@drawable/ic_visibility" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerview"
|
android:id="@+id/recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -147,14 +147,12 @@
|
||||||
android:text="@string/invalid"
|
android:text="@string/invalid"
|
||||||
android:textColor="@android:color/holo_red_light" />
|
android:textColor="@android:color/holo_red_light" />
|
||||||
|
|
||||||
<TextView
|
<CheckBox
|
||||||
android:id="@+id/remove"
|
android:id="@+id/cb_remove"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="10dp"
|
android:contentDescription="@string/select_for_removal"
|
||||||
android:text="@string/remove_button"
|
android:visibility="gone" />
|
||||||
android:textAlignment="viewEnd"
|
|
||||||
android:textColor="@android:color/holo_orange_light" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
@ -6,40 +6,6 @@
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsUserEntryFragment">
|
tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsUserEntryFragment">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<info.nightscout.androidaps.utils.ui.SingleClickButton
|
|
||||||
android:id="@+id/ue_export_to_xml"
|
|
||||||
style="?android:attr/buttonStyle"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawableStart="@drawable/ic_header_export"
|
|
||||||
android:text="@string/ue_export_to_csv" />
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/show_loop"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end|center_vertical"
|
|
||||||
android:checked="false"
|
|
||||||
android:paddingEnd="5dp"
|
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:contentDescription="@string/show_calculation"
|
|
||||||
app:srcCompat="@drawable/ic_loop_closed_white" />
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerview"
|
android:id="@+id/recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
11
app/src/main/res/menu/menu_delete_selection.xml
Normal file
11
app/src/main/res/menu/menu_delete_selection.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/remove_selected"
|
||||||
|
android:icon="@drawable/ic_trash"
|
||||||
|
android:iconTint="@color/white"
|
||||||
|
android:title="@string/remove_selected_items"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
|
</menu>
|
25
app/src/main/res/menu/menu_treatments_carbs_bolus.xml
Normal file
25
app/src/main/res/menu/menu_treatments_carbs_bolus.xml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_remove_items"
|
||||||
|
android:title="@string/remove_items"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_show_invalidated"
|
||||||
|
android:title="@string/show_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_hide_invalidated"
|
||||||
|
android:title="@string/hide_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_delete_future"
|
||||||
|
android:title="@string/delete_future_treatments"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_refresh_ns"
|
||||||
|
android:title="@string/refresh_from_nightscout"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
</menu>
|
25
app/src/main/res/menu/menu_treatments_careportal.xml
Normal file
25
app/src/main/res/menu/menu_treatments_careportal.xml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_remove_items"
|
||||||
|
android:title="@string/remove_items"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_show_invalidated"
|
||||||
|
android:title="@string/show_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_hide_invalidated"
|
||||||
|
android:title="@string/hide_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_refresh_ns"
|
||||||
|
android:title="@string/refresh_from_nightscout"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_remove_started_events"
|
||||||
|
android:title="@string/careportal_removestartedevents"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
</menu>
|
17
app/src/main/res/menu/menu_treatments_extended_bolus.xml
Normal file
17
app/src/main/res/menu/menu_treatments_extended_bolus.xml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_remove_items"
|
||||||
|
android:title="@string/remove_items"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_show_invalidated"
|
||||||
|
android:title="@string/show_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_hide_invalidated"
|
||||||
|
android:title="@string/hide_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
</menu>
|
17
app/src/main/res/menu/menu_treatments_profile_switch.xml
Normal file
17
app/src/main/res/menu/menu_treatments_profile_switch.xml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_remove_items"
|
||||||
|
android:title="@string/remove_items"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_show_invalidated"
|
||||||
|
android:title="@string/show_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_hide_invalidated"
|
||||||
|
android:title="@string/hide_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
</menu>
|
17
app/src/main/res/menu/menu_treatments_temp_basal.xml
Normal file
17
app/src/main/res/menu/menu_treatments_temp_basal.xml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_remove_items"
|
||||||
|
android:title="@string/remove_items"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_show_invalidated"
|
||||||
|
android:title="@string/show_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_hide_invalidated"
|
||||||
|
android:title="@string/hide_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
</menu>
|
21
app/src/main/res/menu/menu_treatments_temp_target.xml
Normal file
21
app/src/main/res/menu/menu_treatments_temp_target.xml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_remove_items"
|
||||||
|
android:title="@string/remove_items"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_show_invalidated"
|
||||||
|
android:title="@string/show_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_hide_invalidated"
|
||||||
|
android:title="@string/hide_invalidated"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_refresh_ns"
|
||||||
|
android:title="@string/refresh_from_nightscout"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
</menu>
|
17
app/src/main/res/menu/menu_treatments_user_entry.xml
Normal file
17
app/src/main/res/menu/menu_treatments_user_entry.xml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_show_loop"
|
||||||
|
android:title="@string/show_loop"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_hide_loop"
|
||||||
|
android:title="@string/hide_loop"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_export"
|
||||||
|
android:title="@string/ue_export_to_csv"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
</menu>
|
|
@ -827,6 +827,9 @@
|
||||||
<string name="sensitivity_raises_target_summary">When sensitivity is detected, raise the target glucose</string>
|
<string name="sensitivity_raises_target_summary">When sensitivity is detected, raise the target glucose</string>
|
||||||
<string name="key_keep_screen_on" translatable="false">keep_screen_on</string>
|
<string name="key_keep_screen_on" translatable="false">keep_screen_on</string>
|
||||||
<string name="careportal_removestartedevents">Clean AndroidAPS started</string>
|
<string name="careportal_removestartedevents">Clean AndroidAPS started</string>
|
||||||
|
<string name="show_invalidated">Show invalidated</string>
|
||||||
|
<string name="hide_invalidated">Hide invalidated</string>
|
||||||
|
<string name="remove_items">Remove items</string>
|
||||||
<string name="storedsettingsfound">Stored settings found</string>
|
<string name="storedsettingsfound">Stored settings found</string>
|
||||||
<string name="allow_hardware_pump_text">Attention: If you activate and connect to a hardware pump, AndroidAPS will copy the basal settings from the profile to the pump, overwriting the existing basal rate stored on the pump. Make sure you have the correct basal setting in AndroidAPS. If you are not sure or don\'t want to overwrite the basal settings on your pump, press cancel and repeat switching to the pump at a later time.</string>
|
<string name="allow_hardware_pump_text">Attention: If you activate and connect to a hardware pump, AndroidAPS will copy the basal settings from the profile to the pump, overwriting the existing basal rate stored on the pump. Make sure you have the correct basal setting in AndroidAPS. If you are not sure or don\'t want to overwrite the basal settings on your pump, press cancel and repeat switching to the pump at a later time.</string>
|
||||||
<string name="error_adding_treatment_title">Treatment data incomplete</string>
|
<string name="error_adding_treatment_title">Treatment data incomplete</string>
|
||||||
|
@ -1208,4 +1211,14 @@
|
||||||
<string name="wear_unknown_action_string">Unknown action command:</string>
|
<string name="wear_unknown_action_string">Unknown action command:</string>
|
||||||
<string name="overview_editquickwizard_percentage">Percentage</string>
|
<string name="overview_editquickwizard_percentage">Percentage</string>
|
||||||
<string name="app_default">Application default</string>
|
<string name="app_default">Application default</string>
|
||||||
|
<string name="refresh_from_nightscout">Refresh from Nightscout</string>
|
||||||
|
<string name="remove_selected_items">Remove selected items</string>
|
||||||
|
<string name="select_for_removal">Select for removal</string>
|
||||||
|
<string name="profile_changes">Profile changes</string>
|
||||||
|
<string name="tempt_targets">Temp Targets</string>
|
||||||
|
<string name="carbs_and_bolus">Carbs and bolus</string>
|
||||||
|
<string name="confirm_remove_multiple_items">Are you sure you want to remove %1$d items</string>
|
||||||
|
<string name="hide_loop">Hide loop</string>
|
||||||
|
<string name="show_loop">Show loop</string>
|
||||||
|
<string name="count_selected">%1$d selected</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
10
core/src/main/res/drawable/ic_close.xml
Normal file
10
core/src/main/res/drawable/ic_close.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="#FFFFFF"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
|
||||||
|
</vector>
|
|
@ -3,6 +3,8 @@
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
<item name="windowActionModeOverlay">true</item>
|
||||||
|
<item name="actionModeCloseDrawable">@drawable/ic_close</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -469,6 +469,7 @@
|
||||||
<string name="uel_stat_reset">STAT RESET</string>
|
<string name="uel_stat_reset">STAT RESET</string>
|
||||||
<string name="uel_delete_logs">DELETE LOGS</string>
|
<string name="uel_delete_logs">DELETE LOGS</string>
|
||||||
<string name="uel_delete_future_treatments">DELETE FUTURE TREATMENTS</string>
|
<string name="uel_delete_future_treatments">DELETE FUTURE TREATMENTS</string>
|
||||||
|
<string name="delete_future_treatments">Delete future treatments</string>
|
||||||
<string name="uel_export_settings">EXPORT SETTINGS</string>
|
<string name="uel_export_settings">EXPORT SETTINGS</string>
|
||||||
<string name="uel_import_settings">IMPORT SETTINGS</string>
|
<string name="uel_import_settings">IMPORT SETTINGS</string>
|
||||||
<string name="uel_reset_databases">RESET DATABASES</string>
|
<string name="uel_reset_databases">RESET DATABASES</string>
|
||||||
|
|
Loading…
Reference in a new issue