fix: treatments persist selection on scrolling

This commit is contained in:
Andries Smit 2022-02-23 10:11:14 +01:00
parent 967d8bb9d3
commit cb3bb58319
6 changed files with 157 additions and 124 deletions

View file

@ -3,10 +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.util.Log
import android.util.SparseArray
import android.view.* import android.view.*
import android.widget.CompoundButton import android.widget.CompoundButton
import android.view.ActionMode import android.view.ActionMode
import androidx.appcompat.widget.Toolbar 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
@ -68,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,
@ -75,17 +82,11 @@ 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()
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
private var selectedItems: MutableList<MealLink> = mutableListOf()
private var showInvalidated = false private var showInvalidated = false
private var removeActionMode: ActionMode? = null private var removeActionMode: ActionMode? = null
private var toolbar: Toolbar? = null private var toolbar: Toolbar? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
@ -253,21 +254,22 @@ 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()
val onChange = CompoundButton.OnCheckedChangeListener { _, value ->
if (value) {
selectedItems.add(ml)
} else {
selectedItems.remove(ml)
}
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size)
}
holder.binding.cbBolusRemove.visibility = ((ml.bolus?.isValid == true) && removeActionMode != null).toVisibility()
holder.binding.cbBolusRemove.setOnCheckedChangeListener(onChange)
holder.binding.cbCarbsRemove.visibility = (ml.carbs?.isValid == true && removeActionMode != null).toVisibility() holder.binding.cbCarbsRemove.visibility = (ml.carbs?.isValid == true && removeActionMode != null).toVisibility()
holder.binding.cbCarbsRemove.setOnCheckedChangeListener(onChange) if (removeActionMode != null) {
val onChange = CompoundButton.OnCheckedChangeListener { _, value ->
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()
@ -425,8 +427,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
selectedItems = mutableListOf() selectedItems.clear()
mode.title = rh.gs(R.string.count_selected, selectedItems.size) mode.title = rh.gs(R.string.count_selected, selectedItems.size())
binding.recyclerview.adapter?.notifyDataSetChanged() binding.recyclerview.adapter?.notifyDataSetChanged()
return true return true
} }
@ -437,7 +439,6 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
return when (item.itemId) { return when (item.itemId) {
R.id.remove_selected -> { R.id.remove_selected -> {
removeSelected() removeSelected()
mode.finish()
true true
} }
@ -452,8 +453,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
} }
private fun getConfirmationText(): String { private fun getConfirmationText(): String {
if (selectedItems.size == 1) { if (selectedItems.size() == 1) {
val mealLink = selectedItems.first() val mealLink = selectedItems.valueAt(0)
val bolus = mealLink.bolus val bolus = mealLink.bolus
if (bolus != null) if (bolus != null)
return rh.gs(R.string.configbuilder_insulin) + ": " + rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" + return rh.gs(R.string.configbuilder_insulin) + ": " + rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" +
@ -463,14 +464,14 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
return rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs.amount.toInt()) + "\n" + 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) rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(carbs.timestamp)
} }
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
} }
fun removeSelected() { fun removeSelected() {
if (selectedItems.size > 0) if (selectedItems.size() > 0)
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
selectedItems.forEach { ml -> selectedItems.forEach {key, ml ->
ml.bolus?.let { bolus -> ml.bolus?.let { bolus ->
uel.log( uel.log(
Action.BOLUS_REMOVED, Sources.Treatments, Action.BOLUS_REMOVED, Sources.Treatments,
@ -496,7 +497,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
) )
} }
} }
removeActionMode?.finish()
}) })
} }
else
removeActionMode?.finish()
} }
} }

View file

