Merge pull request #4 from nightscout/dev

Dev
This commit is contained in:
Tim Street 2022-02-27 09:32:28 +00:00 committed by GitHub
commit cee8eedf64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
409 changed files with 5236 additions and 2829 deletions

View file

@ -109,7 +109,7 @@ android {
defaultConfig {
multiDexEnabled true
versionCode 1500
version "3.0.0.1-dev-a"
version "3.0.0.1-dev-c"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'

View file

@ -64,6 +64,7 @@
</activity>
<activity android:name=".activities.PreferencesActivity" />
<activity android:name=".plugins.general.overview.activities.QuickWizardListActivity"
android:theme="@style/AppTheme"
android:exported="false">
<intent-filter>
<action android:name="info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity" />
@ -75,8 +76,7 @@
<activity android:name=".activities.HistoryBrowseActivity" />
<activity android:name=".activities.TreatmentsActivity" />
<activity android:name=".activities.SurveyActivity" />
<activity android:name=".activities.ProfileHelperActivity"
android:theme="@style/ProfileHelperAppTheme" />
<activity android:name=".activities.ProfileHelperActivity" />
<activity android:name=".activities.StatsActivity" />
<activity
android:name="com.google.firebase.auth.internal.FederatedSignInActivity"
@ -229,8 +229,7 @@
<activity
android:name=".setupwizard.SetupWizardActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/title_activity_setup_wizard"
android:theme="@style/AppTheme.NoActionBar" />
android:label="@string/title_activity_setup_wizard" />
<activity
android:name=".activities.SingleFragmentActivity"

View file

@ -287,7 +287,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
}
//console.log(" (autosens ratio "+sensitivityRatio+")");
}
console.error("; CR:",profile.carb_ratio);
console.error("CR:",profile.carb_ratio);
// compare currenttemp to iob_data.lastTemp and cancel temp if they don't match
var lastTempAge;
@ -298,7 +298,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
}
//console.error("currenttemp:",currenttemp,"lastTemp:",JSON.stringify(iob_data.lastTemp),"lastTempAge:",lastTempAge,"m");
var tempModulus = (lastTempAge + currenttemp.duration) % 30;
console.error("currenttemp:",currenttemp,"lastTempAge:",lastTempAge,"m","tempModulus:",tempModulus,"m");
console.error("currenttemp:",round(currenttemp.rate,2),"lastTempAge:",lastTempAge,"m","tempModulus:",tempModulus,"m");
rT.temp = 'absolute';
rT.deliverAt = deliverAt;
if ( microBolusAllowed && currenttemp && iob_data.lastTemp && currenttemp.rate !== iob_data.lastTemp.rate && lastTempAge > 10 && currenttemp.duration ) {

View file

@ -1247,4 +1247,4 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
};
module.exports = determine_basal;
module.exports = determine_basal;

View file

@ -56,8 +56,8 @@ import info.nightscout.androidaps.utils.tabs.TabPageAdapter
import info.nightscout.androidaps.utils.ui.UIRunnable
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.*
import javax.inject.Inject
import kotlin.system.exitProcess
@ -320,7 +320,7 @@ class MainActivity : NoSplashAppCompatActivity() {
message += rh.gs(R.string.about_link_urls)
val messageSpanned = SpannableString(message)
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS)
AlertDialog.Builder(this)
AlertDialog.Builder(this, R.style.DialogTheme)
.setTitle(rh.gs(R.string.app_name) + " " + BuildConfig.VERSION)
.setIcon(iconsProvider.getIcon())
.setMessage(messageSpanned)

View file

@ -39,10 +39,10 @@ import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.locale.LocaleHelper
import info.nightscout.androidaps.utils.protection.PasswordCheck
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.exceptions.UndeliverableException
import io.reactivex.plugins.RxJavaPlugins
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.exceptions.UndeliverableException
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.plugins.RxJavaPlugins
import net.danlew.android.joda.JodaTimeAndroid
import java.io.IOException
import java.net.SocketException

View file

@ -42,8 +42,8 @@ import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.*
import javax.inject.Inject
import kotlin.math.min
@ -179,7 +179,8 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
val cal = Calendar.getInstance()
cal.timeInMillis = overviewData.fromTime
DatePickerDialog(
this, dateSetListener,
this, R.style.MaterialPickerTheme,
dateSetListener,
cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH),
cal.get(Calendar.DAY_OF_MONTH)

View file

@ -123,9 +123,11 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
override fun onDestroy() {
super.onDestroy()
PreferenceManager
.getDefaultSharedPreferences(context)
.unregisterOnSharedPreferenceChangeListener(this)
context?.let { context ->
PreferenceManager
.getDefaultSharedPreferences(context)
.unregisterOnSharedPreferenceChangeListener(this)
}
}
private fun addPreferencesFromResourceIfEnabled(p: PluginBase?, rootKey: String?, enabled: Boolean) {
@ -139,9 +141,11 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
PreferenceManager
.getDefaultSharedPreferences(context)
.registerOnSharedPreferenceChangeListener(this)
context?.let { context ->
PreferenceManager
.getDefaultSharedPreferences(context)
.registerOnSharedPreferenceChangeListener(this)
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
@ -263,19 +267,19 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
@SuppressLint("RestrictedApi")
private fun addPreferencesFromResource(@XmlRes preferencesResId: Int, key: String?) {
val xmlRoot = preferenceManager.inflateFromResource(context,
preferencesResId, null)
val root: Preference?
if (key != null) {
root = xmlRoot.findPreference(key)
if (root == null) return
require(root is PreferenceScreen) {
("Preference object with key " + key
+ " is not a PreferenceScreen")
context?.let { context ->
val xmlRoot = preferenceManager.inflateFromResource(context, preferencesResId, null)
val root: Preference?
if (key != null) {
root = xmlRoot.findPreference(key)
if (root == null) return
require(root is PreferenceScreen) {
("Preference object with key $key is not a PreferenceScreen")
}
preferenceScreen = root
} else {
addPreferencesFromResource(preferencesResId)
}
preferenceScreen = root
} else {
addPreferencesFromResource(preferencesResId)
}
}
@ -305,15 +309,9 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
p.initialExpandedChildrenCount = Int.MAX_VALUE
}
} else {
if (p.key != null) {
visible = visible || p.key.contains(filter, true)
}
if (p.title != null) {
visible = visible || p.title.contains(filter, true)
}
if (p.summary != null) {
visible = visible || p.summary.contains(filter, true)
}
visible = visible || p.key?.contains(filter, true) == true
visible = visible || p.title?.contains(filter, true) == true
visible = visible || p.summary?.contains(filter, true) == true
}
p.isVisible = visible
@ -393,32 +391,30 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
// We use Preference and custom editor instead of EditTextPreference
// to hash password while it is saved and never have to show it, even hashed
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
override fun onPreferenceTreeClick(preference: Preference): Boolean {
context?.let { context ->
if (preference != null) {
if (preference.key == rh.gs(R.string.key_master_password)) {
passwordCheck.queryPassword(context, R.string.current_master_password, R.string.key_master_password, {
passwordCheck.setPassword(context, R.string.master_password, R.string.key_master_password)
})
return true
}
if (preference.key == rh.gs(R.string.key_settings_password)) {
passwordCheck.setPassword(context, R.string.settings_password, R.string.key_settings_password)
return true
}
if (preference.key == rh.gs(R.string.key_bolus_password)) {
passwordCheck.setPassword(context, R.string.bolus_password, R.string.key_bolus_password)
return true
}
if (preference.key == rh.gs(R.string.key_application_password)) {
passwordCheck.setPassword(context, R.string.application_password, R.string.key_application_password)
return true
}
// NSClient copy settings
if (preference.key == rh.gs(R.string.key_statuslights_copy_ns)) {
nsSettingStatus.copyStatusLightsNsSettings(context)
return true
}
if (preference.key == rh.gs(R.string.key_master_password)) {
passwordCheck.queryPassword(context, R.string.current_master_password, R.string.key_master_password, {
passwordCheck.setPassword(context, R.string.master_password, R.string.key_master_password)
})
return true
}
if (preference.key == rh.gs(R.string.key_settings_password)) {
passwordCheck.setPassword(context, R.string.settings_password, R.string.key_settings_password)
return true
}
if (preference.key == rh.gs(R.string.key_bolus_password)) {
passwordCheck.setPassword(context, R.string.bolus_password, R.string.key_bolus_password)
return true
}
if (preference.key == rh.gs(R.string.key_application_password)) {
passwordCheck.setPassword(context, R.string.application_password, R.string.key_application_password)
return true
}
// NSClient copy settings
if (preference.key == rh.gs(R.string.key_statuslights_copy_ns)) {
nsSettingStatus.copyStatusLightsNsSettings(context)
return true
}
}
return super.onPreferenceTreeClick(preference)

View file

@ -283,7 +283,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
tabSelected = tab
typeSelected[tabSelected] = newContent
binding.profiletypeTitle.defaultHintTextColor = ColorStateList.valueOf(rh.gc(if (tab == 0) R.color.tabBgColorSelected else R.color.examinedProfile))
binding.profiletypeTitle.defaultHintTextColor = ColorStateList.valueOf(rh.gc(if (tab == 0) R.color.helperProfile else R.color.examinedProfile))
// show new content
binding.profiletype.setText(
@ -314,7 +314,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
}
private fun setBackgroundColorOnSelected(tab: Int) {
binding.menu1.setBackgroundColor(rh.gc(if (tab == 1) R.color.defaultbackground else R.color.tempbasal))
binding.menu1.setBackgroundColor(rh.gc(if (tab == 1) R.color.defaultbackground else R.color.helperProfile))
binding.menu2.setBackgroundColor(rh.gc(if (tab == 0) R.color.defaultbackground else R.color.examinedProfile))
}
}

View file

@ -1,13 +1,13 @@
package info.nightscout.androidaps.activities
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.fragments.*
import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import javax.inject.Inject
@ -23,40 +23,60 @@ class TreatmentsActivity : NoSplashAppCompatActivity() {
super.onCreate(savedInstanceState)
binding = TreatmentsFragmentBinding.inflate(layoutInflater)
setContentView(binding.root)
//binding.tempBasals.visibility = buildHelper.isEngineeringMode().toVisibility()
//binding.extendedBoluses.visibility = (buildHelper.isEngineeringMode() && !activePlugin.activePump.isFakingTempsByExtendedBoluses).toVisibility()
binding.treatments.setOnClickListener {
setFragment(TreatmentsBolusCarbsFragment())
setBackgroundColorOnSelected(it)
supportActionBar?.title = rh.gs(R.string.carbs_and_bolus)
}
binding.extendedBoluses.setOnClickListener {
setFragment(TreatmentsExtendedBolusesFragment())
setBackgroundColorOnSelected(it)
supportActionBar?.title = rh.gs(R.string.extended_bolus)
}
binding.tempBasals.setOnClickListener {
setFragment(TreatmentsTemporaryBasalsFragment())
setBackgroundColorOnSelected(it)
supportActionBar?.title = rh.gs(R.string.tempbasal_label)
}
binding.tempTargets.setOnClickListener {
setFragment(TreatmentsTempTargetFragment())
setBackgroundColorOnSelected(it)
supportActionBar?.title = rh.gs(R.string.tempt_targets)
}
binding.profileSwitches.setOnClickListener {
setFragment(TreatmentsProfileSwitchFragment())
setBackgroundColorOnSelected(it)
supportActionBar?.title = rh.gs(R.string.profile_changes)
}
binding.careportal.setOnClickListener {
setFragment(TreatmentsCareportalFragment())
setBackgroundColorOnSelected(it)
supportActionBar?.title = rh.gs(R.string.careportal)
}
binding.userentry.setOnClickListener {
setFragment(TreatmentsUserEntryFragment())
setBackgroundColorOnSelected(it)
supportActionBar?.title = rh.gs(R.string.user_action)
}
setFragment(TreatmentsBolusCarbsFragment())
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) {

View file

@ -3,9 +3,13 @@ package info.nightscout.androidaps.activities.fragments
import android.annotation.SuppressLint
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.util.Log
import android.util.SparseArray
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.RecyclerView
import dagger.android.support.DaggerFragment
@ -45,10 +49,10 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.Completable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@ -67,6 +71,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
@Inject lateinit var repository: AppRepository
@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(
val bolus: Bolus? = null,
val carbs: Carbs? = null,
@ -74,14 +82,12 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
)
private val disposable = CompositeDisposable()
private val millsToThePast = T.days(30).msecs()
private var _binding: TreatmentsBolusCarbsFragmentBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private var selectedItems: SparseArray<MealLink> = SparseArray()
private var showInvalidated = false
private var removeActionMode: ActionMode? = null
private var toolbar: Toolbar? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
TreatmentsBolusCarbsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
@ -89,92 +95,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
@SuppressLint("CheckResult")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
toolbar = activity?.findViewById(R.id.toolbar)
binding.recyclerview.setHasFixedSize(true)
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
@ -204,36 +128,35 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
fun swapAdapter() {
val now = System.currentTimeMillis()
if (binding.showInvalidated.isChecked)
disposable += carbsMealLinksWithInvalid(now)
.zipWith(bolusMealLinksWithInvalid(now)) { first, second -> first + second }
.zipWith(calcResultMealLinksWithInvalid(now)) { first, second -> first + second }
.map { ml ->
ml.sortedByDescending {
it.carbs?.timestamp ?: it.bolus?.timestamp
?: it.bolusCalculatorResult?.timestamp
disposable +=
if (showInvalidated)
carbsMealLinksWithInvalid(now)
.zipWith(bolusMealLinksWithInvalid(now)) { first, second -> first + second }
.zipWith(calcResultMealLinksWithInvalid(now)) { first, second -> first + second }
.map { ml ->
ml.sortedByDescending {
it.carbs?.timestamp ?: it.bolus?.timestamp
?: it.bolusCalculatorResult?.timestamp
}
}
}
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true)
binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility()
}
else
disposable += carbsMealLinks(now)
.zipWith(bolusMealLinks(now)) { first, second -> first + second }
.zipWith(calcResultMealLinks(now)) { first, second -> first + second }
.map { ml ->
ml.sortedByDescending {
it.carbs?.timestamp ?: it.bolus?.timestamp
?: it.bolusCalculatorResult?.timestamp
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true)
}
else
carbsMealLinks(now)
.zipWith(bolusMealLinks(now)) { first, second -> first + second }
.zipWith(calcResultMealLinks(now)) { first, second -> first + second }
.map { ml ->
ml.sortedByDescending {
it.carbs?.timestamp ?: it.bolus?.timestamp
?: it.bolusCalculatorResult?.timestamp
}
}
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true)
}
}
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true)
binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility()
}
}
@ -267,13 +190,14 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
removeActionMode?.let { it.finish() }
binding.recyclerview.adapter = null // avoid leaks
_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 =
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))
// 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 ->
holder.binding.calcTime.text = dateUtil.timeString(bolusCalculatorResult.timestamp)
}
// 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 ->
holder.binding.bolusTime.text = dateUtil.timeString(bolus.timestamp)
holder.binding.insulin.text = rh.gs(R.string.formatinsulinunits, bolus.amount)
@ -321,7 +245,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
}
}
// 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 ->
holder.binding.carbsTime.text = dateUtil.timeString(carbs.timestamp)
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.carbsInvalid.visibility = carbs.isValid.not().toVisibility()
}
holder.binding.bolusRemove.visibility = (ml.bolus?.isValid == true).toVisibility()
holder.binding.carbsRemove.visibility = (ml.carbs?.isValid == true).toVisibility()
holder.binding.bolusRemove.tag = ml
holder.binding.carbsRemove.tag = ml
holder.binding.cbBolusRemove.visibility = (ml.bolus?.isValid == true && removeActionMode != null).toVisibility()
holder.binding.cbCarbsRemove.visibility = (ml.carbs?.isValid == true && removeActionMode != null).toVisibility()
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
val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L
holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility()
}
override fun getItemCount(): Int {
return mealLinks.size
}
override fun getItemCount() = mealLinks.size
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.bolusRemove.setOnClickListener { ml ->
val bolus = (ml.tag as MealLink?)?.bolus ?: return@setOnClickListener
activity?.let { activity ->
val text = rh.gs(R.string.configbuilder_insulin) + ": " +
rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" +
rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(bolus.timestamp)
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), text, Runnable {
}
}
}
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 ->
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())
}
}
}
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)
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 { _, ml ->
ml.bolus?.let { bolus ->
uel.log(
Action.BOLUS_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(bolus.timestamp),
ValueWithUnit.Insulin(bolus.amount)
//ValueWithUnit.Gram(mealLinkLoaded.carbs.toInt())
)
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) }
)
})
}
}
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 {
}
ml.carbs?.let { carb ->
uel.log(
Action.CARBS_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(carb.timestamp),
@ -398,11 +495,12 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) }
)
})
}
}
}
binding.carbsRemove.paintFlags = binding.carbsRemove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
removeActionMode?.finish()
})
}
}
else
removeActionMode?.finish()
}
}
}