@ -1,9 +1,11 @@
package info.nightscout.androidaps.activities.fragments package info.nightscout.androidaps.activities.fragments
import android.os.Bundle import android.os.Bundle
import android.util.SparseArray
import android.view.* import android.view.*
import android.view.ActionMode import android.view.ActionMode
import androidx.appcompat.widget.Toolbar 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
@ -56,18 +58,17 @@ 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 var _binding: TreatmentsCareportalFragmentBinding? = null
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
private val disposable = CompositeDisposable()
private val millsToThePast = T.days(30).msecs() private val millsToThePast = T.days(30).msecs()
private var selectedItems: MutableList<TherapyEvent> = mutableListOf() private var selectedItems: SparseArray<TherapyEvent> = SparseArray()
private var showInvalidated = false private var showInvalidated = false
private var toolbar: Toolbar? = null private var toolbar: Toolbar? = null
private var removeActionMode: ActionMode? = null private var removeActionMode: ActionMode? = null
private var _binding: TreatmentsCareportalFragmentBinding? = 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 =
TreatmentsCareportalFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root TreatmentsCareportalFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
@ -172,13 +173,16 @@ class TreatmentsCareportalFragment : DaggerFragment() {
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.cbRemove.visibility = (therapyEvent.isValid && removeActionMode != null).toVisibility() holder.binding.cbRemove.visibility = (therapyEvent.isValid && removeActionMode != null).toVisibility()
holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> if (removeActionMode != null) {
if (value) { holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
selectedItems.add(therapyEvent) if (value) {
} else { selectedItems.put(position, therapyEvent)
selectedItems.remove(therapyEvent) } else {
selectedItems.remove(position)
}
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
} }
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()
@ -243,8 +247,8 @@ class TreatmentsCareportalFragment : DaggerFragment() {
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
selectedItems = mutableListOf() selectedItems.clear()
mode.title = rh.gs(R.string.count_selected, selectedItems.size) mode.title = rh.gs(R.string.count_selected, selectedItems.size())
binding.recyclerview.adapter?.notifyDataSetChanged() binding.recyclerview.adapter?.notifyDataSetChanged()
return true return true
} }
@ -255,7 +259,6 @@ class TreatmentsCareportalFragment : DaggerFragment() {
return when (item.itemId) { return when (item.itemId) {
R.id.remove_selected -> { R.id.remove_selected -> {
removeSelected() removeSelected()
mode.finish()
true true
} }
@ -270,20 +273,20 @@ class TreatmentsCareportalFragment : DaggerFragment() {
} }
private fun getConfirmationText(): String { private fun getConfirmationText(): String {
if (selectedItems.size == 1) { if (selectedItems.size() == 1) {
val therapyEvent = selectedItems.first() val therapyEvent = selectedItems.valueAt(0)
return rh.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type) + "\n" + return rh.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type) + "\n" +
rh.gs(R.string.notes_label) + ": " + (therapyEvent.note ?: "") + "\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)
} }
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
} }
private fun removeSelected() { private fun removeSelected() {
if (selectedItems.size > 0) if (selectedItems.size() > 0)
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
selectedItems.forEach { therapyEvent -> selectedItems.forEach { _, therapyEvent ->
uel.log( uel.log(
Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note, Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note,
ValueWithUnit.Timestamp(therapyEvent.timestamp), ValueWithUnit.Timestamp(therapyEvent.timestamp),
@ -295,9 +298,11 @@ class TreatmentsCareportalFragment : DaggerFragment() {
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) } { aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
) )
} }
removeActionMode?.finish()
}) })
} }
else
removeActionMode?.finish()
} }
} }

View file

@ -2,9 +2,11 @@ package info.nightscout.androidaps.activities.fragments
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.util.SparseArray
import android.view.* import android.view.*
import android.view.ActionMode import android.view.ActionMode
import androidx.appcompat.widget.Toolbar 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
@ -59,11 +61,10 @@ 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!!
private var selectedItems: MutableList<ExtendedBolus> = mutableListOf() private var selectedItems: SparseArray<ExtendedBolus> = SparseArray()
private var showInvalidated = false private var showInvalidated = false
private var removeActionMode: ActionMode? = null private var removeActionMode: ActionMode? = null
private var toolbar: Toolbar? = null private var toolbar: Toolbar? = null
@ -149,13 +150,16 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate) holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate)
if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor) if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor)
holder.binding.cbRemove.visibility = (extendedBolus.isValid && removeActionMode != null).toVisibility() holder.binding.cbRemove.visibility = (extendedBolus.isValid && removeActionMode != null).toVisibility()
holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> if (removeActionMode != null) {
if (value) { holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
selectedItems.add(extendedBolus) if (value) {
} else { selectedItems.put(position, extendedBolus)
selectedItems.remove(extendedBolus) } else {
selectedItems.remove(position)
}
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
} }
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()
@ -209,8 +213,8 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
selectedItems = mutableListOf() selectedItems.clear()
mode.title = rh.gs(R.string.count_selected, selectedItems.size) mode.title = rh.gs(R.string.count_selected, selectedItems.size())
binding.recyclerview.adapter?.notifyDataSetChanged() binding.recyclerview.adapter?.notifyDataSetChanged()
return true return true
} }
@ -221,7 +225,6 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
return when (item.itemId) { return when (item.itemId) {
R.id.remove_selected -> { R.id.remove_selected -> {
removeSelected() removeSelected()
mode.finish()
true true
} }
@ -236,18 +239,19 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
} }
private fun getConfirmationText(): String { private fun getConfirmationText(): String {
if (selectedItems.size == 1) { if (selectedItems.size() == 1) {
val bolus = selectedItems.valueAt(0)
return rh.gs(R.string.extended_bolus) + "\n" + return rh.gs(R.string.extended_bolus) + "\n" +
"${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(selectedItems.first().timestamp)}" "${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(bolus.timestamp)}"
} }
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
} }
private fun removeSelected() { private fun removeSelected() {
if (selectedItems.size > 0) if (selectedItems.size() > 0)
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
selectedItems.forEach { extendedBolus -> selectedItems.forEach { _, extendedBolus ->
uel.log( uel.log(
Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments, Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(extendedBolus.timestamp), ValueWithUnit.Timestamp(extendedBolus.timestamp),
@ -260,7 +264,10 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
{ 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) })
} }
removeActionMode?.finish()
}) })
} }
else
removeActionMode?.finish()
} }
} }