View file

@ -1,10 +1,11 @@
package info.nightscout.androidaps.activities.fragments
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.util.SparseArray
import android.view.*
import android.view.ActionMode
import androidx.appcompat.widget.Toolbar
import androidx.core.util.forEach
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
@ -36,10 +37,10 @@ import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.Completable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@ -57,61 +58,61 @@ class TreatmentsCareportalFragment : DaggerFragment() {
@Inject lateinit var repository: AppRepository
@Inject lateinit var uel: UserEntryLogger
private val disposable = CompositeDisposable()
private val millsToThePast = T.days(30).msecs()
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 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 =
TreatmentsCareportalFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
toolbar = activity?.findViewById(R.id.toolbar)
setHasOptionsMenu(true)
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.refreshFromNightscout.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.refresheventsfromnightscout) + " ?", Runnable {
uel.log(Action.CAREPORTAL_NS_REFRESH, Sources.Treatments)
disposable += Completable.fromAction { repository.deleteAllTherapyEventsEntries() }
.subscribeOn(aapsSchedulers.io)
.subscribeBy(
onError = { aapsLogger.error("Error removing entries", it) },
onComplete = { rxBus.send(EventTherapyEventChange()) }
)
rxBus.send(EventNSClientRestart())
})
}
}
binding.removeAndroidapsStartedEvents.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.careportal_removestartedevents), Runnable {
uel.log(Action.RESTART_EVENTS_REMOVED, Sources.Treatments)
repository.runTransactionForResult(InvalidateAAPSStartedTherapyEventTransaction(rh.gs(R.string.androidaps_start)))
.subscribe(
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated 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())
private fun refreshFromNightscout() {
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.refresheventsfromnightscout) + " ?", Runnable {
uel.log(Action.CAREPORTAL_NS_REFRESH, Sources.Treatments)
disposable += Completable.fromAction { repository.deleteAllTherapyEventsEntries() }
.subscribeOn(aapsSchedulers.io)
.subscribeBy(
onError = { aapsLogger.error("Error removing entries", it) },
onComplete = { rxBus.send(EventTherapyEventChange()) }
)
rxBus.send(EventNSClientRestart())
})
}
}
private fun removeStartedEvents() {
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.careportal_removestartedevents), Runnable {
uel.log(Action.RESTART_EVENTS_REMOVED, Sources.Treatments)
disposable += repository.runTransactionForResult(InvalidateAAPSStartedTherapyEventTransaction(rh.gs(R.string.androidaps_start)))
.subscribe(
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
)
})
}
}
fun swapAdapter() {
val now = System.currentTimeMillis()
disposable +=
if (binding.showInvalidated.isChecked)
if (showInvalidated)
repository
.getTherapyEventDataIncludingInvalidFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
@ -148,6 +149,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
removeActionMode?.let { it.finish() }
binding.recyclerview.adapter = null // avoid leaks
_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.note.text = therapyEvent.note
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
holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility()
}
override fun getItemCount(): Int {
return therapyList.size
}
override fun getItemCount() = therapyList.size
inner class TherapyEventsViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = TreatmentsCareportalItemBinding.bind(view)
init {
binding.remove.setOnClickListener { v: View ->
val therapyEvent = v.tag as TherapyEvent
activity?.let { activity ->
val text = 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)
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), text, Runnable {
uel.log(Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note ,
ValueWithUnit.Timestamp(therapyEvent.timestamp),
ValueWithUnit.TherapyEventType(therapyEvent.type))
disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id))
.subscribe(
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
)
}, null)
}
}
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
}
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_treatments_careportal, 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_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)
}
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.TherapyEventType(therapyEvent.type)
)
disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id))
.subscribe(
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
)
}
removeActionMode?.finish()
})
}
else
removeActionMode?.finish()
}
}

View file

@ -1,12 +1,12 @@
package info.nightscout.androidaps.activities.fragments
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.util.SparseArray
import android.view.*
import android.view.ActionMode
import androidx.appcompat.widget.Toolbar
import androidx.core.util.forEach
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
@ -27,18 +27,19 @@ import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
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.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import info.nightscout.shared.logging.LTag
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@ -60,23 +61,27 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
@Inject lateinit var repository: AppRepository
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!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View =
private var selectedItems: SparseArray<ExtendedBolus> = SparseArray()
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
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
setHasOptionsMenu(true)
toolbar = activity?.findViewById(R.id.toolbar)
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
}
fun swapAdapter() {
val now = System.currentTimeMillis()
if (binding.showInvalidated.isChecked)
disposable += if (showInvalidated)
repository
.getExtendedBolusDataIncludingInvalidFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
@ -109,6 +114,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
removeActionMode?.let { it.finish() }
binding.recyclerview.adapter = null // avoid leaks
_binding = null
}
@ -125,7 +131,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).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.text = dateUtil.dateString(extendedBolus.timestamp)
@SuppressLint("SetTextI18n")
@ -143,41 +149,125 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
holder.binding.iob.text = rh.gs(R.string.formatinsulinunits, iob.iob)
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)
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
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) {
val binding = TreatmentsExtendedbolusItemBinding.bind(itemView)
init {
binding.remove.setOnClickListener { v: View ->
val extendedBolus = v.tag as ExtendedBolus
context?.let { context ->
OKDialog.showConfirmation(context, rh.gs(R.string.removerecord),
"""
${rh.gs(R.string.extended_bolus)}
${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(extendedBolus.timestamp)}
""".trimIndent(), { _: DialogInterface, _: Int ->
uel.log(Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(extendedBolus.timestamp),
ValueWithUnit.Insulin(extendedBolus.amount),
ValueWithUnit.UnitPerHour(extendedBolus.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt()))
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
.subscribe(
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
}, null)
}
}
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
}
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_treatments_extended_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
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.Insulin(extendedBolus.amount),
ValueWithUnit.UnitPerHour(extendedBolus.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt())
)
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
.subscribe(
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
}
removeActionMode?.finish()
})
}
else
removeActionMode?.finish()
}
}

View file

@ -2,13 +2,16 @@ package info.nightscout.androidaps.activities.fragments
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.util.SparseArray
import android.view.*
import android.view.ActionMode
import androidx.appcompat.widget.Toolbar
import androidx.core.util.forEach
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.fragments.TreatmentsProfileSwitchFragment.RecyclerProfileViewAdapter.ProfileSwitchViewHolder
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.Action
@ -18,20 +21,17 @@ import info.nightscout.androidaps.database.transactions.InvalidateProfileSwitchT
import info.nightscout.androidaps.databinding.TreatmentsProfileswitchFragmentBinding
import info.nightscout.androidaps.databinding.TreatmentsProfileswitchItemBinding
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged
import info.nightscout.androidaps.events.EventProfileSwitchChanged
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
import info.nightscout.androidaps.extensions.getCustomizedName
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
import info.nightscout.androidaps.activities.fragments.TreatmentsProfileSwitchFragment.RecyclerProfileViewAdapter.ProfileSwitchViewHolder
import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
@ -39,11 +39,13 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.Completable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy
import javax.inject.Inject
class TreatmentsProfileSwitchFragment : DaggerFragment() {
@ -61,50 +63,50 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
@Inject lateinit var uel: UserEntryLogger
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 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 =
TreatmentsProfileswitchFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
toolbar = activity?.findViewById(R.id.toolbar)
binding.recyclerview.setHasFixedSize(true)
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.deleteAllEffectiveProfileSwitches()
repository.deleteAllProfileSwitches()
}
.subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main)
.subscribeBy(
onError = { aapsLogger.error("Error removing entries", it) },
onComplete = {
rxBus.send(EventProfileSwitchChanged())
rxBus.send(EventEffectiveProfileSwitchChanged(0L))
rxBus.send(EventNewHistoryData(0, false))
}
)
rxBus.send(EventNSClientRestart())
}
private fun refreshFromNightscout() {
activity?.let { activity ->
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)
.observeOn(aapsSchedulers.main)
.subscribeBy(
onError = { aapsLogger.error("Error removing entries", it) },
onComplete = {
rxBus.send(EventProfileSwitchChanged())
rxBus.send(EventEffectiveProfileSwitchChanged(0L))
rxBus.send(EventNewHistoryData(0, false))
}
)
rxBus.send(EventNSClientRestart())
}
}
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
@ -126,23 +128,23 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
fun swapAdapter() {
val now = System.currentTimeMillis()
if (binding.showInvalidated.isChecked)
disposable += profileSwitchWithInvalid(now)
.zipWith(effectiveProfileSwitchWithInvalid(now)) { first, second -> first + second }
.map { ml -> ml.sortedByDescending { it.timestamp } }
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
}
else
disposable += profileSwitches(now)
.zipWith(effectiveProfileSwitches(now)) { first, second -> first + second }
.map { ml -> ml.sortedByDescending { it.timestamp } }
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
}
disposable +=
if (showInvalidated)
profileSwitchWithInvalid(now)
.zipWith(effectiveProfileSwitchWithInvalid(now)) { first, second -> first + second }
.map { ml -> ml.sortedByDescending { it.timestamp } }
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
}
else
profileSwitches(now)
.zipWith(effectiveProfileSwitches(now)) { first, second -> first + second }
.map { ml -> ml.sortedByDescending { it.timestamp } }
.observeOn(aapsSchedulers.main)
.subscribe { list ->
binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true)
}
}
@Synchronized
@ -168,6 +170,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
removeActionMode?.finish()
binding.recyclerview.adapter = null // avoid leaks
_binding = null
}
@ -186,64 +189,66 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
holder.binding.date.text = dateUtil.dateString(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.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))
else holder.binding.date.setTextColor(holder.binding.duration.currentTextColor)
holder.binding.remove.tag = profileSwitch
holder.binding.clone.tag = profileSwitch
holder.binding.name.tag = profileSwitch
holder.binding.date.tag = profileSwitch
holder.binding.invalid.visibility = profileSwitch.isValid.not().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.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))
val nextTimestamp = if (profileSwitchList.size != position + 1) profileSwitchList[position + 1].timestamp else 0L
holder.binding.delimiter.visibility = dateUtil.isSameDay(profileSwitch.timestamp, nextTimestamp).toVisibility()
}
override fun getItemCount(): Int {
return profileSwitchList.size
}
override fun getItemCount() = profileSwitchList.size
inner class ProfileSwitchViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
val binding = TreatmentsProfileswitchItemBinding.bind(itemView)
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 {
activity?.let { activity ->
val profileSwitch = (it.tag as ProfileSealed.PS).value
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 {
uel.log(Action.PROFILE_SWITCH_CLONED, Sources.Treatments,
profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"),
ValueWithUnit.Timestamp(profileSwitch.timestamp),
ValueWithUnit.SimpleString(profileSwitch.profileName))
val nonCustomized = profileSealed.convertToNonCustomizedProfile(dateUtil)
localProfilePlugin.addProfile(localProfilePlugin.copyFrom(nonCustomized, profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_")))
rxBus.send(EventLocalProfileChanged())
})
OKDialog.showConfirmation(
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(".", "_"),
ValueWithUnit.Timestamp(profileSwitch.timestamp),
ValueWithUnit.SimpleString(profileSwitch.profileName)
)
val nonCustomized = profileSealed.convertToNonCustomizedProfile(dateUtil)
localProfilePlugin.addProfile(
localProfilePlugin.copyFrom(
nonCustomized,
profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_")
)
)
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.name.setOnClickListener {
ProfileViewerDialog().also { pvd ->
@ -266,4 +271,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()
}
}

View file

@ -1,12 +1,11 @@
package info.nightscout.androidaps.activities.fragments
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.util.SparseArray
import android.view.*
import androidx.appcompat.widget.Toolbar
import androidx.core.util.forEach
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
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.events.EventTreatmentUpdateGui
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.FabricPrivacy
import info.nightscout.androidaps.utils.T
@ -40,13 +41,14 @@ import info.nightscout.androidaps.extensions.friendlyDescription
import info.nightscout.androidaps.extensions.highValueToUnitsToString
import info.nightscout.androidaps.extensions.lowValueToUnitsToString
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.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.Completable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@ -65,57 +67,64 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
@Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable()
private val millsToThePast = T.days(30).msecs()
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 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 =
TreatmentsTemptargetFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.recyclerview.setHasFixedSize(true)
toolbar = activity?.findViewById(R.id.toolbar)
setHasOptionsMenu(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.refreshFromNightscout.setOnClickListener {
context?.let { context ->
OKDialog.showConfirmation(context, rh.gs(R.string.refresheventsfromnightscout) + " ?", {
uel.log(Action.TT_NS_REFRESH, Sources.Treatments)
disposable += Completable.fromAction { repository.deleteAllTempTargetEntries() }
}
private fun refreshFromNightscout() {
activity?.let { activity ->
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)
.observeOn(aapsSchedulers.main)
.subscribeBy(
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() {
val now = System.currentTimeMillis()
if (binding.showInvalidated.isChecked)
repository
.getTemporaryTargetDataIncludingInvalidFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
else
repository
.getTemporaryTargetDataFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
disposable +=
if (showInvalidated)
repository
.getTemporaryTargetDataIncludingInvalidFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
else
repository
.getTemporaryTargetDataFromTime(now - millsToThePast, false)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
}
@Synchronized
@ -145,6 +154,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
removeActionMode?.let { it.finish() }
binding.recyclerview.adapter = null // avoid leaks
_binding = null
}
@ -163,8 +173,19 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
val tempTarget = tempTargetList[position]
holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
holder.binding.remove.visibility = tempTarget.isValid.toVisibility()
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position-1].timestamp)
holder.binding.cbRemove.visibility = (tempTarget.isValid && removeActionMode != null).toVisibility()
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.text = dateUtil.dateString(tempTarget.timestamp)
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.timestamp > dateUtil.now() -> rh.gc(R.color.colorScheduled)
else -> holder.binding.reasonColon.currentTextColor
})
holder.binding.remove.tag = tempTarget
}
)
val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L
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) {
val binding = TreatmentsTemptargetItemBinding.bind(view)
init {
binding.remove.setOnClickListener { v: View ->
val tempTarget = v.tag as TemporaryTarget
context?.let { context ->
OKDialog.showConfirmation(context, rh.gs(R.string.removerecord),
"""
${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)}
${dateUtil.dateAndTimeString(tempTarget.timestamp)}
""".trimIndent(),
{ _: DialogInterface?, _: Int ->
uel.log(Action.TT_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(tempTarget.timestamp),
ValueWithUnit.TherapyEventTTReason(tempTarget.reason),
ValueWithUnit.Mgdl(tempTarget.lowTarget),
ValueWithUnit.Mgdl(tempTarget.highTarget).takeIf { tempTarget.lowTarget != tempTarget.highTarget },
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tempTarget.duration).toInt()))
disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id))
.subscribe(
{ aapsLogger.debug(LTag.DATABASE, "Removed temp target $tempTarget") },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it) })
}, null)
}
}
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
}
}
}
private fun removeSelected() {
if (selectedItems.size() > 0)
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
selectedItems.forEach { _, tempTarget ->
uel.log(
Action.TT_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(tempTarget.timestamp),
ValueWithUnit.TherapyEventTTReason(tempTarget.reason),
ValueWithUnit.Mgdl(tempTarget.lowTarget),
ValueWithUnit.Mgdl(tempTarget.highTarget).takeIf { tempTarget.lowTarget != tempTarget.highTarget },
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tempTarget.duration).toInt())
)
disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id))
.subscribe(
{ aapsLogger.debug(LTag.DATABASE, "Removed temp target $tempTarget") },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it) })
}
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
}
}
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())
}
}

View file