View file

@ -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.util.SparseArray
import android.view.* import android.view.*
import android.view.ActionMode import android.view.ActionMode
import androidx.appcompat.widget.Toolbar 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,17 +63,16 @@ 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: MutableList<ProfileSealed> = mutableListOf() private var selectedItems: SparseArray<ProfileSealed> = SparseArray()
private var showInvalidated = false private var showInvalidated = false
private var removeActionMode: ActionMode? = null private var removeActionMode: ActionMode? = null
private var toolbar: Toolbar? = 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
@ -198,13 +199,16 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
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.cbRemove.visibility = (removeActionMode != null && profileSwitch is ProfileSealed.PS).toVisibility() holder.binding.cbRemove.visibility = (removeActionMode != null && profileSwitch is ProfileSealed.PS).toVisibility()
holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> if (removeActionMode != null) {
if (value) { holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
selectedItems.add(profileSwitch) if (value) {
} else { selectedItems.put(position, profileSwitch)
selectedItems.remove(profileSwitch) } else {
selectedItems.remove(position)
}
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
} }
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()
@ -314,8 +318,8 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
selectedItems = mutableListOf() selectedItems.clear()
mode.title = rh.gs(R.string.count_selected, selectedItems.size) mode.title = rh.gs(R.string.count_selected, selectedItems.size())
binding.recyclerview.adapter?.notifyDataSetChanged() binding.recyclerview.adapter?.notifyDataSetChanged()
return true return true
} }
@ -326,7 +330,6 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
return when (item.itemId) { return when (item.itemId) {
R.id.remove_selected -> { R.id.remove_selected -> {
removeSelected() removeSelected()
mode.finish()
true true
} }
@ -341,18 +344,18 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
} }
private fun getConfirmationText(): String { private fun getConfirmationText(): String {
if (selectedItems.size == 1) { if (selectedItems.size() == 1) {
val profileSwitch = selectedItems.first() 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.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) return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
} }
private fun removeSelected() { private fun removeSelected() {
if (selectedItems.size > 0) if (selectedItems.size() > 0)
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
selectedItems.forEach { profileSwitch -> selectedItems.forEach { _, profileSwitch ->
uel.log( uel.log(
Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName, Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName,
ValueWithUnit.Timestamp(profileSwitch.timestamp) ValueWithUnit.Timestamp(profileSwitch.timestamp)
@ -363,7 +366,10 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) } { aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) }
) )
} }
removeActionMode?.finish()
}) })
} }
else
removeActionMode?.finish()
} }
} }

View file