@ -1,11 +1,11 @@
package info.nightscout.androidaps.activities.fragments
import android.content.DialogInterface
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.util.Log
import android.util.SparseArray
import android.view.*
import androidx.appcompat.widget.Toolbar
import androidx.core.util.forEach
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
@ -36,14 +36,15 @@ import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
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.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.math.abs
@ -64,18 +65,22 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
@Inject lateinit var repository: AppRepository
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()
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private var selectedItems: SparseArray<TemporaryBasal> = 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 =
TreatmentsTempbasalsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
toolbar = activity?.findViewById(R.id.toolbar)
setHasOptionsMenu(true)
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
}
@ -98,7 +103,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
val now = System.currentTimeMillis()
disposable +=
if (activePlugin.activePump.isFakingTempsByExtendedBoluses) {
if (binding.showInvalidated.isChecked)
if (showInvalidated)
tempBasalsWithInvalid(now)
.zipWith(extendedBolusesWithInvalid(now)) { first, second -> first + second }
.map { list -> list.filterNotNull() }
@ -113,7 +118,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
} else {
if (binding.showInvalidated.isChecked)
if (showInvalidated)
tempBasalsWithInvalid(now)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) }
@ -150,6 +155,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
removeActionMode?.let { it.finish() }
binding.recyclerview.adapter = null // avoid leaks
_binding = null
}
@ -164,7 +170,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
holder.binding.ns.visibility = (tempBasal.interfaceIDs.nightscoutId != null).toVisibility()
holder.binding.invalid.visibility = tempBasal.isValid.not().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.text = dateUtil.dateString(tempBasal.timestamp)
if (tempBasal.isInProgress) {
@ -187,62 +193,147 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
holder.binding.emulatedSuspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.EMULATED_PUMP_SUSPEND).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)
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
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) {
val binding = TreatmentsTempbasalsItemBinding.bind(itemView)
init {
binding.remove.setOnClickListener { v: View ->
val tempBasal = v.tag as TemporaryBasal
var extendedBolus: ExtendedBolus? = null
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
if (isFakeExtended) {
val eb = repository.getExtendedBolusActiveAt(tempBasal.timestamp).blockingGet()
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) {
uel.log(Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(extendedBolus.timestamp),
ValueWithUnit.Insulin(extendedBolus.amount),
ValueWithUnit.UnitPerHour(extendedBolus.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt()))
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
.subscribe(
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
} else if (!isFakeExtended) {
uel.log(Action.TEMP_BASAL_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(tempBasal.timestamp),
if (tempBasal.isAbsolute) ValueWithUnit.UnitPerHour(tempBasal.rate) else ValueWithUnit.Percent(tempBasal.rate.toInt()),
ValueWithUnit.Minute(T.msecs(tempBasal.duration).mins().toInt()))
disposable += repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(tempBasal.id))
.subscribe(
{ aapsLogger.debug(LTag.DATABASE, "Removed temporary basal $tempBasal") },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) })
}
}, null)
}
}
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
}
}
}
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
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
if (isFakeExtended) {
val eb = repository.getExtendedBolusActiveAt(tempBasal.timestamp).blockingGet()
extendedBolus = if (eb is ValueWrapper.Existing) eb.value else null
}
if (isFakeExtended && extendedBolus != null) {
uel.log(
Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(extendedBolus.timestamp),
ValueWithUnit.Insulin(extendedBolus.amount),
ValueWithUnit.UnitPerHour(extendedBolus.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt())
)
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
.subscribe(
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
} else if (!isFakeExtended) {
uel.log(
Action.TEMP_BASAL_REMOVED, Sources.Treatments,
ValueWithUnit.Timestamp(tempBasal.timestamp),
if (tempBasal.isAbsolute) ValueWithUnit.UnitPerHour(tempBasal.rate) else ValueWithUnit.Percent(tempBasal.rate.toInt()),
ValueWithUnit.Minute(T.msecs(tempBasal.duration).mins().toInt())
)
disposable += repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(tempBasal.id))
.subscribe(
{ aapsLogger.debug(LTag.DATABASE, "Removed temporary basal $tempBasal") },
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) })
}
}
removeActionMode?.finish()
})
}
else
removeActionMode?.finish()
}
}

View file

@ -1,9 +1,7 @@
package info.nightscout.androidaps.activities.fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.*
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment
@ -29,7 +27,8 @@ import info.nightscout.androidaps.utils.userEntry.UserEntryPresentationHelper
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@ -51,11 +50,10 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
private val millsToThePastFiltered = T.days(30).msecs()
private val millsToThePastUnFiltered = T.days(3).msecs()
private var showLoop = false
private var _binding: TreatmentsUserEntryFragmentBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
@ -63,35 +61,33 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
binding.ueExportToXml.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.ue_export_to_csv) + "?") {
uel.log(Action.EXPORT_CSV, Sources.Treatments)
importExportPrefs.exportUserEntriesCsv(activity)
}
}
fun exportUserEnteries() {
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.ue_export_to_csv) + "?") {
uel.log(Action.EXPORT_CSV, Sources.Treatments)
importExportPrefs.exportUserEntriesCsv(activity)
}
}
binding.showLoop.setOnCheckedChangeListener { _, _ ->
rxBus.send(EventTreatmentUpdateGui())
}
}
fun swapAdapter() {
val now = System.currentTimeMillis()
if (binding.showLoop.isChecked)
disposable.add( repository
.getUserEntryDataFromTime(now - millsToThePastUnFiltered)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) }
)
else
disposable.add( repository
.getUserEntryFilteredDataFromTime(now - millsToThePastFiltered)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) }
)
disposable +=
if (showLoop)
repository
.getUserEntryDataFromTime(now - millsToThePastUnFiltered)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) }
else
repository
.getUserEntryFilteredDataFromTime(now - millsToThePastFiltered)
.observeOn(aapsSchedulers.main)
.subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) }
}
@Synchronized
@ -99,15 +95,15 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
super.onResume()
swapAdapter()
disposable.add(rxBus
disposable += rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ swapAdapter() }, fabricPrivacy::logException))
disposable.add(rxBus
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventTreatmentUpdateGui::class.java)
.observeOn(aapsSchedulers.io)
.debounce(1L, TimeUnit.SECONDS)
.subscribe({ swapAdapter() }, fabricPrivacy::logException))
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
}
@Synchronized
@ -132,7 +128,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) {
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.text = dateUtil.dateString(current.timestamp)
holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp)
@ -152,7 +148,40 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
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
}
}

View file

@ -7,7 +7,7 @@ import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
import io.reactivex.disposables.Disposable
import io.reactivex.rxjava3.disposables.Disposable
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -28,8 +28,8 @@ import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DecimalFormat
import java.util.*
import java.util.concurrent.TimeUnit

View file

@ -31,8 +31,8 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.extensions.fromConstant
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DecimalFormat
import java.util.*
import javax.inject.Inject

View file

@ -29,8 +29,8 @@ import info.nightscout.shared.SafeParse
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.*
import javax.inject.Inject
import kotlin.math.abs

View file

@ -30,8 +30,8 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.toSignedString
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.SafeParse
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DecimalFormat
import java.util.*
import java.util.concurrent.TimeUnit

View file

@ -40,8 +40,8 @@ import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
class LoopDialog : DaggerDialogFragment() {

View file

@ -32,8 +32,8 @@ import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DecimalFormat
import java.util.*
import java.util.concurrent.TimeUnit
@ -143,7 +143,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
binding.reusebutton.text = rh.gs(R.string.reuse_profile_pct_hours, profile.value.originalPercentage, T.msecs(profile.value.originalTimeshift).hours().toInt())
binding.reusebutton.setOnClickListener {
binding.percentage.value = profile.value.originalPercentage.toDouble()
binding.timeshift.value = profile.value.originalTimeshift.toDouble()
binding.timeshift.value = T.msecs(profile.value.originalTimeshift).hours().toDouble()
}
}
}

View file

@ -28,8 +28,8 @@ import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DecimalFormat
import java.util.*
import java.util.concurrent.TimeUnit

View file

@ -31,8 +31,8 @@ import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DecimalFormat
import java.util.*
import javax.inject.Inject

View file

@ -33,7 +33,7 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.androidaps.utils.wizard.BolusWizard
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import java.text.DecimalFormat
import java.util.*
import javax.inject.Inject
@ -125,7 +125,9 @@ class WizardDialog : DaggerDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
loadCheckedStates()
processCobCheckBox()
binding.sbCheckbox.visibility = sp.getBoolean(R.string.key_usesuperbolus, false).toVisibility()
val useSuperBolus = sp.getBoolean(R.string.key_usesuperbolus, false)
binding.sbCheckbox.visibility = useSuperBolus.toVisibility()
binding.superBolusRow.visibility = useSuperBolus.toVisibility()
binding.notesLayout.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value()
@ -146,7 +148,7 @@ class WizardDialog : DaggerDialogFragment() {
if (correctionPercent) {
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble()
binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
binding.correctionInput.value = calculatedPercentage
binding.correctionUnit.text = "%"
} else {
@ -175,9 +177,10 @@ class WizardDialog : DaggerDialogFragment() {
dismiss()
}
binding.bgCheckboxIcon.setOnClickListener { binding.bgCheckbox.isChecked = !binding.bgCheckbox.isChecked }
binding.ttCheckboxIcon.setOnClickListener { binding.ttCheckbox.isChecked = !binding.ttCheckbox.isChecked }
binding.trendCheckboxIcon.setOnClickListener { binding.bgTrendCheckbox.isChecked = !binding.bgTrendCheckbox.isChecked }
binding.cobCheckboxIcon.setOnClickListener { binding.cobCheckbox.isChecked = !binding.cobCheckbox.isChecked; processCobCheckBox(); }
binding.iobCheckboxIcon.setOnClickListener { if (!binding.cobCheckbox.isChecked) binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked }
binding.iobCheckboxIcon.setOnClickListener { binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked; processIobCheckBox(); }
// cancel button
binding.okcancel.cancel.setOnClickListener {
aapsLogger.debug(LTag.APS, "Dialog canceled: ${this.javaClass.name}")
@ -212,7 +215,7 @@ class WizardDialog : DaggerDialogFragment() {
binding.correctionUnit.text = if (isChecked) "%" else rh.gs(R.string.insulin_unit_shortname)
correctionPercent = binding.correctionPercent.isChecked
if (correctionPercent) {
binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
binding.correctionInput.customContentDescription = rh.gs(R.string.a11_correction_percentage)
} else {
binding.correctionInput.setParams(
@ -265,35 +268,42 @@ class WizardDialog : DaggerDialogFragment() {
private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) {
saveCheckedStates()
binding.ttCheckbox.isEnabled = binding.bgCheckbox.isChecked && repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
binding.ttCheckboxIcon.visibility = binding.ttCheckbox.isEnabled.toVisibility()
if (buttonView.id == binding.cobCheckbox.id)
processCobCheckBox()
if (buttonView.id == binding.iobCheckbox.id)
processIobCheckBox()
processEnabledIcons()
calculateInsulin()
}
private fun processCobCheckBox() {
if (binding.cobCheckbox.isChecked) {
binding.iobCheckbox.isEnabled = false
binding.iobCheckboxIcon.isEnabled = false
binding.iobCheckbox.isChecked = true
} else {
binding.iobCheckbox.isEnabled = true
binding.iobCheckboxIcon.isEnabled = true
}
}
private fun processIobCheckBox() {
if (!binding.iobCheckbox.isChecked) {
binding.cobCheckbox.isChecked = false
}
}
private fun processEnabledIcons() {
binding.bgCheckboxIcon.isChecked = binding.bgCheckbox.isChecked
binding.ttCheckboxIcon.isChecked = binding.ttCheckbox.isChecked
binding.trendCheckboxIcon.isChecked = binding.bgTrendCheckbox.isChecked
binding.iobCheckboxIcon.isChecked = binding.iobCheckbox.isChecked
binding.cobCheckboxIcon.isChecked = binding.cobCheckbox.isChecked
binding.bgCheckboxIcon.alpha = if (binding.bgCheckbox.isChecked) 1.0f else 0.2f
binding.ttCheckboxIcon.alpha = if (binding.ttCheckbox.isChecked) 1.0f else 0.2f
binding.trendCheckboxIcon.alpha = if (binding.bgTrendCheckbox.isChecked) 1.0f else 0.2f
binding.iobCheckboxIcon.alpha = if (binding.iobCheckbox.isChecked) 1.0f else 0.2f
binding.cobCheckboxIcon.alpha = if (binding.cobCheckbox.isChecked) 1.0f else 0.2f
binding.bgCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.ttCheckboxIcon.visibility = (binding.calculationCheckbox.isChecked.not() && binding.ttCheckbox.isEnabled).toVisibility()
binding.trendCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.iobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
binding.cobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
@ -345,7 +355,9 @@ class WizardDialog : DaggerDialogFragment() {
// Set BG if not old
binding.bgInput.value = iobCobCalculator.ads.actualBg()?.valueToUnits(units) ?: 0.0
binding.ttCheckbox.isEnabled = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
binding.ttCheckboxIcon.visibility = binding.ttCheckbox.isEnabled.toVisibility()
// IOB calculation
val bolusIob = iobCobCalculator.calculateIobFromBolus().round()

View file

@ -19,8 +19,8 @@ import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
class LoopFragment : DaggerFragment() {

View file

@ -59,8 +59,8 @@ import info.nightscout.androidaps.plugins.aps.events.EventLoopInvoked
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.abs

View file

@ -18,8 +18,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.JSONFormatter
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONArray
import org.json.JSONException
import javax.inject.Inject

View file

@ -20,8 +20,8 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONArray
import org.json.JSONException
import javax.inject.Inject

View file

@ -258,9 +258,9 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri
this.mealData.put("lastBolusTime", mealData.lastBolusTime)
this.mealData.put("lastCarbTime", mealData.lastCarbTime)
this.mealData.put("TDDAIMI7", tddCalculator.averageTDD(tddCalculator.calculate(7)).totalAmount)
this.mealData.put("TDDAIMI7", tddCalculator.averageTDD(tddCalculator.calculate(7))?.totalAmount)
this.mealData.put("TDDPUMP", tddCalculator.calculateDaily().totalAmount)
this.mealData.put("TDDLast24", tddCalculator!!.calculate24Daily().totalAmount)
this.mealData.put("TDDLast24", tddCalculator.calculate24Daily().totalAmount)
if (constraintChecker.isAutosensModeEnabled().value()) {
autosensData.put("ratio", autosensDataRatio)

View file

@ -65,6 +65,7 @@ class OpenAPSSMBDynamicISFPlugin @Inject constructor(
pluginDescription
.pluginName(R.string.openaps_smb_dynamic_isf)
.description(R.string.description_smb_dynamic_isf)
.shortName(R.string.dynisf_shortname)
.setDefault(false)
}

View file

@ -19,13 +19,13 @@ import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.events.EventConfigBuilderUpdateGui
import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.kotlin.plusAssign
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import java.util.*
import javax.inject.Inject

View file

@ -22,8 +22,8 @@ import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -12,8 +12,8 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.abs

View file

@ -37,11 +37,11 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.SntpClient
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.kotlin.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import javax.inject.Inject
class ObjectivesFragment : DaggerFragment() {

View file

@ -9,6 +9,7 @@ import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.OpenAPSSMBDynamicISFPlugin
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
@ -36,6 +37,7 @@ class SafetyPlugin @Inject constructor(
private val constraintChecker: ConstraintChecker,
private val openAPSAMAPlugin: OpenAPSAMAPlugin,
private val openAPSSMBPlugin: OpenAPSSMBPlugin,
private val OpenAPSSMBDynamicISFPlugin: OpenAPSSMBDynamicISFPlugin,
private val sensitivityOref1Plugin: SensitivityOref1Plugin,
private val activePlugin: ActivePlugin,
private val hardLimits: HardLimits,
@ -188,10 +190,12 @@ class SafetyPlugin @Inject constructor(
override fun applyMaxIOBConstraints(maxIob: Constraint<Double>): Constraint<Double> {
val apsMode = sp.getString(R.string.key_aps_mode, "open")
val maxIobPref: Double = if (openAPSSMBPlugin.isEnabled()) sp.getDouble(R.string.key_openapssmb_max_iob, 3.0) else sp.getDouble(R.string.key_openapsma_max_iob, 1.5)
val maxIobPref: Double = if (openAPSSMBPlugin.isEnabled() || OpenAPSSMBDynamicISFPlugin.isEnabled()) sp.getDouble(R.string.key_openapssmb_max_iob, 3.0) else sp.getDouble(R.string
.key_openapsma_max_iob, 1.5)
maxIob.setIfSmaller(aapsLogger, maxIobPref, String.format(rh.gs(R.string.limitingiob), maxIobPref, rh.gs(R.string.maxvalueinpreferences)), this)
if (openAPSAMAPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobAMA(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobAMA(), rh.gs(R.string.hardlimit)), this)
if (openAPSSMBPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this)
if (OpenAPSSMBDynamicISFPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this)
if (apsMode == "lgs") maxIob.setIfSmaller(aapsLogger, HardLimits.MAX_IOB_LGS, String.format(rh.gs(R.string.limitingiob), HardLimits.MAX_IOB_LGS, rh.gs(R.string.lowglucosesuspend)), this)
return maxIob
}
@ -207,4 +211,4 @@ class SafetyPlugin @Inject constructor(
configuration.storeDouble(R.string.key_treatmentssafety_maxbolus, sp, rh)
configuration.storeInt(R.string.key_treatmentssafety_maxcarbs, sp, rh)
}
}
}

View file

@ -49,8 +49,8 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.androidaps.utils.ui.SingleClickButton
import info.nightscout.androidaps.utils.ui.UIRunnable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.*
import javax.inject.Inject

View file

@ -25,7 +25,7 @@ import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -36,10 +36,10 @@ import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.ui.UIRunnable
import io.reactivex.Completable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject

View file

@ -29,9 +29,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.eros.history.database.Ero
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.Completable.fromAction
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.rxjava3.core.Completable.fromAction
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.subscribeBy
import javax.inject.Inject
class MaintenanceFragment : DaggerFragment() {

View file

@ -310,7 +310,7 @@ class NSClientAddUpdateWorker(
} ?: aapsLogger.error("Error parsing TherapyEvent json $json")
}
eventType == TherapyEvent.Type.COMBO_BOLUS.text ->
if (config.NSCLIENT) {
if (buildHelper.isEngineeringMode() && sp.getBoolean(R.string.key_ns_receive_tbr_eb, false) || config.NSCLIENT) {
extendedBolusFromJson(json)?.let { extendedBolus ->
repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus))
.doOnError {
@ -356,7 +356,7 @@ class NSClientAddUpdateWorker(
} ?: aapsLogger.error("Error parsing ExtendedBolus json $json")
}
eventType == TherapyEvent.Type.TEMPORARY_BASAL.text ->
if (config.NSCLIENT) {
if (buildHelper.isEngineeringMode() && sp.getBoolean(R.string.key_ns_receive_tbr_eb, false) || config.NSCLIENT) {
temporaryBasalFromJson(json)?.let { temporaryBasal ->
repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal))
.doOnError {

View file

@ -21,8 +21,8 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
class NSClientFragment : DaggerFragment() {

View file

@ -38,7 +38,7 @@ import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@ -159,6 +159,7 @@ class NSClientPlugin @Inject constructor(
// preferenceFragment.findPreference<SwitchPreference>(rh.gs(R.string.key_ns_receive_carbs))?.isVisible = buildHelper.isEngineeringMode()
// preferenceFragment.findPreference<SwitchPreference>(rh.gs(R.string.key_ns_receive_temp_target))?.isVisible = buildHelper.isEngineeringMode()
}
preferenceFragment.findPreference<SwitchPreference>(rh.gs(R.string.key_ns_receive_tbr_eb))?.isVisible = buildHelper.isEngineeringMode()
}
private val mConnection: ServiceConnection = object : ServiceConnection {

View file

@ -49,7 +49,7 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.socket.client.IO
import io.socket.client.Socket
import io.socket.emitter.Emitter

View file

@ -78,8 +78,8 @@ import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.androidaps.utils.ui.SingleClickButton
import info.nightscout.androidaps.utils.ui.UIRunnable
import info.nightscout.androidaps.utils.wizard.QuickWizard
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject

View file

@ -24,8 +24,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONObject
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
@ -12,26 +13,30 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.ItemTouchHelper.*
import androidx.recyclerview.widget.ItemTouchHelper.ACTION_STATE_DRAG
import androidx.recyclerview.widget.ItemTouchHelper.DOWN
import androidx.recyclerview.widget.ItemTouchHelper.END
import androidx.recyclerview.widget.ItemTouchHelper.START
import androidx.recyclerview.widget.ItemTouchHelper.UP
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
import info.nightscout.androidaps.databinding.OverviewQuickwizardlistActivityBinding
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWizardDialog
import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.rxkotlin.plusAssign
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
class QuickWizardListActivity : NoSplashAppCompatActivity() {
class QuickWizardListActivity : DaggerAppCompatActivityWithResult() {
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var rxBus: RxBus
@ -176,6 +181,10 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
binding = OverviewQuickwizardlistActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
title = rh.gs(R.string.quickwizard)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
binding.recyclerview.setHasFixedSize(true)
binding.recyclerview.layoutManager = LinearLayoutManager(this)
binding.recyclerview.adapter = RecyclerViewAdapter(supportFragmentManager)
@ -203,4 +212,14 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() {
disposable.clear()
super.onPause()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean =
when (item.itemId) {
android.R.id.home -> {
finish()
true
}
else -> false
}
}

View file

@ -105,7 +105,8 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.from.setOnClickListener {
context?.let {
TimePickerDialog(
it, fromTimeSetListener,
it, R.style.MaterialPickerTheme,
fromTimeSetListener,
T.secs(fromSeconds.toLong()).hours().toInt(),
T.secs((fromSeconds % 3600).toLong()).mins().toInt(),
DateFormat.is24HourFormat(context)
@ -123,7 +124,8 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
binding.to.setOnClickListener {
context?.let {
TimePickerDialog(
it, toTimeSetListener,
it, R.style.MaterialPickerTheme,
toTimeSetListener,
T.secs(toSeconds.toLong()).hours().toInt(),
T.secs((toSeconds % 3600).toLong()).mins().toInt(),
DateFormat.is24HourFormat(context)

View file

@ -13,7 +13,7 @@ import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import javax.inject.Inject
/**

View file

@ -20,8 +20,8 @@ import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -11,9 +11,9 @@ import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSm
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.kotlin.plusAssign
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import java.util.*
import javax.inject.Inject
import kotlin.math.max

View file

@ -48,8 +48,8 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.androidaps.utils.textValidator.ValidatingEditTextPreference
import info.nightscout.shared.SafeParse
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import org.apache.commons.lang3.StringUtils
import org.joda.time.DateTime
import java.text.Normalizer
@ -67,7 +67,7 @@ class SmsCommunicatorPlugin @Inject constructor(
injector: HasAndroidInjector,
aapsLogger: AAPSLogger,
rh: ResourceHelper,
private val smsManager: SmsManager,
private val smsManager: SmsManager?,
private val aapsSchedulers: AapsSchedulers,
private val sp: SP,
private val constraintChecker: ConstraintChecker,
@ -165,7 +165,7 @@ class SmsCommunicatorPlugin @Inject constructor(
override fun updatePreferenceSummary(pref: Preference) {
super.updatePreferenceSummary(pref)
if (pref is EditTextPreference) {
if (pref.getKey().contains("smscommunicator_allowednumbers") && (pref.text == null || TextUtils.isEmpty(pref.text.trim { it <= ' ' }))) {
if (pref.getKey().contains("smscommunicator_allowednumbers") && (TextUtils.isEmpty(pref.text?.trim { it <= ' ' }))) {
pref.setSummary(rh.gs(R.string.smscommunicator_allowednumbers_summary))
}
}
@ -1100,10 +1100,10 @@ class SmsCommunicatorPlugin @Inject constructor(
sms.text = stripAccents(sms.text)
try {
aapsLogger.debug(LTag.SMS, "Sending SMS to " + sms.phoneNumber + ": " + sms.text)
if (sms.text.toByteArray().size <= 140) smsManager.sendTextMessage(sms.phoneNumber, null, sms.text, null, null)
if (sms.text.toByteArray().size <= 140) smsManager?.sendTextMessage(sms.phoneNumber, null, sms.text, null, null)
else {
val parts = smsManager.divideMessage(sms.text)
smsManager.sendMultipartTextMessage(sms.phoneNumber, null, parts,
val parts = smsManager?.divideMessage(sms.text)
smsManager?.sendMultipartTextMessage(sms.phoneNumber, null, parts,
null, null)
}
messages.add(sms)

View file

@ -14,10 +14,10 @@ import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolD
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolResetData
import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolUpdateGUI
import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.kotlin.plusAssign
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import javax.inject.Inject
class TidepoolFragment : DaggerFragment() {

View file

@ -30,11 +30,11 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.ToastUtils
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.kotlin.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@ -68,6 +68,7 @@ class TidepoolPlugin @Inject constructor(
private val listLog = ArrayList<EventTidepoolStatus>()
var textLog: Spanned = HtmlHelper.fromHtml("")
@Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS", "NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS", "UNNECESSARY_NOT_NULL_ASSERTION")
override fun onStart() {
super.onStart()
disposable += rxBus

View file

@ -42,8 +42,8 @@ import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.androidaps.utils.wizard.BolusWizard
import info.nightscout.androidaps.utils.wizard.QuickWizard
import info.nightscout.shared.SafeParse
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*

View file

@ -20,7 +20,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -15,8 +15,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -34,8 +34,8 @@ import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONArray
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledFuture

View file

@ -24,16 +24,18 @@ import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.ui.SpinnerHelper
import info.nightscout.androidaps.utils.ui.TimeListEdit
import info.nightscout.shared.SafeParse
import info.nightscout.shared.logging.AAPSLogger
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.math.RoundingMode
import java.text.DecimalFormat
import javax.inject.Inject
@ -54,12 +56,12 @@ class LocalProfileFragment : DaggerFragment() {
private var disposable: CompositeDisposable = CompositeDisposable()
private var basalView: TimeListEdit? = null
private var spinner: SpinnerHelper? = null
// private var spinner: SpinnerHelper? = null
private val save = Runnable {
doEdit()
basalView?.updateLabel(rh.gs(R.string.basal_label) + ": " + sumLabel())
localProfilePlugin.profile?.getSpecificProfile(spinner?.selectedItem.toString())?.let {
localProfilePlugin.getEditedProfile()?.let {
binding.basalGraph.show(ProfileSealed.Pure(it))
binding.icGraph.show(ProfileSealed.Pure(it))
binding.isfGraph.show(ProfileSealed.Pure(it))
@ -79,7 +81,7 @@ class LocalProfileFragment : DaggerFragment() {
}
private fun sumLabel(): String {
val profile = localProfilePlugin.getEditProfile()
val profile = localProfilePlugin.getEditedProfile()
val sum = profile?.let { ProfileSealed.Pure(profile).baseBasalSum() } ?: 0.0
return "" + DecimalFormatter.to2Decimal(sum) + rh.gs(R.string.insulin_unit_shortname)
}
@ -135,56 +137,115 @@ class LocalProfileFragment : DaggerFragment() {
binding.name.addTextChangedListener(textWatch)
binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch)
binding.dia.tag = "LP_DIA"
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic_holder, "IC", rh.gs(R.string.ic_long_label), currentProfile.ic, null, doubleArrayOf(hardLimits.minIC(), hardLimits.maxIC()), null, 0.1, DecimalFormat ("0.0"), save)
basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", rh.gs(R.string.basal_long_label) + ": " + sumLabel(), currentProfile.basal, null, doubleArrayOf(pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate), null, 0.01, DecimalFormat("0.00"), save)
TimeListEdit(
context,
aapsLogger,
dateUtil,
view,
R.id.ic_holder,
"IC",
rh.gs(R.string.ic_long_label),
currentProfile.ic,
null,
doubleArrayOf(hardLimits.minIC(), hardLimits.maxIC()),
null,
0.1,
DecimalFormat("0.0"),
save
)
basalView =
TimeListEdit(
context,
aapsLogger,
dateUtil,
view,
R.id.basal_holder,
"BASAL",
rh.gs(R.string.basal_long_label) + ": " + sumLabel(),
currentProfile.basal,
null,
doubleArrayOf(pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate),
null,
0.01,
DecimalFormat("0.00"),
save
)
if (units == Constants.MGDL) {
val isfRange = doubleArrayOf(HardLimits.MIN_ISF, HardLimits.MAX_ISF)
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null, isfRange , null, 1.0, DecimalFormat("0"), save)
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_MIN_BG, HardLimits.VERY_HARD_LIMIT_TARGET_BG, 1.0, DecimalFormat("0"), save)
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null, isfRange, null, 1.0, DecimalFormat("0"), save)
TimeListEdit(
context,
aapsLogger,
dateUtil,
view,
R.id.target_holder,
"TARGET",
rh.gs(R.string.target_long_label),
currentProfile.targetLow,
currentProfile.targetHigh,
HardLimits.VERY_HARD_LIMIT_MIN_BG,
HardLimits.VERY_HARD_LIMIT_TARGET_BG,
1.0,
DecimalFormat("0"),
save
)
} else {
val isfRange = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL)),
roundDown(Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL)))
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null,isfRange , null, 0.1, DecimalFormat("0.0"), save)
val range1 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[0], GlucoseUnit.MMOL)),
roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[1], GlucoseUnit.MMOL)))
val range2 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[0], GlucoseUnit.MMOL)),
roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[1], GlucoseUnit.MMOL)))
Log.i("TimeListEdit", "build: range1" + range1[0] + " " + range1[1] + " range2" + range2[0] + " " + range2[1])
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, range1 , range2, 0.1, DecimalFormat("0.0"), save)
val isfRange = doubleArrayOf(
roundUp(Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL)),
roundDown(Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL))
)
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null, isfRange, null, 0.1, DecimalFormat("0.0"), save)
val range1 = doubleArrayOf(
roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[0], GlucoseUnit.MMOL)),
roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[1], GlucoseUnit.MMOL))
)
val range2 = doubleArrayOf(
roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[0], GlucoseUnit.MMOL)),
roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[1], GlucoseUnit.MMOL))
)
Log.i("TimeListEdit", "build: range1" + range1[0] + " " + range1[1] + " range2" + range2[0] + " " + range2[1])
TimeListEdit(
context,
aapsLogger,
dateUtil,
view,
R.id.target_holder,
"TARGET",
rh.gs(R.string.target_long_label),
currentProfile.targetLow,
currentProfile.targetHigh,
range1,
range2,
0.1,
DecimalFormat("0.0"),
save
)
}
// Spinner
spinner = SpinnerHelper(binding.spinner)
context?.let { context ->
val profileList: ArrayList<CharSequence> = localProfilePlugin.profile?.getProfileList() ?: ArrayList()
spinner?.adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
val selection = localProfilePlugin.currentProfileIndex
if (selection in 0 until profileList.size) spinner?.setSelection(selection)
binding.profileList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, profileList))
} ?: return
spinner?.setOnItemSelectedListener(object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
if (localProfilePlugin.isEdited) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.doyouwantswitchprofile), {
binding.profileList.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
if (localProfilePlugin.isEdited) {
activity?.let { activity ->
OKDialog.showConfirmation(
activity, rh.gs(R.string.doyouwantswitchprofile),
{
localProfilePlugin.currentProfileIndex = position
localProfilePlugin.isEdited = false
build()
}, {
val selection = localProfilePlugin.currentProfileIndex
if (selection in 0 until (spinner?.adapter?.count ?: -1)) spinner?.setSelection(selection)
}
)
}
} else {
localProfilePlugin.currentProfileIndex = position
build()
}, null
)
}
} else {
localProfilePlugin.currentProfileIndex = position
build()
}
})
localProfilePlugin.profile?.getSpecificProfile(spinner?.selectedItem.toString())?.let {
}
localProfilePlugin.getEditedProfile()?.let {
binding.basalGraph.show(ProfileSealed.Pure(it))
binding.icGraph.show(ProfileSealed.Pure(it))
binding.isfGraph.show(ProfileSealed.Pure(it))
@ -206,8 +267,12 @@ class LocalProfileFragment : DaggerFragment() {
if (localProfilePlugin.isEdited) {
activity?.let { OKDialog.show(it, "", rh.gs(R.string.saveorresetchangesfirst)) }
} else {
uel.log(Action.CLONE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name
?: ""))
uel.log(
Action.CLONE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(
localProfilePlugin.currentProfile()?.name
?: ""
)
)
localProfilePlugin.cloneProfile()
build()
}
@ -216,8 +281,12 @@ class LocalProfileFragment : DaggerFragment() {
binding.profileRemove.setOnClickListener {
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(R.string.deletecurrentprofile), {
uel.log(Action.PROFILE_REMOVED, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name
?: ""))
uel.log(
Action.PROFILE_REMOVED, Sources.LocalProfile, ValueWithUnit.SimpleString(
localProfilePlugin.currentProfile()?.name
?: ""
)
)
localProfilePlugin.removeCurrentProfile()
build()
}, null)
@ -245,8 +314,12 @@ class LocalProfileFragment : DaggerFragment() {
if (!localProfilePlugin.isValidEditState(activity)) {
return@setOnClickListener //Should not happen as saveButton should not be visible if not valid
}
uel.log(Action.STORE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name
?: ""))
uel.log(
Action.STORE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(
localProfilePlugin.currentProfile()?.name
?: ""
)
)
localProfilePlugin.storeSettings(activity)
build()
}
@ -294,7 +367,7 @@ class LocalProfileFragment : DaggerFragment() {
val isEdited = localProfilePlugin.isEdited
if (isValid) {
this.view?.setBackgroundColor(rh.gc(R.color.ok_background))
binding.spinner.isEnabled = true
binding.profileList.isEnabled = true
if (isEdited) {
//edited profile -> save first
@ -306,7 +379,7 @@ class LocalProfileFragment : DaggerFragment() {
}
} else {
this.view?.setBackgroundColor(rh.gc(R.color.error_background))
binding.spinner.isEnabled = false
binding.profileList.isEnabled = false
binding.profileswitch.visibility = View.GONE
binding.save.visibility = View.GONE //don't save an invalid profile
}

View file

@ -170,7 +170,7 @@ class LocalProfilePlugin @Inject constructor(
}
@Synchronized
fun getEditProfile(): PureProfile? {
fun getEditedProfile(): PureProfile? {
val profile = JSONObject()
with(profiles[currentProfileIndex]) {
profile.put("dia", dia)

View file

@ -21,8 +21,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
class VirtualPumpFragment : DaggerFragment() {

View file

@ -28,8 +28,8 @@ import info.nightscout.androidaps.utils.TimeChangeType
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONException
import org.json.JSONObject
import javax.inject.Inject

View file

@ -34,8 +34,8 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.concurrent.TimeUnit
import javax.inject.Inject

View file

@ -26,7 +26,7 @@ import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.XDripBroadcast
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -18,8 +18,8 @@ import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.XDripBroadcast
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -41,9 +41,9 @@ import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -52,7 +52,7 @@ class QueueThread internal constructor(
val secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000
val pump = activePlugin.activePump
// Manifest.permission.BLUETOOTH_CONNECT
if (config.PUMPDRIVERS && Build.VERSION.SDK_INT >= /*Build.VERSION_CODES.S*/31)
if (config.PUMPDRIVERS && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
if (androidPermission.permissionNotGranted(context, "android.permission.BLUETOOTH_CONNECT")) {
aapsLogger.debug(LTag.PUMPQUEUE, "no permission")
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTING))

View file

@ -8,7 +8,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.events.EventStatus
import info.nightscout.androidaps.setupwizard.elements.SWItem
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import javax.inject.Inject
class SWEventListener constructor(

View file

@ -24,7 +24,7 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.locale.LocaleHelper.update
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import javax.inject.Inject
import kotlin.math.max
import kotlin.math.min

View file

@ -97,7 +97,7 @@ class AndroidPermission @Inject constructor(
@Synchronized
fun notifyForBtConnectPermission(activity: FragmentActivity) {
if (Build.VERSION.SDK_INT >= /*Build.VERSION_CODES.S*/31) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Manifest.permission.BLUETOOTH_CONNECT
if (permissionNotGranted(activity, "android.permission.BLUETOOTH_CONNECT") || permissionNotGranted(activity, "android.permission.BLUETOOTH_SCAN")) {
val notification = NotificationWithAction(injector, Notification.PERMISSION_BT, rh.gs(R.string.needconnectpermission), Notification.URGENT)

View file

@ -22,8 +22,8 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.min

View file

@ -28,7 +28,7 @@ object PrefImportSummaryDialog {
@SuppressLint("InflateParams")
fun showSummary(context: Context, importOk: Boolean, importPossible: Boolean, prefs: Prefs, ok: (() -> Unit)?, cancel: (() -> Unit)? = null) {
@StyleRes val theme: Int = if (importOk) R.style.AppTheme else {
@StyleRes val theme: Int = if (importOk) R.style.DialogTheme else {
if (importPossible) R.style.AppThemeWarningDialog else R.style.AppThemeErrorDialog
}
@ -92,7 +92,7 @@ object PrefImportSummaryDialog {
webView.setBackgroundColor(Color.TRANSPARENT)
webView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null)
AlertDialogHelper.Builder(context, R.style.AppTheme)
AlertDialogHelper.Builder(context, R.style.DialogTheme)
.setCustomTitle(
AlertDialogHelper.buildCustomTitle(
context,

View file

@ -19,7 +19,7 @@ object TwoMessagesAlertDialog {
val secondMessageLayout = LayoutInflater.from(context).inflate(R.layout.dialog_alert_two_messages, null)
(secondMessageLayout.findViewById<View>(R.id.password_prompt_title) as TextView).text = secondMessage
val dialog = AlertDialogHelper.Builder(context)
AlertDialogHelper.Builder(context, R.style.DialogTheme)
.setMessage(message)
.setCustomTitle(
AlertDialogHelper.buildCustomTitle(
@ -40,7 +40,7 @@ object TwoMessagesAlertDialog {
if (cancel != null) runOnUiThread { cancel() }
}
.show()
dialog.setCanceledOnTouchOutside(false)
.setCanceledOnTouchOutside(false)
}
}

View file

@ -6,18 +6,18 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.toText
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.toText
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
class TddCalculator @Inject constructor(
@ -76,8 +76,8 @@ class TddCalculator @Inject constructor(
return result
}
fun calculateDaily():TotalDailyDose {
val startTime = MidnightTime.calc(dateUtil.now() )
fun calculateDaily(): TotalDailyDose {
val startTime = MidnightTime.calc(dateUtil.now())
val endTime = dateUtil.now()
val tdd = TotalDailyDose(timestamp = startTime)
//val result = TotalDailyDose()
@ -118,12 +118,12 @@ class TddCalculator @Inject constructor(
tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount
//}
aapsLogger.debug(LTag.CORE, tdd.toString())
return tdd
}
fun calculate24Daily():TotalDailyDose {
val startTime = dateUtil.now() - T.hours(hour = 24).msecs()
fun calculate24Daily(): TotalDailyDose {
val startTime = dateUtil.now() - T.hours(hour = 24).msecs()
val endTime = dateUtil.now()
val tdd = TotalDailyDose(timestamp = startTime)
//val result = TotalDailyDose()
@ -142,7 +142,7 @@ class TddCalculator @Inject constructor(
//result.put(midnight, tdd)
}
val calculationStep = T.mins(5).msecs()
val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep)
//val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep)
for (t in startTime until endTime step calculationStep) {
//val midnight = MidnightTime.calc(t)
@ -165,12 +165,13 @@ class TddCalculator @Inject constructor(
tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount
//}
aapsLogger.debug(LTag.CORE, tdd.toString())
return tdd
}
fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose {
fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose? {
val totalTdd = TotalDailyDose(timestamp = dateUtil.now())
if (tdds.size() == 0) return null
for (i in 0 until tdds.size()) {
val tdd = tdds.valueAt(i)
totalTdd.basalAmount += tdd.basalAmount
@ -189,10 +190,11 @@ class TddCalculator @Inject constructor(
val tdds = calculate(7)
val averageTdd = averageTDD(tdds)
return HtmlHelper.fromHtml(
"<b>" + rh.gs(R.string.tdd) + ":</b><br>" +
if (averageTdd != null) "<b>" + rh.gs(R.string.tdd) + ":</b><br>" +
toText(tdds, true) +
"<b>" + rh.gs(R.string.average) + ":</b><br>" +
averageTdd.toText(rh, tdds.size(), true)
else ""
)
}

View file

@ -33,8 +33,8 @@ import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.*
import javax.inject.Inject
import kotlin.math.abs

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="26dp"
android:height="26dp"
android:drawable="@drawable/ic_temptarget_high" />
</layer-list>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/cb_background_tt" />
</selector>

View file

@ -5,8 +5,8 @@
android:viewportHeight="24">
<path
android:pathData="M12.069,20.423c-4.644,0 -8.422,-3.779 -8.422,-8.423s3.778,-8.422 8.422,-8.422S20.492,7.355 20.492,12S16.713,20.423 12.069,20.423zM12.069,4.943c-3.891,0 -7.057,3.166 -7.057,7.057c0,3.891 3.166,7.057 7.057,7.057c3.891,0 7.057,-3.166 7.057,-7.057C19.126,8.109 15.961,4.943 12.069,4.943z"
android:fillColor="#67DFE8"/>
android:fillColor="@color/ic_local_activate"/>
<path
android:pathData="M9.945,16.362c-0.113,0 -0.227,-0.028 -0.33,-0.085c-0.217,-0.12 -0.353,-0.349 -0.353,-0.598V8.32c0,-0.249 0.135,-0.478 0.353,-0.598c0.218,-0.12 0.485,-0.112 0.694,0.021l5.827,3.679c0.198,0.125 0.318,0.343 0.318,0.577s-0.12,0.452 -0.318,0.577l-5.827,3.679C10.198,16.326 10.072,16.362 9.945,16.362zM10.627,9.559v4.881L14.493,12L10.627,9.559z"
android:fillColor="#67DFE8"/>
android:fillColor="@color/ic_local_activate"/>
</vector>

View file

@ -5,5 +5,5 @@
android:viewportHeight="24">
<path
android:pathData="M13.787,4.15c-4.338,0 -7.867,3.529 -7.867,7.867v5.193l-2.486,-2.485c-0.25,-0.248 -0.653,-0.248 -0.902,0c-0.249,0.249 -0.249,0.653 0,0.902l3.575,3.574c0.008,0.008 0.019,0.011 0.028,0.018c0.054,0.048 0.112,0.091 0.18,0.119c0.078,0.032 0.161,0.049 0.244,0.049s0.166,-0.017 0.244,-0.049c0.068,-0.028 0.126,-0.071 0.18,-0.119c0.008,-0.008 0.019,-0.01 0.028,-0.018l3.575,-3.574c0.249,-0.249 0.249,-0.653 0,-0.902c-0.249,-0.248 -0.653,-0.248 -0.902,0l-2.486,2.485v-5.193c0,-3.635 2.957,-6.592 6.591,-6.592c3.635,0 6.592,2.957 6.592,6.592c0,1.761 -0.686,3.415 -1.931,4.66c-0.249,0.249 -0.249,0.653 0,0.902c0.25,0.248 0.652,0.248 0.902,0c1.485,-1.486 2.304,-3.461 2.304,-5.563C21.654,7.68 18.125,4.15 13.787,4.15z"
android:fillColor="#E93057"/>
android:fillColor="@color/ic_local_reset"/>
</vector>

View file

@ -27,14 +27,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_profileswitch"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_actions_profileswitch"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_profileswitch"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -42,14 +42,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_temptarget"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_temptarget_high"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_temporarytarget"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -57,14 +57,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_settempbasal"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_actions_starttempbasal"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/overview_tempbasal_button"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -72,15 +72,15 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_canceltempbasal"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_cancelbasal"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/canceltemp"
android:textSize="11sp"
android:visibility="gone"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -88,14 +88,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_extendedbolus"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_actions_startextbolus"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/overview_extendedbolus_button"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -103,15 +103,15 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_extendedbolus_cancel"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_actions_cancelextbolus"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/overview_extendedbolus_cancel_button"
android:textSize="11sp"
android:visibility="gone"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -141,14 +141,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_bgcheck"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_bgcheck"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_bgcheck"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -156,14 +156,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_fill"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_cp_pump_canula"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/primefill"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -171,13 +171,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_cgmsensorinsert"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_cgm_insert"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_cgmsensorinsert"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -185,13 +186,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_pumpbatterychange"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_pump_battery"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_pumpbatterychange"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -199,13 +201,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_note"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_note"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_note"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -213,13 +216,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_exercise"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_exercise"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_exercise"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -227,13 +231,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_announcement"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_announcement"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_announcement"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -241,13 +246,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_question"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_question"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_question"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -270,13 +276,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_historybrowser"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_pump_history"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/nav_historybrowser"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -284,14 +291,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_tddstats"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_cp_stats"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/tdd"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"

View file

@ -27,14 +27,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_profileswitch"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_actions_profileswitch"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_profileswitch"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -42,14 +42,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_temptarget"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_temptarget_high"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_temporarytarget"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -57,14 +57,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_settempbasal"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_actions_starttempbasal"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/overview_tempbasal_button"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -72,15 +72,15 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_canceltempbasal"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_cancelbasal"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/canceltemp"
android:textSize="11sp"
android:visibility="gone"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -88,14 +88,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_extendedbolus"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_actions_startextbolus"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/overview_extendedbolus_button"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -103,15 +103,15 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_extendedbolus_cancel"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_actions_cancelextbolus"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/overview_extendedbolus_cancel_button"
android:textSize="11sp"
android:visibility="gone"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -141,14 +141,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_bgcheck"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_bgcheck"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_bgcheck"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -156,14 +156,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_fill"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_cp_pump_canula"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/primefill"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -171,13 +171,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_cgmsensorinsert"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_cgm_insert"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_cgmsensorinsert"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -185,13 +186,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_pumpbatterychange"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_pump_battery"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_pumpbatterychange"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -199,13 +201,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_note"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_note"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_note"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -213,13 +216,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_exercise"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_exercise"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_exercise"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -227,13 +231,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_announcement"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_announcement"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_announcement"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -241,13 +246,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_question"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:drawableTop="@drawable/ic_cp_question"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/careportal_question"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -270,13 +276,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_historybrowser"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_pump_history"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/nav_historybrowser"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
@ -284,14 +291,14 @@
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/actions_tddstats"
style="@style/ButtonSmallFontStyle"
style="?android:attr/buttonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_cp_stats"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:text="@string/tdd"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"

View file

@ -33,8 +33,9 @@
android:layout_height="match_parent"
app:srcCompat="@drawable/ic_chevron_left_black_24dp" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/date"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
@ -52,8 +53,9 @@
android:layout_height="match_parent"
app:srcCompat="@drawable/ic_last_page_black_24dp" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/zoom"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"

View file

@ -62,21 +62,21 @@
android:layout_gravity="center_vertical"
android:paddingBottom="8dp">
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/reset"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginEnd="8dp"
style="@style/mdtp_ActionButton.Text"
style="@style/OkCancelButton.Text"
android:text="@string/resettodefaults" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
style="@style/mdtp_ActionButton.Text"
android:text="@string/mdtp_ok" />
style="@style/OkCancelButton.Text"
android:text="@string/ok" />
</LinearLayout>

View file

@ -21,7 +21,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
app:tabIndicatorColor="#FFFFFF"
app:tabIndicatorColor="@color/tabSelectedTextColor"
app:tabTextColor="@color/tabTextColor"
app:tabSelectedTextColor="@color/tabSelectedTextColor"
app:tabMode="scrollable" />
<com.google.android.material.tabs.TabLayout
@ -31,8 +33,11 @@
android:background="@android:color/transparent"
app:tabMinWidth="0dp"
app:tabPadding="0dp"
app:tabIndicatorColor="#FFFFFF"
app:tabIndicatorColor="@color/tabSelectedTextColor"
app:tabTextColor="@color/tabTextColor"
app:tabSelectedTextColor="@color/tabSelectedTextColor"
app:tabMode="scrollable" />
</androidx.appcompat.widget.Toolbar>
<androidx.drawerlayout.widget.DrawerLayout

View file

@ -78,21 +78,21 @@
android:layout_gravity="center_vertical"
android:paddingBottom="8dp">
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/reset"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginEnd="8dp"
style="@style/mdtp_ActionButton.Text"
style="@style/OkCancelButton.Text"
android:text="@string/reset" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
style="@style/mdtp_ActionButton.Text"
android:text="@string/mdtp_ok" />
style="@style/OkCancelButton.Text"
android:text="@string/ok" />
</LinearLayout>

View file

@ -14,6 +14,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
style="@style/mdtp_ActionButton.Text"
style="@style/OkCancelButton.Text"
android:text="@string/close" />
</LinearLayout>

View file

@ -5,11 +5,12 @@
android:gravity="center"
android:orientation="vertical">
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/unlock"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:layout_gravity="center"
android:text="@string/unlock_settings" />
<androidx.core.widget.NestedScrollView

View file

@ -21,17 +21,17 @@
android:layout_marginEnd="8dp"
android:stretchColumns="2" />
<Button
<com.google.android.material.button.MaterialButton
style="@style/GrayButton"
android:id="@+id/summary_details_btn"
style="?android:attr/buttonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="bottom"
android:gravity="center"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="3dp"
android:layout_marginBottom="10dp"
android:text="@string/check_preferences_details_btn"
android:textColor="@color/colorTreatmentButton"
android:visibility="gone" />

View file

@ -215,26 +215,33 @@
android:orientation="horizontal"
android:padding="5dp">
<Button
<com.google.android.material.button.MaterialButton
style="@style/GrayButton"
android:id="@+id/plus1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="+5" />
android:text="+5"
tools:ignore="HardcodedText" />
<Button
<com.google.android.material.button.MaterialButton
style="@style/GrayButton"
android:id="@+id/plus2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="+10" />
android:text="+10"
tools:ignore="HardcodedText" />
<Button
<com.google.android.material.button.MaterialButton
style="@style/GrayButton"
android:id="@+id/plus3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="+20" />
android:text="+20"
tools:ignore="HardcodedText" />
</LinearLayout>

View file

@ -105,22 +105,25 @@
android:layout_height="wrap_content"
android:padding="5dp">
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/fill_preset_button1"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="0.3U" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/fill_preset_button2"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="0.7U" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/fill_preset_button3"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"

View file

@ -146,22 +146,25 @@
android:orientation="horizontal"
android:padding="5dp">
<Button
<com.google.android.material.button.MaterialButton
style="@style/GrayButton"
android:id="@+id/plus05"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:contentDescription="Increment insuline with 0.5"
android:contentDescription="Increment insulin with 0.5"
android:text="+0.5" />
<Button
<com.google.android.material.button.MaterialButton
style="@style/GrayButton"
android:id="@+id/plus10"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="+1.0" />
<Button
<com.google.android.material.button.MaterialButton
style="@style/GrayButton"
android:id="@+id/plus20"
android:layout_width="match_parent"
android:layout_height="match_parent"

View file

@ -395,14 +395,14 @@
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/cancel"
style="@style/mdtp_ActionButton.Text"
style="@style/OkCancelButton.Text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:text="@string/mdtp_cancel"
android:text="@string/cancel"
android:padding="10dp"
android:textAlignment="textEnd" />

View file

@ -240,12 +240,12 @@
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|center_vertical"
android:layout_marginTop="0dp"
android:layout_marginTop="10dp"
android:background="@android:color/transparent"
android:orientation="horizontal"
android:padding="0dp">
@ -254,53 +254,67 @@
android:id="@+id/bg_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.7"
android:scaleY="0.7"
android:button="@drawable/checkbox_bg_icon"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:button="@android:color/transparent"
android:checked="true"
android:contentDescription="@string/treatments_wizard_bg_label" />
android:contentDescription="@string/treatments_wizard_bg_label"
android:drawableStart="@drawable/checkbox_bg_icon"
android:scaleX="1.4"
android:scaleY="1.4" />
<CheckBox
android:id="@+id/tt_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:button="@android:color/transparent"
android:checked="true"
android:contentDescription="@string/treatments_wizard_tt_label"
android:drawableStart="@drawable/checkbox_tt_icon"
android:scaleX="1.6"
android:scaleY="1.6"
android:visibility="gone" />
<CheckBox
android:id="@+id/trend_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.7"
android:scaleY="0.7"
android:button="@drawable/checkbox_trend_icon"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:button="@android:color/transparent"
android:checked="true"
android:contentDescription="@string/bg_trend_label" />
android:contentDescription="@string/bg_trend_label"
android:drawableStart="@drawable/checkbox_trend_icon"
android:scaleX="1.4"
android:scaleY="1.4" />
<CheckBox
android:id="@+id/iob_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.9"
android:scaleY="0.9"
android:button="@drawable/checkbox_iob_icon"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:button="@android:color/transparent"
android:checked="true"
android:contentDescription="@string/iob" />
android:contentDescription="@string/iob"
android:drawableStart="@drawable/checkbox_iob_icon"
android:scaleX="1.4"
android:scaleY="1.4" />
<CheckBox
android:id="@+id/cob_checkbox_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:scaleX="0.7"
android:scaleY="0.7"
android:button="@drawable/checkbox_cob_icon"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:button="@android:color/transparent"
android:checked="true"
android:contentDescription="@string/treatments_wizard_cob_label" />
android:contentDescription="@string/treatments_wizard_cob_label"
android:drawableStart="@drawable/checkbox_cob_icon"
android:scaleX="1.6"
android:scaleY="1.6" />
</LinearLayout>
@ -323,7 +337,7 @@
android:contentDescription="@string/show_calculation"
android:drawableEnd="@drawable/ic_visibility" />
<include
<include
android:id="@+id/okcancel"
layout="@layout/okcancel" />
@ -614,6 +628,7 @@
</TableRow>
<TableRow
android:id="@+id/super_bolus_row"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true">

View file

@ -488,13 +488,13 @@
android:layout_gravity="center_vertical"
android:paddingBottom="8dp">
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
style="@style/mdtp_ActionButton.Text"
android:text="@string/mdtp_ok" />
style="@style/OkCancelButton.Text"
android:text="@string/ok" />
</LinearLayout>
</LinearLayout>

View file

@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="?android:colorBackground">
card_view:cardBackgroundColor="@color/cardColorBackground">
<LinearLayout
android:id="@+id/food_item"

View file

@ -10,38 +10,25 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="start"
android:orientation="horizontal">
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:hint="@string/select_profile"
android:textColorHint="@color/white"
app:boxStrokeColor="@color/list_delimiter">
<TextView
android:layout_width="wrap_content"
<androidx.appcompat.widget.AppCompatAutoCompleteTextView
android:id="@+id/profileList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:labelFor="@+id/spinner"
android:text="@string/selected_profile"
android:textAppearance="?android:attr/textAppearanceMedium" />
android:clickable="true"
android:enabled="false"
tools:ignore="KeyboardInaccessibleWidget" />
<Spinner
android:id="@+id/spinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_weight="1" />
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@color/list_delimiter" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
@ -217,7 +204,7 @@
android:layout_height="40dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp"
app:customContentDescription="@string/dia" />
app:customContentDescription="@string/dia" />
<TextView
android:layout_width="wrap_content"
@ -320,21 +307,20 @@
</LinearLayout>
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/profileswitch"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="1"
android:drawableStart="@drawable/ic_local_activate"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/activate_profile" />
android:text="@string/activate_profile"
app:icon="@drawable/ic_local_activate"
app:iconTint="@color/ic_local_activate" />
<LinearLayout
android:layout_width="match_parent"
@ -342,37 +328,35 @@
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/reset"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:drawableStart="@drawable/ic_local_reset"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/reset" />
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:text="@string/reset"
app:icon="@drawable/ic_local_reset"
app:iconTint="@color/ic_local_reset" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/save"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:drawableStart="@drawable/ic_local_save"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/save" />
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:text="@string/save"
app:icon="@drawable/ic_local_save"
app:iconTint="@color/ic_local_save" />
</LinearLayout>
</LinearLayout>

View file

@ -10,9 +10,9 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
<com.google.android.material.button.MaterialButton
style="@style/GrayButton"
android:id="@+id/run"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/openapsma_run" />

View file

@ -10,94 +10,94 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/nav_logsettings"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/nav_logsettings"
android:textColor="@color/colorTreatmentButton" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/log_send"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/send_all_logs"
android:textColor="@color/colorTreatmentButton" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/log_delete"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/delete_logs"
android:textColor="@color/colorTreatmentButton" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/nav_export"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/nav_export"
android:textColor="@color/colorTreatmentButton" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/nav_import"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/nav_import"
android:textColor="@color/colorTreatmentButton" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/export_csv"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/ue_export_to_csv"
android:textColor="@color/colorTreatmentButton" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/nav_resetdb"
style="?android:attr/buttonStyle"
style="@style/GrayButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/nav_resetdb"
android:textColor="@color/colorTreatmentButton" />

Some files were not shown because too many files have changed in this diff Show more