@ -2,8 +2,10 @@ package info.nightscout.androidaps.activities.fragments
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.util.SparseArray
import android.view.* import android.view.*
import androidx.appcompat.widget.Toolbar 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
@ -65,19 +67,17 @@ 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 var _binding: TreatmentsTemptargetFragmentBinding? = null
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
private val disposable = CompositeDisposable()
private val millsToThePast = T.days(30).msecs() private val millsToThePast = T.days(30).msecs()
private var selectedItems: MutableList<TemporaryTarget> = mutableListOf() private var selectedItems: SparseArray<TemporaryTarget> = SparseArray()
private var showInvalidated = false private var showInvalidated = false
private var toolbar: Toolbar? = null private var toolbar: Toolbar? = null
private var removeActionMode: ActionMode? = null private var removeActionMode: ActionMode? = null
private var _binding: TreatmentsTemptargetFragmentBinding? = 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 =
TreatmentsTemptargetFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root TreatmentsTemptargetFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
@ -174,13 +174,16 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility() holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
holder.binding.cbRemove.visibility = (tempTarget.isValid && removeActionMode != null).toVisibility() holder.binding.cbRemove.visibility = (tempTarget.isValid && removeActionMode != null).toVisibility()
holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> if (removeActionMode != null) {
if (value) { holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
selectedItems.add(tempTarget) if (value) {
} else { selectedItems.put(position, tempTarget)
selectedItems.remove(tempTarget) } else {
selectedItems.remove(position)
}
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
} }
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) 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()
@ -211,10 +214,10 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
} }
private fun removeSelected() { private fun removeSelected() {
if (selectedItems.size > 0) if (selectedItems.size() > 0)
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
selectedItems.forEach { tempTarget -> selectedItems.forEach { _, tempTarget ->
uel.log( uel.log(
Action.TT_REMOVED, Sources.Treatments, Action.TT_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(tempTarget.timestamp), ValueWithUnit.Timestamp(tempTarget.timestamp),
@ -228,8 +231,11 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
{ 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) })
} }
removeActionMode?.finish()
}) })
} }
else
removeActionMode?.finish()
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
@ -277,8 +283,8 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
selectedItems = mutableListOf() selectedItems.clear()
mode.title = rh.gs(R.string.count_selected, selectedItems.size) mode.title = rh.gs(R.string.count_selected, selectedItems.size())
binding.recyclerview.adapter?.notifyDataSetChanged() binding.recyclerview.adapter?.notifyDataSetChanged()
return true return true
} }
@ -289,7 +295,6 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
return when (item.itemId) { return when (item.itemId) {
R.id.remove_selected -> { R.id.remove_selected -> {
removeSelected() removeSelected()
mode.finish()
true true
} }
@ -304,12 +309,12 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
} }
private fun getConfirmationText(): String { private fun getConfirmationText(): String {
if (selectedItems.size == 1) { if (selectedItems.size() == 1) {
val tempTarget = selectedItems.first() val tempTarget = selectedItems.valueAt(0)
return "${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)}\n" + return "${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)}\n" +
dateUtil.dateAndTimeString(tempTarget.timestamp) dateUtil.dateAndTimeString(tempTarget.timestamp)
} }
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
} }
} }

View file

@ -1,8 +1,11 @@
package info.nightscout.androidaps.activities.fragments package info.nightscout.androidaps.activities.fragments
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.util.SparseArray
import android.view.* import android.view.*
import androidx.appcompat.widget.Toolbar 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
@ -62,16 +65,15 @@ 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: MutableList<TemporaryBasal> = mutableListOf() private var selectedItems: SparseArray<TemporaryBasal> = SparseArray()
private var showInvalidated = false private var showInvalidated = false
private var toolbar: Toolbar? = null private var toolbar: Toolbar? = null
private var removeActionMode: ActionMode? = null private var removeActionMode: ActionMode? = 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 =
TreatmentsTempbasalsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root TreatmentsTempbasalsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
@ -192,13 +194,16 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility() holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility()
if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor) if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor)
holder.binding.cbRemove.visibility = (tempBasal.isValid && removeActionMode != null).toVisibility() holder.binding.cbRemove.visibility = (tempBasal.isValid && removeActionMode != null).toVisibility()
holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> if (removeActionMode != null) {
if (value) { holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
selectedItems.add(tempBasal) if (value) {
} else { selectedItems.put(position, tempBasal)
selectedItems.remove(tempBasal) } else {
selectedItems.remove(position)
}
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
} }
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()
@ -252,8 +257,8 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
selectedItems = mutableListOf() selectedItems.clear()
mode.title = rh.gs(R.string.count_selected, selectedItems.size) mode.title = rh.gs(R.string.count_selected, selectedItems.size())
binding.recyclerview.adapter?.notifyDataSetChanged() binding.recyclerview.adapter?.notifyDataSetChanged()
return true return true
} }
@ -264,7 +269,6 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
return when (item.itemId) { return when (item.itemId) {
R.id.remove_selected -> { R.id.remove_selected -> {
removeSelected() removeSelected()
mode.finish()
true true
} }
@ -279,23 +283,22 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
} }
private fun getConfirmationText(): String { private fun getConfirmationText(): String {
if (selectedItems.size == 1) { if (selectedItems.size() == 1) {
val tempBasal = selectedItems.first() val tempBasal = selectedItems.valueAt(0)
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
val profile = profileFunction.getProfile(dateUtil.now()) val profile = profileFunction.getProfile(dateUtil.now())
if (profile != null) if (profile != null)
return "${if (isFakeExtended) rh.gs(R.string.extended_bolus) else rh.gs(R.string.tempbasal_label)}: ${tempBasal.toStringFull(profile, dateUtil)}\n" + 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)}" "${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(tempBasal.timestamp)}"
} }
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
} }
private fun removeSelected() { private fun removeSelected() {
// TODO check if item should not be delete val profile = profileFunction.getProfile(dateUtil.now()) == null if (selectedItems.size() > 0)
if (selectedItems.size > 0)
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
selectedItems.forEach { tempBasal -> 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) {
@ -327,7 +330,10 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) }) { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) })
} }
} }
removeActionMode?.finish()
}) })
} }
else
removeActionMode?.finish()
} }
} }