This commit is contained in:
Milos Kozak 2022-03-11 08:23:16 +01:00
commit 21d0320e61
52 changed files with 817 additions and 554 deletions

View file

@ -44,5 +44,5 @@ Hints
* Start small, it is easier to review smaller changes that affect fewer parts of code * Start small, it is easier to review smaller changes that affect fewer parts of code
* Take a look into Issues list (https://github.com/nightscout/AndroidAPS/issues) - maybe there is something you can fix or implement * Take a look into Issues list (https://github.com/nightscout/AndroidAPS/issues) - maybe there is something you can fix or implement
* For new features, make sure there is Issue to track progress and have on-topic discussion * For new features, make sure there is Issue to track progress and have on-topic discussion
* Reach out to community, discuss idea on Gitter (https://gitter.im/MilosKozak/AndroidAPS) * Reach out to community, discuss idea on Discord (https://discord.gg/4fQUWHZ4Mw)
* Speak with other developers to minimise merge conflicts. Find out who worked, working or plan to work on speciffic issue or part of app * Speak with other developers to minimise merge conflicts. Find out who worked, working or plan to work on speciffic issue or part of app

View file

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

View file

@ -89,7 +89,7 @@ class MainActivity : NoSplashAppCompatActivity() {
private var pluginPreferencesMenuItem: MenuItem? = null private var pluginPreferencesMenuItem: MenuItem? = null
private var menu: Menu? = null private var menu: Menu? = null
private var menuOpen = false private var menuOpen = false
private var isProtectionCheckActive = false
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -168,11 +168,14 @@ class MainActivity : NoSplashAppCompatActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, null, if (!isProtectionCheckActive) {
UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { finish() } }, isProtectionCheckActive = true
UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { finish() } } protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, UIRunnable { isProtectionCheckActive = false },
UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { isProtectionCheckActive = false; finish() } },
UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { isProtectionCheckActive = false; finish() } }
) )
} }
}
private fun setWakeLock() { private fun setWakeLock() {
val keepScreenOn = sp.getBoolean(R.string.key_keep_screen_on, false) val keepScreenOn = sp.getBoolean(R.string.key_keep_screen_on, false)
@ -417,6 +420,8 @@ class MainActivity : NoSplashAppCompatActivity() {
// Add to crash log too // Add to crash log too
FirebaseCrashlytics.getInstance().setCustomKey("HEAD", BuildConfig.HEAD) FirebaseCrashlytics.getInstance().setCustomKey("HEAD", BuildConfig.HEAD)
FirebaseCrashlytics.getInstance().setCustomKey("Version", BuildConfig.VERSION) FirebaseCrashlytics.getInstance().setCustomKey("Version", BuildConfig.VERSION)
FirebaseCrashlytics.getInstance().setCustomKey("BuildType", BuildConfig.BUILD_TYPE)
FirebaseCrashlytics.getInstance().setCustomKey("BuildFlavor", BuildConfig.FLAVOR)
FirebaseCrashlytics.getInstance().setCustomKey("Remote", remote) FirebaseCrashlytics.getInstance().setCustomKey("Remote", remote)
FirebaseCrashlytics.getInstance().setCustomKey("Committed", BuildConfig.COMMITTED) FirebaseCrashlytics.getInstance().setCustomKey("Committed", BuildConfig.COMMITTED)
FirebaseCrashlytics.getInstance().setCustomKey("Hash", hashes[0]) FirebaseCrashlytics.getInstance().setCustomKey("Hash", hashes[0])

View file

@ -8,17 +8,17 @@ import android.os.Bundle
import androidx.annotation.XmlRes import androidx.annotation.XmlRes
import androidx.preference.* import androidx.preference.*
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
import info.nightscout.androidaps.danar.DanaRPlugin import info.nightscout.androidaps.danar.DanaRPlugin
import info.nightscout.androidaps.danars.DanaRSPlugin import info.nightscout.androidaps.danars.DanaRSPlugin
import info.nightscout.androidaps.diaconn.DiaconnG8Plugin import info.nightscout.androidaps.diaconn.DiaconnG8Plugin
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRebuildTabs import info.nightscout.androidaps.events.EventRebuildTabs
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploader import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploader
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
@ -43,17 +43,12 @@ import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
import info.nightscout.androidaps.plugins.source.DexcomPlugin import info.nightscout.androidaps.plugins.source.*
import info.nightscout.androidaps.plugins.source.EversensePlugin
import info.nightscout.androidaps.plugins.source.GlimpPlugin
import info.nightscout.androidaps.plugins.source.PoctechPlugin
import info.nightscout.androidaps.plugins.source.TomatoPlugin
import info.nightscout.androidaps.plugins.source.GlunovoPlugin
import info.nightscout.shared.SafeParse
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show
import info.nightscout.androidaps.utils.protection.PasswordCheck import info.nightscout.androidaps.utils.protection.PasswordCheck
import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.protection.ProtectionCheck.ProtectionType.*
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.shared.SafeParse
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject import javax.inject.Inject
@ -239,7 +234,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
rh.gs(R.string.key_application_protection) == key || rh.gs(R.string.key_application_protection) == key ||
rh.gs(R.string.key_bolus_protection) == key) && rh.gs(R.string.key_bolus_protection) == key) &&
sp.getString(R.string.key_master_password, "") == "" && sp.getString(R.string.key_master_password, "") == "" &&
sp.getInt(key, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal sp.getInt(key, NONE.ordinal) == BIOMETRIC.ordinal
) { ) {
activity?.let { activity?.let {
val title = rh.gs(R.string.unsecure_fallback_biometric) val title = rh.gs(R.string.unsecure_fallback_biometric)
@ -249,9 +244,9 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
} }
// Master password erased with activated Biometric protection // Master password erased with activated Biometric protection
val isBiometricActivated = sp.getInt(R.string.key_settings_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal || val isBiometricActivated = sp.getInt(R.string.key_settings_protection, NONE.ordinal) == BIOMETRIC.ordinal ||
sp.getInt(R.string.key_application_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal || sp.getInt(R.string.key_application_protection, NONE.ordinal) == BIOMETRIC.ordinal ||
sp.getInt(R.string.key_bolus_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal sp.getInt(R.string.key_bolus_protection, NONE.ordinal) == BIOMETRIC.ordinal
if (rh.gs(R.string.key_master_password) == key && sp.getString(key, "") == "" && isBiometricActivated) { if (rh.gs(R.string.key_master_password) == key && sp.getString(key, "") == "" && isBiometricActivated) {
activity?.let { activity?.let {
val title = rh.gs(R.string.unsecure_fallback_biometric) val title = rh.gs(R.string.unsecure_fallback_biometric)
@ -322,26 +317,35 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
if (pref is ListPreference) { if (pref is ListPreference) {
pref.setSummary(pref.entry) pref.setSummary(pref.entry)
// Preferences // Preferences
// Preferences
if (pref.getKey() == rh.gs(R.string.key_settings_protection)) { if (pref.getKey() == rh.gs(R.string.key_settings_protection)) {
val pass: Preference? = findPreference(rh.gs(R.string.key_settings_password)) val pass: Preference? = findPreference(rh.gs(R.string.key_settings_password))
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString() val usePassword = pref.value == CUSTOM_PASSWORD.ordinal.toString()
pass?.let { it.isVisible = usePassword }
val pin: Preference? = findPreference(rh.gs(R.string.key_settings_pin))
val usePin = pref.value == CUSTOM_PIN.ordinal.toString()
pin?.let { it.isVisible = usePin }
} }
// Application // Application
// Application
if (pref.getKey() == rh.gs(R.string.key_application_protection)) { if (pref.getKey() == rh.gs(R.string.key_application_protection)) {
val pass: Preference? = findPreference(rh.gs(R.string.key_application_password)) val pass: Preference? = findPreference(rh.gs(R.string.key_application_password))
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString() val usePassword = pref.value == CUSTOM_PASSWORD.ordinal.toString()
pass?.let { it.isVisible = usePassword }
val pin: Preference? = findPreference(rh.gs(R.string.key_application_pin))
val usePin = pref.value == CUSTOM_PIN.ordinal.toString()
pin?.let { it.isVisible = usePin }
} }
// Bolus // Bolus
// Bolus
if (pref.getKey() == rh.gs(R.string.key_bolus_protection)) { if (pref.getKey() == rh.gs(R.string.key_bolus_protection)) {
val pass: Preference? = findPreference(rh.gs(R.string.key_bolus_password)) val pass: Preference? = findPreference(rh.gs(R.string.key_bolus_password))
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString() val usePassword = pref.value == CUSTOM_PASSWORD.ordinal.toString()
pass?.let { it.isVisible = usePassword }
val pin: Preference? = findPreference(rh.gs(R.string.key_bolus_pin))
val usePin = pref.value == CUSTOM_PIN.ordinal.toString()
pin?.let { it.isVisible = usePin }
} }
} }
if (pref is EditTextPreference) { if (pref is EditTextPreference) {
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) { if (pref.getKey().contains("password") || pref.getKey().contains("pin") || pref.getKey().contains("secret")) {
pref.setSummary("******") pref.setSummary("******")
} else if (pref.text != null) { } else if (pref.text != null) {
pref.dialogMessage = pref.dialogMessage pref.dialogMessage = pref.dialogMessage
@ -357,18 +361,25 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
rh.gs(R.string.key_bolus_password), rh.gs(R.string.key_bolus_password),
rh.gs(R.string.key_master_password), rh.gs(R.string.key_master_password),
rh.gs(R.string.key_application_password), rh.gs(R.string.key_application_password),
rh.gs(R.string.key_settings_password) rh.gs(R.string.key_settings_password),
rh.gs(R.string.key_bolus_pin),
rh.gs(R.string.key_application_pin),
rh.gs(R.string.key_settings_pin)
) )
if (pref is Preference) { if (pref is Preference) {
if ((pref.key != null) && (hmacPasswords.contains(pref.key))) { if ((pref.key != null) && (hmacPasswords.contains(pref.key))) {
if (sp.getString(pref.key, "").startsWith("hmac:")) { if (sp.getString(pref.key, "").startsWith("hmac:")) {
pref.summary = "******" pref.summary = "******"
} else {
if (pref.getKey().contains("pin")) {
pref.summary = rh.gs(R.string.pin_not_set)
}else { }else {
pref.summary = rh.gs(R.string.password_not_set) pref.summary = rh.gs(R.string.password_not_set)
} }
} }
} }
}
pref?.let { adjustUnitDependentPrefs(it) } pref?.let { adjustUnitDependentPrefs(it) }
} }
@ -411,6 +422,18 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
passwordCheck.setPassword(context, R.string.application_password, R.string.key_application_password) passwordCheck.setPassword(context, R.string.application_password, R.string.key_application_password)
return true return true
} }
if (preference.key == rh.gs(R.string.key_settings_pin)) {
passwordCheck.setPassword(context, R.string.settings_pin, R.string.key_settings_pin, pinInput = true)
return true
}
if (preference.key == rh.gs(R.string.key_bolus_pin)) {
passwordCheck.setPassword(context, R.string.bolus_pin, R.string.key_bolus_pin, pinInput = true)
return true
}
if (preference.key == rh.gs(R.string.key_application_pin)) {
passwordCheck.setPassword(context, R.string.application_pin, R.string.key_application_pin, pinInput = true)
return true
}
// NSClient copy settings // NSClient copy settings
if (preference.key == rh.gs(R.string.key_statuslights_copy_ns)) { if (preference.key == rh.gs(R.string.key_statuslights_copy_ns)) {
nsSettingStatus.copyStatusLightsNsSettings(context) nsSettingStatus.copyStatusLightsNsSettings(context)

View file

@ -103,7 +103,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList) val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList)
binding.reason.adapter = adapterReason binding.reason.adapter = adapterReason
binding.targetCancel.setOnClickListener { shortClick(it) } binding.targetCancel.setOnClickListener { binding.duration.value = 0.0; shortClick(it) }
binding.eatingSoon.setOnClickListener { shortClick(it) } binding.eatingSoon.setOnClickListener { shortClick(it) }
binding.activity.setOnClickListener { shortClick(it) } binding.activity.setOnClickListener { shortClick(it) }
binding.hypo.setOnClickListener { shortClick(it) } binding.hypo.setOnClickListener { shortClick(it) }
@ -149,10 +149,6 @@ class TempTargetDialog : DialogFragmentWithDate() {
binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble() binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble()
binding.reason.setSelection(reasonList.indexOf(rh.gs(R.string.hypo))) binding.reason.setSelection(reasonList.indexOf(rh.gs(R.string.hypo)))
} }
R.id.cancel -> {
binding.duration.value = 0.0
}
} }
} }

View file

@ -438,10 +438,10 @@ class WizardDialog : DaggerDialogFragment() {
) )
wizard?.let { wizard -> wizard?.let { wizard ->
binding.bg.text = String.format(rh.gs(R.string.format_bg_isf), valueToUnitsToString(Profile.toMgdl(bg, profileFunction.getUnits()), profileFunction.getUnits().asText), wizard.sens) binding.bg.text = rh.gs(R.string.format_bg_isf, valueToUnitsToString(Profile.toMgdl(bg, profileFunction.getUnits()), profileFunction.getUnits().asText), wizard.sens)
binding.bgInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromBG) binding.bgInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromBG)
binding.carbs.text = String.format(rh.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic) binding.carbs.text = rh.gs(R.string.format_carbs_ic, carbs.toDouble(), wizard.ic)
binding.carbsInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs) binding.carbsInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs)
binding.iobInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB + wizard.insulinFromBasalIOB) binding.iobInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB + wizard.insulinFromBasalIOB)
@ -464,7 +464,7 @@ class WizardDialog : DaggerDialogFragment() {
// COB // COB
if (binding.cobCheckbox.isChecked) { if (binding.cobCheckbox.isChecked) {
binding.cob.text = String.format(rh.gs(R.string.format_cob_ic), cob, wizard.ic) binding.cob.text = rh.gs(R.string.format_cob_ic, cob, wizard.ic)
binding.cobInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromCOB) binding.cobInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromCOB)
} else { } else {
binding.cob.text = "" binding.cob.text = ""

View file

@ -109,29 +109,29 @@ class SafetyPlugin @Inject constructor(
} }
override fun applyBasalConstraints(absoluteRate: Constraint<Double>, profile: Profile): Constraint<Double> { override fun applyBasalConstraints(absoluteRate: Constraint<Double>, profile: Profile): Constraint<Double> {
absoluteRate.setIfGreater(aapsLogger, 0.0, String.format(rh.gs(R.string.limitingbasalratio), 0.0, rh.gs(R.string.itmustbepositivevalue)), this) absoluteRate.setIfGreater(aapsLogger, 0.0, rh.gs(R.string.limitingbasalratio, 0.0, rh.gs(R.string.itmustbepositivevalue)), this)
if (config.APS) { if (config.APS) {
var maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1.0) var maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1.0)
if (maxBasal < profile.getMaxDailyBasal()) { if (maxBasal < profile.getMaxDailyBasal()) {
maxBasal = profile.getMaxDailyBasal() maxBasal = profile.getMaxDailyBasal()
absoluteRate.addReason(rh.gs(R.string.increasingmaxbasal), this) absoluteRate.addReason(rh.gs(R.string.increasingmaxbasal), this)
} }
absoluteRate.setIfSmaller(aapsLogger, maxBasal, String.format(rh.gs(R.string.limitingbasalratio), maxBasal, rh.gs(R.string.maxvalueinpreferences)), this) absoluteRate.setIfSmaller(aapsLogger, maxBasal,rh.gs(R.string.limitingbasalratio, maxBasal, rh.gs(R.string.maxvalueinpreferences)), this)
// Check percentRate but absolute rate too, because we know real current basal in pump // Check percentRate but absolute rate too, because we know real current basal in pump
val maxBasalMultiplier = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0) val maxBasalMultiplier = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0)
val maxFromBasalMultiplier = floor(maxBasalMultiplier * profile.getBasal() * 100) / 100 val maxFromBasalMultiplier = floor(maxBasalMultiplier * profile.getBasal() * 100) / 100
absoluteRate.setIfSmaller(aapsLogger, maxFromBasalMultiplier, String.format(rh.gs(R.string.limitingbasalratio), maxFromBasalMultiplier, rh.gs(R.string.maxbasalmultiplier)), this) absoluteRate.setIfSmaller(aapsLogger, maxFromBasalMultiplier, rh.gs(R.string.limitingbasalratio, maxFromBasalMultiplier, rh.gs(R.string.maxbasalmultiplier)), this)
val maxBasalFromDaily = sp.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3.0) val maxBasalFromDaily = sp.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3.0)
val maxFromDaily = floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100 val maxFromDaily = floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100
absoluteRate.setIfSmaller(aapsLogger, maxFromDaily, String.format(rh.gs(R.string.limitingbasalratio), maxFromDaily, rh.gs(R.string.maxdailybasalmultiplier)), this) absoluteRate.setIfSmaller(aapsLogger, maxFromDaily,rh.gs(R.string.limitingbasalratio, maxFromDaily, rh.gs(R.string.maxdailybasalmultiplier)), this)
} }
absoluteRate.setIfSmaller(aapsLogger, hardLimits.maxBasal(), String.format(rh.gs(R.string.limitingbasalratio), hardLimits.maxBasal(), rh.gs(R.string.hardlimit)), this) absoluteRate.setIfSmaller(aapsLogger, hardLimits.maxBasal(),rh.gs(R.string.limitingbasalratio, hardLimits.maxBasal(), rh.gs(R.string.hardlimit)), this)
val pump = activePlugin.activePump val pump = activePlugin.activePump
// check for pump max // check for pump max
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0 val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
absoluteRate.setIfSmaller(aapsLogger, pumpLimit, String.format(rh.gs(R.string.limitingbasalratio), pumpLimit, rh.gs(R.string.pumplimit)), this) absoluteRate.setIfSmaller(aapsLogger, pumpLimit, rh.gs(R.string.limitingbasalratio, pumpLimit, rh.gs(R.string.pumplimit)), this)
} }
// do rounding // do rounding
@ -151,19 +151,19 @@ class SafetyPlugin @Inject constructor(
val pump = activePlugin.activePump val pump = activePlugin.activePump
var percentRateAfterConst = java.lang.Double.valueOf(absoluteConstraint.value() / currentBasal * 100).toInt() var percentRateAfterConst = java.lang.Double.valueOf(absoluteConstraint.value() / currentBasal * 100).toInt()
percentRateAfterConst = if (percentRateAfterConst < 100) Round.ceilTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() else Round.floorTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() percentRateAfterConst = if (percentRateAfterConst < 100) Round.ceilTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() else Round.floorTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt()
percentRate.set(aapsLogger, percentRateAfterConst, String.format(rh.gs(R.string.limitingpercentrate), percentRateAfterConst, rh.gs(R.string.pumplimit)), this) percentRate.set(aapsLogger, percentRateAfterConst, rh.gs(R.string.limitingpercentrate, percentRateAfterConst, rh.gs(R.string.pumplimit)), this)
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) {
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0 val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
percentRate.setIfSmaller(aapsLogger, pumpLimit.toInt(), String.format(rh.gs(R.string.limitingbasalratio), pumpLimit, rh.gs(R.string.pumplimit)), this) percentRate.setIfSmaller(aapsLogger, pumpLimit.toInt(), rh.gs(R.string.limitingbasalratio, pumpLimit, rh.gs(R.string.pumplimit)), this)
} }
return percentRate return percentRate
} }
override fun applyBolusConstraints(insulin: Constraint<Double>): Constraint<Double> { override fun applyBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
insulin.setIfGreater(aapsLogger, 0.0, String.format(rh.gs(R.string.limitingbolus), 0.0, rh.gs(R.string.itmustbepositivevalue)), this) insulin.setIfGreater(aapsLogger, 0.0, rh.gs(R.string.limitingbolus, 0.0, rh.gs(R.string.itmustbepositivevalue)), this)
val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0) val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0)
insulin.setIfSmaller(aapsLogger, maxBolus, String.format(rh.gs(R.string.limitingbolus), maxBolus, rh.gs(R.string.maxvalueinpreferences)), this) insulin.setIfSmaller(aapsLogger, maxBolus, rh.gs(R.string.limitingbolus, maxBolus, rh.gs(R.string.maxvalueinpreferences)), this)
insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), String.format(rh.gs(R.string.limitingbolus), hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this) insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), rh.gs(R.string.limitingbolus, hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this)
val pump = activePlugin.activePump val pump = activePlugin.activePump
val rounded = pump.pumpDescription.pumpType.determineCorrectBolusSize(insulin.value()) val rounded = pump.pumpDescription.pumpType.determineCorrectBolusSize(insulin.value())
insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this) insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this)
@ -171,10 +171,10 @@ class SafetyPlugin @Inject constructor(
} }
override fun applyExtendedBolusConstraints(insulin: Constraint<Double>): Constraint<Double> { override fun applyExtendedBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
insulin.setIfGreater(aapsLogger, 0.0, String.format(rh.gs(R.string.limitingextendedbolus), 0.0, rh.gs(R.string.itmustbepositivevalue)), this) insulin.setIfGreater(aapsLogger, 0.0, rh.gs(R.string.limitingextendedbolus, 0.0, rh.gs(R.string.itmustbepositivevalue)), this)
val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0) val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0)
insulin.setIfSmaller(aapsLogger, maxBolus, String.format(rh.gs(R.string.limitingextendedbolus), maxBolus, rh.gs(R.string.maxvalueinpreferences)), this) insulin.setIfSmaller(aapsLogger, maxBolus, rh.gs(R.string.limitingextendedbolus, maxBolus, rh.gs(R.string.maxvalueinpreferences)), this)
insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), String.format(rh.gs(R.string.limitingextendedbolus), hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this) insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), rh.gs(R.string.limitingextendedbolus, hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this)
val pump = activePlugin.activePump val pump = activePlugin.activePump
val rounded = pump.pumpDescription.pumpType.determineCorrectExtendedBolusSize(insulin.value()) val rounded = pump.pumpDescription.pumpType.determineCorrectExtendedBolusSize(insulin.value())
insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this) insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this)
@ -182,9 +182,9 @@ class SafetyPlugin @Inject constructor(
} }
override fun applyCarbsConstraints(carbs: Constraint<Int>): Constraint<Int> { override fun applyCarbsConstraints(carbs: Constraint<Int>): Constraint<Int> {
carbs.setIfGreater(aapsLogger, 0, String.format(rh.gs(R.string.limitingcarbs), 0, rh.gs(R.string.itmustbepositivevalue)), this) carbs.setIfGreater(aapsLogger, 0, rh.gs(R.string.limitingcarbs, 0, rh.gs(R.string.itmustbepositivevalue)), this)
val maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48) val maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48)
carbs.setIfSmaller(aapsLogger, maxCarbs, String.format(rh.gs(R.string.limitingcarbs), maxCarbs, rh.gs(R.string.maxvalueinpreferences)), this) carbs.setIfSmaller(aapsLogger, maxCarbs, rh.gs(R.string.limitingcarbs, maxCarbs, rh.gs(R.string.maxvalueinpreferences)), this)
return carbs return carbs
} }
@ -192,11 +192,11 @@ class SafetyPlugin @Inject constructor(
val apsMode = sp.getString(R.string.key_aps_mode, "open") val apsMode = sp.getString(R.string.key_aps_mode, "open")
val maxIobPref: Double = if (openAPSSMBPlugin.isEnabled() || OpenAPSSMBDynamicISFPlugin.isEnabled()) sp.getDouble(R.string.key_openapssmb_max_iob, 3.0) else sp.getDouble(R.string 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) .key_openapsma_max_iob, 1.5)
maxIob.setIfSmaller(aapsLogger, maxIobPref, String.format(rh.gs(R.string.limitingiob), maxIobPref, rh.gs(R.string.maxvalueinpreferences)), this) maxIob.setIfSmaller(aapsLogger, maxIobPref, 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 (openAPSAMAPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobAMA(), 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 (openAPSSMBPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), 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 (OpenAPSSMBDynamicISFPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), 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) if (apsMode == "lgs") maxIob.setIfSmaller(aapsLogger, HardLimits.MAX_IOB_LGS, rh.gs(R.string.limitingiob, HardLimits.MAX_IOB_LGS, rh.gs(R.string.lowglucosesuspend)), this)
return maxIob return maxIob
} }

View file

@ -157,10 +157,20 @@ class ActionsFragment : DaggerFragment() {
cannulaOrPatch = view.findViewById(R.id.cannula_or_patch) cannulaOrPatch = view.findViewById(R.id.cannula_or_patch)
profileSwitch?.setOnClickListener { profileSwitch?.setOnClickListener {
ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog") activity?.let { activity ->
protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.BOLUS,
UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog")})
}
} }
tempTarget?.setOnClickListener { tempTarget?.setOnClickListener {
TempTargetDialog().show(childFragmentManager, "Actions") activity?.let { activity ->
protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.BOLUS,
UIRunnable { TempTargetDialog().show(childFragmentManager, "Actions") })
}
} }
extendedBolus?.setOnClickListener { extendedBolus?.setOnClickListener {
activity?.let { activity -> activity?.let { activity ->
@ -187,7 +197,12 @@ class ActionsFragment : DaggerFragment() {
} }
} }
setTempBasal?.setOnClickListener { setTempBasal?.setOnClickListener {
TempBasalDialog().show(childFragmentManager, "Actions") activity?.let { activity ->
protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.BOLUS,
UIRunnable { TempBasalDialog().show(childFragmentManager, "Actions") })
}
} }
cancelTempBasal?.setOnClickListener { cancelTempBasal?.setOnClickListener {
if (iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) != null) { if (iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) != null) {

View file

@ -27,6 +27,7 @@ import info.nightscout.androidaps.plugins.general.overview.OverviewData
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.DashHistoryDatabase import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.DashHistoryDatabase
import info.nightscout.androidaps.plugins.pump.omnipod.eros.history.database.ErosHistoryDatabase import info.nightscout.androidaps.plugins.pump.omnipod.eros.history.database.ErosHistoryDatabase
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.rxjava3.core.Completable.fromAction import io.reactivex.rxjava3.core.Completable.fromAction
@ -48,6 +49,7 @@ class MaintenanceFragment : DaggerFragment() {
@Inject lateinit var diaconnDatabase: DiaconnHistoryDatabase @Inject lateinit var diaconnDatabase: DiaconnHistoryDatabase
@Inject lateinit var erosDatabase: ErosHistoryDatabase @Inject lateinit var erosDatabase: ErosHistoryDatabase
@Inject lateinit var dashDatabase: DashHistoryDatabase @Inject lateinit var dashDatabase: DashHistoryDatabase
@Inject lateinit var protectionCheck: ProtectionCheck
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var dataSyncSelector: DataSyncSelector @Inject lateinit var dataSyncSelector: DataSyncSelector
@Inject lateinit var pumpSync: PumpSync @Inject lateinit var pumpSync: PumpSync
@ -128,6 +130,23 @@ class MaintenanceFragment : DaggerFragment() {
} }
} }
} }
if (protectionCheck.isLocked(ProtectionCheck.Protection.PREFERENCES)) {
binding.mainLayout.visibility = View.GONE
} else {
binding.unlock.visibility = View.GONE
}
binding.unlock.setOnClickListener {
activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, {
activity.runOnUiThread {
binding.mainLayout.visibility = View.VISIBLE
binding.unlock.visibility = View.GONE
}
})
}
}
} }
@Synchronized @Synchronized

View file

@ -164,11 +164,11 @@ class NotificationStore @Inject constructor(
@Suppress("SetTextI18n") @Suppress("SetTextI18n")
holder.binding.text.text = dateUtil.timeString(notification.date) + " " + notification.text holder.binding.text.text = dateUtil.timeString(notification.date) + " " + notification.text
when (notification.level) { when (notification.level) {
Notification.URGENT -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationUrgent)) Notification.URGENT -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationUrgent))
Notification.NORMAL -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationNormal)) Notification.NORMAL -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationNormal))
Notification.LOW -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationLow)) Notification.LOW -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationLow))
Notification.INFO -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationInfo)) Notification.INFO -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationInfo))
Notification.ANNOUNCEMENT -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationAnnouncement)) Notification.ANNOUNCEMENT -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationAnnouncement))
} }
} }

View file

@ -328,7 +328,7 @@ class SmsCommunicatorPlugin @Inject constructor(
} else if (lastBG != null) { } else if (lastBG != null) {
val agoMilliseconds = dateUtil.now() - lastBG.timestamp val agoMilliseconds = dateUtil.now() - lastBG.timestamp
val agoMin = (agoMilliseconds / 60.0 / 1000.0).toInt() val agoMin = (agoMilliseconds / 60.0 / 1000.0).toInt()
reply = rh.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsString(units) + " " + String.format(rh.gs(R.string.sms_minago), agoMin) + ", " reply = rh.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsString(units) + " " + rh.gs(R.string.sms_minago, agoMin) + ", "
} }
val glucoseStatus = glucoseStatusProvider.glucoseStatusData val glucoseStatus = glucoseStatusProvider.glucoseStatusData
if (glucoseStatus != null) reply += rh.gs(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", " if (glucoseStatus != null) reply += rh.gs(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", "
@ -348,7 +348,7 @@ class SmsCommunicatorPlugin @Inject constructor(
"DISABLE", "STOP" -> { "DISABLE", "STOP" -> {
if (loop.enabled) { if (loop.enabled) {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_loopdisablereplywithcode), passCode) val reply = rh.gs(R.string.smscommunicator_loopdisablereplywithcode, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
override fun run() { override fun run() {
@ -372,7 +372,7 @@ class SmsCommunicatorPlugin @Inject constructor(
"ENABLE", "START" -> { "ENABLE", "START" -> {
if (!loop.enabled) { if (!loop.enabled) {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_loopenablereplywithcode), passCode) val reply = rh.gs(R.string.smscommunicator_loopenablereplywithcode, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
override fun run() { override fun run() {
@ -389,7 +389,7 @@ class SmsCommunicatorPlugin @Inject constructor(
"STATUS" -> { "STATUS" -> {
val reply = if (loop.enabled) { val reply = if (loop.enabled) {
if (loop.isSuspended) String.format(rh.gs(R.string.loopsuspendedfor), loop.minutesToEndOfSuspend()) if (loop.isSuspended) rh.gs(R.string.loopsuspendedfor, loop.minutesToEndOfSuspend())
else rh.gs(R.string.smscommunicator_loopisenabled) else rh.gs(R.string.smscommunicator_loopisenabled)
} else } else
rh.gs(R.string.loopisdisabled) rh.gs(R.string.loopisdisabled)
@ -399,7 +399,7 @@ class SmsCommunicatorPlugin @Inject constructor(
"RESUME" -> { "RESUME" -> {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_loopresumereplywithcode), passCode) val reply = rh.gs(R.string.smscommunicator_loopresumereplywithcode, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
override fun run() { override fun run() {
@ -436,7 +436,7 @@ class SmsCommunicatorPlugin @Inject constructor(
return return
} else { } else {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_suspendreplywithcode), duration, passCode) val reply = rh.gs(R.string.smscommunicator_suspendreplywithcode, duration, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, duration) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, duration) {
override fun run() { override fun run() {
@ -515,7 +515,7 @@ class SmsCommunicatorPlugin @Inject constructor(
receivedSms.processed = true receivedSms.processed = true
} else if ((divided.size == 2) && (divided[1].equals("CONNECT", ignoreCase = true))) { } else if ((divided.size == 2) && (divided[1].equals("CONNECT", ignoreCase = true))) {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_pumpconnectwithcode), passCode) val reply = rh.gs(R.string.smscommunicator_pumpconnectwithcode, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
override fun run() { override fun run() {
@ -548,7 +548,7 @@ class SmsCommunicatorPlugin @Inject constructor(
return return
} else { } else {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_pumpdisconnectwithcode), duration, passCode) val reply = rh.gs(R.string.smscommunicator_pumpdisconnectwithcode, duration, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
override fun run() { override fun run() {
@ -601,7 +601,7 @@ class SmsCommunicatorPlugin @Inject constructor(
if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.noprofile))) if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.noprofile)))
else { else {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_profilereplywithcode), list[pIndex - 1], percentage, passCode) val reply = rh.gs(R.string.smscommunicator_profilereplywithcode, list[pIndex - 1], percentage, passCode)
receivedSms.processed = true receivedSms.processed = true
val finalPercentage = percentage val finalPercentage = percentage
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, list[pIndex - 1] as String, finalPercentage) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, list[pIndex - 1] as String, finalPercentage) {
@ -627,7 +627,7 @@ class SmsCommunicatorPlugin @Inject constructor(
private fun processBASAL(divided: Array<String>, receivedSms: Sms) { private fun processBASAL(divided: Array<String>, receivedSms: Sms) {
if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") { if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_basalstopreplywithcode), passCode) val reply = rh.gs(R.string.smscommunicator_basalstopreplywithcode, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
override fun run() { override fun run() {
@ -662,14 +662,14 @@ class SmsCommunicatorPlugin @Inject constructor(
else { else {
tempBasalPct = constraintChecker.applyBasalPercentConstraints(Constraint(tempBasalPct), profile).value() tempBasalPct = constraintChecker.applyBasalPercentConstraints(Constraint(tempBasalPct), profile).value()
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_basalpctreplywithcode), tempBasalPct, duration, passCode) val reply = rh.gs(R.string.smscommunicator_basalpctreplywithcode, tempBasalPct, duration, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasalPct, duration) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasalPct, duration) {
override fun run() { override fun run() {
commandQueue.tempBasalPercent(anInteger(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() { commandQueue.tempBasalPercent(anInteger(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
override fun run() { override fun run() {
if (result.success) { if (result.success) {
var replyText = if (result.isPercent) String.format(rh.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(rh.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration) var replyText = if (result.isPercent) rh.gs(R.string.smscommunicator_tempbasalset_percent, result.percent, result.duration) else rh.gs(R.string.smscommunicator_tempbasalset, result.absolute, result.duration)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
if (result.isPercent) if (result.isPercent)
@ -706,15 +706,15 @@ class SmsCommunicatorPlugin @Inject constructor(
else { else {
tempBasal = constraintChecker.applyBasalConstraints(Constraint(tempBasal), profile).value() tempBasal = constraintChecker.applyBasalConstraints(Constraint(tempBasal), profile).value()
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_basalreplywithcode), tempBasal, duration, passCode) val reply = rh.gs(R.string.smscommunicator_basalreplywithcode, tempBasal, duration, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasal, duration) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasal, duration) {
override fun run() { override fun run() {
commandQueue.tempBasalAbsolute(aDouble(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() { commandQueue.tempBasalAbsolute(aDouble(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
override fun run() { override fun run() {
if (result.success) { if (result.success) {
var replyText = if (result.isPercent) String.format(rh.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) var replyText = if (result.isPercent) rh.gs(R.string.smscommunicator_tempbasalset_percent, result.percent, result.duration)
else String.format(rh.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration) else rh.gs(R.string.smscommunicator_tempbasalset, result.absolute, result.duration)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
if (result.isPercent) if (result.isPercent)
@ -743,7 +743,7 @@ class SmsCommunicatorPlugin @Inject constructor(
private fun processEXTENDED(divided: Array<String>, receivedSms: Sms) { private fun processEXTENDED(divided: Array<String>, receivedSms: Sms) {
if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") { if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_extendedstopreplywithcode), passCode) val reply = rh.gs(R.string.smscommunicator_extendedstopreplywithcode, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
override fun run() { override fun run() {
@ -773,14 +773,14 @@ class SmsCommunicatorPlugin @Inject constructor(
if (extended == 0.0 || duration == 0) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrongformat))) if (extended == 0.0 || duration == 0) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrongformat)))
else { else {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_extendedreplywithcode), extended, duration, passCode) val reply = rh.gs(R.string.smscommunicator_extendedreplywithcode, extended, duration, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, extended, duration) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, extended, duration) {
override fun run() { override fun run() {
commandQueue.extendedBolus(aDouble(), secondInteger(), object : Callback() { commandQueue.extendedBolus(aDouble(), secondInteger(), object : Callback() {
override fun run() { override fun run() {
if (result.success) { if (result.success) {
var replyText = String.format(rh.gs(R.string.smscommunicator_extendedset), aDouble, duration) var replyText = rh.gs(R.string.smscommunicator_extendedset, aDouble, duration)
if (config.APS) replyText += "\n" + rh.gs(R.string.loopsuspended) if (config.APS) replyText += "\n" + rh.gs(R.string.loopsuspended)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
@ -817,9 +817,9 @@ class SmsCommunicatorPlugin @Inject constructor(
} else if (bolus > 0.0) { } else if (bolus > 0.0) {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = if (isMeal) val reply = if (isMeal)
String.format(rh.gs(R.string.smscommunicator_mealbolusreplywithcode), bolus, passCode) rh.gs(R.string.smscommunicator_mealbolusreplywithcode, bolus, passCode)
else else
String.format(rh.gs(R.string.smscommunicator_bolusreplywithcode), bolus, passCode) rh.gs(R.string.smscommunicator_bolusreplywithcode, bolus, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, bolus) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, bolus) {
override fun run() { override fun run() {
@ -833,9 +833,9 @@ class SmsCommunicatorPlugin @Inject constructor(
override fun run() { override fun run() {
if (resultSuccess) { if (resultSuccess) {
var replyText = if (isMeal) var replyText = if (isMeal)
String.format(rh.gs(R.string.smscommunicator_mealbolusdelivered), resultBolusDelivered) rh.gs(R.string.smscommunicator_mealbolusdelivered, resultBolusDelivered)
else else
String.format(rh.gs(R.string.smscommunicator_bolusdelivered), resultBolusDelivered) rh.gs(R.string.smscommunicator_bolusdelivered, resultBolusDelivered)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
lastRemoteBolusTime = dateUtil.now() lastRemoteBolusTime = dateUtil.now()
if (isMeal) { if (isMeal) {
@ -866,7 +866,7 @@ class SmsCommunicatorPlugin @Inject constructor(
val tt = if (currentProfile.units == GlucoseUnit.MMOL) { val tt = if (currentProfile.units == GlucoseUnit.MMOL) {
DecimalFormatter.to1Decimal(eatingSoonTT) DecimalFormatter.to1Decimal(eatingSoonTT)
} else DecimalFormatter.to0Decimal(eatingSoonTT) } else DecimalFormatter.to0Decimal(eatingSoonTT)
replyText += "\n" + String.format(rh.gs(R.string.smscommunicator_mealbolusdelivered_tt), tt, eatingSoonTTDuration) replyText += "\n" + rh.gs(R.string.smscommunicator_mealbolusdelivered_tt, tt, eatingSoonTTDuration)
} }
} }
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
@ -920,7 +920,7 @@ class SmsCommunicatorPlugin @Inject constructor(
if (grams == 0) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrongformat))) if (grams == 0) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrongformat)))
else { else {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_carbsreplywithcode), grams, dateUtil.timeString(time), passCode) val reply = rh.gs(R.string.smscommunicator_carbsreplywithcode, grams, dateUtil.timeString(time), passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, grams, time) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, grams, time) {
override fun run() { override fun run() {
@ -930,7 +930,7 @@ class SmsCommunicatorPlugin @Inject constructor(
commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (result.success) { if (result.success) {
var replyText = String.format(rh.gs(R.string.smscommunicator_carbsset), anInteger) var replyText = rh.gs(R.string.smscommunicator_carbsset, anInteger)
replyText += "\n" + activePlugin.activePump.shortStatus(true) replyText += "\n" + activePlugin.activePump.shortStatus(true)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.CARBS, Sources.SMS, activePlugin.activePump.shortStatus(true) + ": " + rh.gs(R.string.smscommunicator_carbsset, anInteger), uel.log(Action.CARBS, Sources.SMS, activePlugin.activePump.shortStatus(true) + ": " + rh.gs(R.string.smscommunicator_carbsset, anInteger),
@ -956,7 +956,7 @@ class SmsCommunicatorPlugin @Inject constructor(
val isStop = divided[1].equals("STOP", ignoreCase = true) || divided[1].equals("CANCEL", ignoreCase = true) val isStop = divided[1].equals("STOP", ignoreCase = true) || divided[1].equals("CANCEL", ignoreCase = true)
if (isMeal || isActivity || isHypo) { if (isMeal || isActivity || isHypo) {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_temptargetwithcode), divided[1].uppercase(Locale.getDefault()), passCode) val reply = rh.gs(R.string.smscommunicator_temptargetwithcode, divided[1].uppercase(Locale.getDefault()), passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
override fun run() { override fun run() {
@ -1009,7 +1009,7 @@ class SmsCommunicatorPlugin @Inject constructor(
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
val ttString = if (units == GlucoseUnit.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt) val ttString = if (units == GlucoseUnit.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt)
val replyText = String.format(rh.gs(R.string.smscommunicator_tt_set), ttString, ttDuration) val replyText = rh.gs(R.string.smscommunicator_tt_set, ttString, ttDuration)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.TT, Sources.SMS, uel.log(Action.TT, Sources.SMS,
ValueWithUnit.fromGlucoseUnit(tt, units.asText), ValueWithUnit.fromGlucoseUnit(tt, units.asText),
@ -1018,7 +1018,7 @@ class SmsCommunicatorPlugin @Inject constructor(
}) })
} else if (isStop) { } else if (isStop) {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_temptargetcancel), passCode) val reply = rh.gs(R.string.smscommunicator_temptargetcancel, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
override fun run() { override fun run() {
@ -1028,7 +1028,7 @@ class SmsCommunicatorPlugin @Inject constructor(
}, { }, {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
val replyText = String.format(rh.gs(R.string.smscommunicator_tt_canceled)) val replyText = rh.gs(R.string.smscommunicator_tt_canceled)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.CANCEL_TT, Sources.SMS, rh.gs(R.string.smscommunicator_tt_canceled), uel.log(Action.CANCEL_TT, Sources.SMS, rh.gs(R.string.smscommunicator_tt_canceled),
ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.smscommunicator_tt_canceled))) ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.smscommunicator_tt_canceled)))
@ -1043,12 +1043,12 @@ class SmsCommunicatorPlugin @Inject constructor(
|| divided[1].equals("DISABLE", ignoreCase = true)) || divided[1].equals("DISABLE", ignoreCase = true))
if (isStop) { if (isStop) {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_stopsmswithcode), passCode) val reply = rh.gs(R.string.smscommunicator_stopsmswithcode, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
override fun run() { override fun run() {
sp.putBoolean(R.string.key_smscommunicator_remotecommandsallowed, false) sp.putBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)
val replyText = String.format(rh.gs(R.string.smscommunicator_stoppedsms)) val replyText = rh.gs(R.string.smscommunicator_stoppedsms)
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
uel.log(Action.STOP_SMS, Sources.SMS, rh.gs(R.string.smscommunicator_stoppedsms), uel.log(Action.STOP_SMS, Sources.SMS, rh.gs(R.string.smscommunicator_stoppedsms),
ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.smscommunicator_stoppedsms))) ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.smscommunicator_stoppedsms)))
@ -1061,7 +1061,7 @@ class SmsCommunicatorPlugin @Inject constructor(
val cal = SafeParse.stringToDouble(divided[1]) val cal = SafeParse.stringToDouble(divided[1])
if (cal > 0.0) { if (cal > 0.0) {
val passCode = generatePassCode() val passCode = generatePassCode()
val reply = String.format(rh.gs(R.string.smscommunicator_calibrationreplywithcode), cal, passCode) val reply = rh.gs(R.string.smscommunicator_calibrationreplywithcode, cal, passCode)
receivedSms.processed = true receivedSms.processed = true
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false, cal) { messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false, cal) {
override fun run() { override fun run() {
@ -1127,7 +1127,7 @@ class SmsCommunicatorPlugin @Inject constructor(
} }
private fun generatePassCode(): String = private fun generatePassCode(): String =
String.format(rh.gs(R.string.smscommunicator_code_from_authenticator_for), otp.name()) rh.gs(R.string.smscommunicator_code_from_authenticator_for, otp.name())
private fun stripAccents(str: String): String { private fun stripAccents(str: String): String {
var s = str var s = str

View file

@ -111,7 +111,7 @@ class ActionStringHandler @Inject constructor(
@Synchronized @Synchronized
private fun handleInitiate(actionString: String) { private fun handleInitiate(actionString: String) {
//TODO: i18n //TODO: i18n
Log.i("ActionStringHandler", "handleInitiate actionString=" + actionString) Log.i("ActionStringHandler", "handleInitiate actionString=$actionString")
if (!sp.getBoolean(R.string.key_wear_control, false)) return if (!sp.getBoolean(R.string.key_wear_control, false)) return
lastBolusWizard = null lastBolusWizard = null
var rTitle = rh.gs(R.string.confirm).uppercase() var rTitle = rh.gs(R.string.confirm).uppercase()
@ -640,10 +640,10 @@ class ActionStringHandler @Inject constructor(
var msg = "" var msg = ""
//check for validity //check for validity
if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) { if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) {
msg += String.format(rh.gs(R.string.valueoutofrange), "Profile-Percentage") + "\n" msg += rh.gs(R.string.valueoutofrange, "Profile-Percentage") + "\n"
} }
if (timeshift < 0 || timeshift > 23) { if (timeshift < 0 || timeshift > 23) {
msg += String.format(rh.gs(R.string.valueoutofrange), "Profile-Timeshift") + "\n" msg += rh.gs(R.string.valueoutofrange, "Profile-Timeshift") + "\n"
} }
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile()
if (profile == null) { if (profile == null) {

View file

@ -95,7 +95,7 @@ class WearPlugin @Inject constructor(
.toObservable(EventBolusRequested::class.java) .toObservable(EventBolusRequested::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ event: EventBolusRequested -> .subscribe({ event: EventBolusRequested ->
val status = String.format(rh.gs(R.string.bolusrequested), event.amount) val status = rh.gs(R.string.bolusrequested, event.amount)
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS) val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS)
intent.putExtra("progresspercent", 0) intent.putExtra("progresspercent", 0)
intent.putExtra("progressstatus", status) intent.putExtra("progressstatus", status)

View file

@ -29,6 +29,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.ui.TimeListEdit import info.nightscout.androidaps.utils.ui.TimeListEdit
@ -49,6 +50,7 @@ class LocalProfileFragment : DaggerFragment() {
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var localProfilePlugin: LocalProfilePlugin @Inject lateinit var localProfilePlugin: LocalProfilePlugin
@Inject lateinit var hardLimits: HardLimits @Inject lateinit var hardLimits: HardLimits
@Inject lateinit var protectionCheck: ProtectionCheck
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@ -88,8 +90,7 @@ class LocalProfileFragment : DaggerFragment() {
private var _binding: LocalprofileFragmentBinding? = null private var _binding: LocalprofileFragmentBinding? = null
// This property is only valid between onCreateView and // This property is only valid between onCreateView and onDestroyView.
// onDestroyView.
private val binding get() = _binding!! private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@ -124,6 +125,23 @@ class LocalProfileFragment : DaggerFragment() {
binding.target.visibility = View.VISIBLE binding.target.visibility = View.VISIBLE
} }
binding.dia.editText?.id?.let { binding.diaLabel.labelFor = it } binding.dia.editText?.id?.let { binding.diaLabel.labelFor = it }
if (protectionCheck.isLocked(ProtectionCheck.Protection.PREFERENCES)) {
binding.mainLayout.visibility = View.GONE
} else {
binding.unlock.visibility = View.GONE
}
binding.unlock.setOnClickListener {
activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, {
activity.runOnUiThread {
binding.mainLayout.visibility = View.VISIBLE
binding.unlock.visibility = View.GONE
}
})
}
}
} }
fun build() { fun build() {

View file

@ -113,7 +113,7 @@ class AndroidPermission @Inject constructor(
@Synchronized @Synchronized
fun notifyForBatteryOptimizationPermission(activity: FragmentActivity) { fun notifyForBatteryOptimizationPermission(activity: FragmentActivity) {
if (permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) { if (permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
val notification = NotificationWithAction(injector, Notification.PERMISSION_BATTERY, String.format(rh.gs(R.string.needwhitelisting), rh.gs(R.string.app_name)), Notification.URGENT) val notification = NotificationWithAction(injector, Notification.PERMISSION_BATTERY, rh.gs(R.string.needwhitelisting, rh.gs(R.string.app_name)), Notification.URGENT)
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) } notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) }
rxBus.send(EventNewNotification(notification)) rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_BATTERY)) } else rxBus.send(EventDismissNotification(Notification.PERMISSION_BATTERY))

View file

@ -242,77 +242,67 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="45dp"
android:layout_gravity="center|center_vertical" android:paddingHorizontal="10dp">
android:layout_marginTop="10dp"
android:background="@android:color/transparent"
android:orientation="horizontal"
android:padding="0dp">
<CheckBox <ToggleButton
android:id="@+id/bg_checkbox_icon" android:id="@+id/bg_checkbox_icon"
android:layout_width="wrap_content" style="?android:attr/borderlessButtonStyle"
android:layout_height="wrap_content" android:layout_width="0dp"
android:layout_marginLeft="15dp" android:layout_height="match_parent"
android:layout_marginRight="15dp" android:layout_weight="1"
android:button="@android:color/transparent"
android:checked="true" android:checked="true"
android:contentDescription="@string/treatments_wizard_bg_label" android:contentDescription="@string/treatments_wizard_bg_label"
android:drawableStart="@drawable/checkbox_bg_icon" android:drawableTop="@drawable/checkbox_bg_icon"
android:scaleX="1.4" android:scaleX="1.4"
android:scaleY="1.4" /> android:scaleY="1.4" />
<CheckBox <ToggleButton
android:id="@+id/tt_checkbox_icon" android:id="@+id/tt_checkbox_icon"
android:layout_width="wrap_content" style="?android:attr/borderlessButtonStyle"
android:layout_height="wrap_content" android:layout_width="0dp"
android:layout_marginLeft="15dp" android:layout_height="match_parent"
android:layout_marginRight="15dp" android:layout_weight="1"
android:button="@android:color/transparent"
android:checked="true" android:checked="true"
android:contentDescription="@string/treatments_wizard_tt_label" android:contentDescription="@string/treatments_wizard_tt_label"
android:drawableStart="@drawable/checkbox_tt_icon" android:drawableTop="@drawable/checkbox_tt_icon"
android:scaleX="1.6" android:scaleX="1.6"
android:scaleY="1.6" android:scaleY="1.6" />
android:visibility="gone" />
<CheckBox <ToggleButton
android:id="@+id/trend_checkbox_icon" android:id="@+id/trend_checkbox_icon"
android:layout_width="wrap_content" style="?android:attr/borderlessButtonStyle"
android:layout_height="wrap_content" android:layout_width="0dp"
android:layout_marginLeft="15dp" android:layout_height="match_parent"
android:layout_marginRight="15dp" android:layout_weight="1"
android:button="@android:color/transparent"
android:checked="true" android:checked="true"
android:contentDescription="@string/bg_trend_label" android:contentDescription="@string/bg_trend_label"
android:drawableStart="@drawable/checkbox_trend_icon" android:drawableTop="@drawable/checkbox_trend_icon"
android:scaleX="1.4" android:scaleX="1.4"
android:scaleY="1.4" /> android:scaleY="1.4" />
<CheckBox <ToggleButton
android:id="@+id/iob_checkbox_icon" android:id="@+id/iob_checkbox_icon"
android:layout_width="wrap_content" style="?android:attr/borderlessButtonStyle"
android:layout_height="wrap_content" android:layout_width="0dp"
android:layout_marginLeft="15dp" android:layout_height="match_parent"
android:layout_marginRight="15dp" android:layout_weight="1"
android:button="@android:color/transparent"
android:checked="true" android:checked="true"
android:contentDescription="@string/iob" android:contentDescription="@string/iob"
android:drawableStart="@drawable/checkbox_iob_icon" android:drawableTop="@drawable/checkbox_iob_icon"
android:scaleX="1.4" android:scaleX="1.4"
android:scaleY="1.4" /> android:scaleY="1.4" />
<CheckBox <ToggleButton
android:id="@+id/cob_checkbox_icon" android:id="@+id/cob_checkbox_icon"
android:layout_width="wrap_content" style="?android:attr/borderlessButtonStyle"
android:layout_height="wrap_content" android:layout_width="0dp"
android:layout_marginLeft="15dp" android:layout_height="match_parent"
android:layout_marginRight="15dp" android:layout_weight="1"
android:button="@android:color/transparent"
android:checked="true" android:checked="true"
android:contentDescription="@string/treatments_wizard_cob_label" android:contentDescription="@string/treatments_wizard_cob_label"
android:drawableStart="@drawable/checkbox_cob_icon" android:drawableTop="@drawable/checkbox_cob_icon"
android:scaleX="1.6" android:scaleX="1.6"
android:scaleY="1.6" /> android:scaleY="1.6" />

View file

@ -10,6 +10,20 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/unlock"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/unlock_settings" />
<LinearLayout
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -361,6 +375,8 @@
</LinearLayout> </LinearLayout>
</LinearLayout>
</ScrollView> </ScrollView>

View file

@ -5,7 +5,16 @@
android:paddingTop="2dp" android:paddingTop="2dp"
tools:context=".plugins.general.maintenance.MaintenanceFragment"> tools:context=".plugins.general.maintenance.MaintenanceFragment">
<com.google.android.material.button.MaterialButton
android:id="@+id/unlock"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/unlock_settings" />
<LinearLayout <LinearLayout
android:id="@+id/main_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">

View file

@ -7,7 +7,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_margin="1dp" android:layout_margin="1dp"
card_view:cardBackgroundColor="@color/cardColorBackground" card_view:cardBackgroundColor="@color/notificationUrgent"
card_view:cardCornerRadius="6dp"> card_view:cardCornerRadius="6dp">
<LinearLayout <LinearLayout
@ -22,7 +22,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_weight="1" android:layout_weight="1"
android:textColor="?attr/colorOnError"
android:maxLines="4" android:maxLines="4"
android:textStyle="bold"
android:text="Notification text. Notification text. Notification text. Notification text. Notification text. Notification text. " android:text="Notification text. Notification text. Notification text. Notification text. Notification text. Notification text. "
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />

View file

@ -267,6 +267,7 @@
<string name="configbuilder_shortname">KONF</string> <string name="configbuilder_shortname">KONF</string>
<string name="loop_shortname">OKRUH</string> <string name="loop_shortname">OKRUH</string>
<string name="oaps_shortname">OAPS</string> <string name="oaps_shortname">OAPS</string>
<string name="dynisf_shortname">DYNISF</string>
<string name="localprofile_shortname">LPRF</string> <string name="localprofile_shortname">LPRF</string>
<string name="overview_shortname">PREH</string> <string name="overview_shortname">PREH</string>
<string name="virtualpump_shortname">VPUM</string> <string name="virtualpump_shortname">VPUM</string>
@ -432,6 +433,7 @@
<string name="ns_localbroadcasts">Povoliť vysielanie do iných aplikácií (napr. xDrip+). Nepovoľujte, pokiaľ máte nainštalovanú viac ako jednu AAPS, alebo NSClient inštanciu!</string> <string name="ns_localbroadcasts">Povoliť vysielanie do iných aplikácií (napr. xDrip+). Nepovoľujte, pokiaľ máte nainštalovanú viac ako jednu AAPS, alebo NSClient inštanciu!</string>
<string name="ns_localbroadcasts_title">Povoliť lokálne vysielanie.</string> <string name="ns_localbroadcasts_title">Povoliť lokálne vysielanie.</string>
<string name="openapssmb">OpenAPS SMB</string> <string name="openapssmb">OpenAPS SMB</string>
<string name="openaps_smb_dynamic_isf">Dynamická ISF</string>
<string name="enableuam">Povoliť UAM</string> <string name="enableuam">Povoliť UAM</string>
<string name="enablesmb">Povoliť SMB</string> <string name="enablesmb">Povoliť SMB</string>
<string name="enablesmb_summary">Použiť Super Mikro Bolusy namiesto dočasných bazálov, pre zrýchleniu účinku</string> <string name="enablesmb_summary">Použiť Super Mikro Bolusy namiesto dočasných bazálov, pre zrýchleniu účinku</string>
@ -661,6 +663,9 @@
<string name="sensitivity_raises_target_title">Citlivosť zvyšuje cieľ</string> <string name="sensitivity_raises_target_title">Citlivosť zvyšuje cieľ</string>
<string name="sensitivity_raises_target_summary">Ak je zistená vyššia citlivosť, zvýši cieľovú hladinu glykémie</string> <string name="sensitivity_raises_target_summary">Ak je zistená vyššia citlivosť, zvýši cieľovú hladinu glykémie</string>
<string name="careportal_removestartedevents">Vymazať udalosti \"AndroidAPS reštartovaný\"</string> <string name="careportal_removestartedevents">Vymazať udalosti \"AndroidAPS reštartovaný\"</string>
<string name="show_invalidated">Zobraziť neplatné</string>
<string name="hide_invalidated">Skryť zneplatnené</string>
<string name="remove_items">Odstrániť položky</string>
<string name="storedsettingsfound">Nájdené uložené nastavenia</string> <string name="storedsettingsfound">Nájdené uložené nastavenia</string>
<string name="allow_hardware_pump_text">POZOR: Pokiaľ aktivujete a pripojíte skutočnú pumpu, AndroidAPS nakopíruje (a bude udržiavať) nastavenie bazálu z aktívneho profilu do pumpy. Nastavenie bazálu v pumpe bude prepísané. Pokiaľ si nieste istí, alebo nechcete prepísať bazály v pumpe, stlačte Zrušiť a opakujte prepnutie na inú pumpu neskôr.</string> <string name="allow_hardware_pump_text">POZOR: Pokiaľ aktivujete a pripojíte skutočnú pumpu, AndroidAPS nakopíruje (a bude udržiavať) nastavenie bazálu z aktívneho profilu do pumpy. Nastavenie bazálu v pumpe bude prepísané. Pokiaľ si nieste istí, alebo nechcete prepísať bazály v pumpe, stlačte Zrušiť a opakujte prepnutie na inú pumpu neskôr.</string>
<string name="error_adding_treatment_title">Dáta ošetrení neúplné</string> <string name="error_adding_treatment_title">Dáta ošetrení neúplné</string>
@ -877,6 +882,8 @@
<string name="ns_receive_profile_switch_summary">Prijať prepnutia profilov zadané prostredníctvom NS, alebo NSClienta</string> <string name="ns_receive_profile_switch_summary">Prijať prepnutia profilov zadané prostredníctvom NS, alebo NSClienta</string>
<string name="ns_receive_offline_event">Prijímať udalosti APS offline</string> <string name="ns_receive_offline_event">Prijímať udalosti APS offline</string>
<string name="ns_receive_offline_event_summary">Prijať APS offline udalosti zadané prostredníctvom NS, alebo NSClienta</string> <string name="ns_receive_offline_event_summary">Prijať APS offline udalosti zadané prostredníctvom NS, alebo NSClienta</string>
<string name="ns_receive_tbr_eb">Prijímať dočasný bazál a predĺžený bolus</string>
<string name="ns_receive_tbr_eb_summary">Prijať dočasný bazál a predĺžený bolus zadaný cez inú inštanciu</string>
<string name="ns_receive_insulin">Prijímať inzulín</string> <string name="ns_receive_insulin">Prijímať inzulín</string>
<string name="ns_receive_insulin_summary">Prijať inzulín vložený cez NS, alebo NSClient (nie je dodaný, iba započítaný do IOB)</string> <string name="ns_receive_insulin_summary">Prijať inzulín vložený cez NS, alebo NSClient (nie je dodaný, iba započítaný do IOB)</string>
<string name="ns_receive_carbs">Prijímať sacharidy</string> <string name="ns_receive_carbs">Prijímať sacharidy</string>
@ -969,4 +976,15 @@
<string name="wear_unknown_action_string">Neznámy príkaz k akcii:</string> <string name="wear_unknown_action_string">Neznámy príkaz k akcii:</string>
<string name="overview_editquickwizard_percentage">Percentuálny podiel</string> <string name="overview_editquickwizard_percentage">Percentuálny podiel</string>
<string name="app_default">Predvolené aplikáciou</string> <string name="app_default">Predvolené aplikáciou</string>
<string name="select_profile">Vyberte profil pre úpravu</string>
<string name="refresh_from_nightscout">Obnoviť z Nightscoutu</string>
<string name="remove_selected_items">Odstrániť vybrané položky</string>
<string name="select_for_removal">Vyberte pre odstránenie</string>
<string name="profile_changes">Zmeny profilu</string>
<string name="tempt_targets">Dočasné ciele</string>
<string name="carbs_and_bolus">Sacharidy a bolusy</string>
<string name="confirm_remove_multiple_items">Naozaj chcete odstrániť %1$d položku(y)</string>
<string name="hide_loop">Skryť uzavretý okruh</string>
<string name="show_loop">Zobraziť uzavretý okruh</string>
<string name="count_selected">Vybrané: %1$d</string>
</resources> </resources>

View file

@ -60,10 +60,10 @@
<string name="exercise_15g">等血糖值低于你的低血糖警戒线之后吃15克速升的活性碳水合物。</string> <string name="exercise_15g">等血糖值低于你的低血糖警戒线之后吃15克速升的活性碳水合物。</string>
<string name="exercise_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target</string> <string name="exercise_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target</string>
<string name="suspendloop_label">禁用/暂停闭环</string> <string name="suspendloop_label">禁用/暂停闭环</string>
<string name="suspendloop_doigetinsulin">在禁用/暂停闭环时,是否可以输注胰岛素?</string> <string name="suspendloop_doigetinsulin">在禁用/暂停闭环时,我是否接收了胰岛素输注?</string>
<string name="suspendloop_yes">是的,胰岛素基础率可以正常输注的</string> <string name="suspendloop_yes">是的,胰岛素基础率仍在继续输注</string>
<string name="suspendloop_no">不,胰岛素停止输注。</string> <string name="suspendloop_no">不,胰岛素停止输注。</string>
<string name="basaltest_label">Basal(基础率)ISF(胰岛素敏感系数)和I:C(胰岛素:碳水)测试</string> <string name="basaltest_label">Basal基础率ISF胰岛素敏感系数I:C或ICR碳水化合物系数的测试</string>
<string name="basaltest_when">什么时候需要修订这些值?</string> <string name="basaltest_when">什么时候需要修订这些值?</string>
<string name="basaltest_beforeloop">在开始闭环之前。</string> <string name="basaltest_beforeloop">在开始闭环之前。</string>
<string name="basaltest_havingregularhighlow">当经常出现高血糖或低血糖时。</string> <string name="basaltest_havingregularhighlow">当经常出现高血糖或低血糖时。</string>
@ -84,7 +84,7 @@
<string name="prerequisites_own670g">一台 MiniMed 670G 泵。</string> <string name="prerequisites_own670g">一台 MiniMed 670G 泵。</string>
<string name="prerequisites_hint1">https://androidaps.readthedocs.io/en/latest/EN/Module/module.html</string> <string name="prerequisites_hint1">https://androidaps.readthedocs.io/en/latest/EN/Module/module.html</string>
<string name="prerequisites_smartwatch">一个智能手表.</string> <string name="prerequisites_smartwatch">一个智能手表.</string>
<string name="prerequisites_supportedcgm">一个可正常使用的 CGM。</string> <string name="prerequisites_supportedcgm">受支持的CGM血糖监测产品</string>
<string name="prerequisites2_label">先决条件</string> <string name="prerequisites2_label">先决条件</string>
<string name="prerequisites2_what">什么是建立和使用 AndroidAPS的基本条件</string> <string name="prerequisites2_what">什么是建立和使用 AndroidAPS的基本条件</string>
<string name="prerequisites2_profile">验证参数信息用于个人配置文件如ISF胰岛素敏感度系数、I:C胰岛素碳水比率、基础率、DIA胰岛素作用持续时间等等</string> <string name="prerequisites2_profile">验证参数信息用于个人配置文件如ISF胰岛素敏感度系数、I:C胰岛素碳水比率、基础率、DIA胰岛素作用持续时间等等</string>
@ -93,9 +93,9 @@
<string name="prerequisites2_supportedcgm">一台安装了动态血糖监测应用或兼容软件的手机/设备,用于接收血糖数据。</string> <string name="prerequisites2_supportedcgm">一台安装了动态血糖监测应用或兼容软件的手机/设备,用于接收血糖数据。</string>
<string name="prerequisites2_hint1">https://androidaps.readthedocs.io/en/latest/EN/Module/module.html</string> <string name="prerequisites2_hint1">https://androidaps.readthedocs.io/en/latest/EN/Module/module.html</string>
<string name="update_label">更新 AndroidAPS</string> <string name="update_label">更新 AndroidAPS</string>
<string name="whatistrue">检查所有正确的答案.</string> <string name="whatistrue">选择所有正确的答案.</string>
<string name="update_git">您需要在您的计算机上安装和配置Git。</string> <string name="update_git">您需要在您的计算机上安装和配置Git。</string>
<string name="update_asap">更新的 AndroidAPS 版本发布时,先前的版本可能会在指定时间之后受到远程限制。</string> <string name="update_asap">AndroidAPS更新发布正式版本时,先前的版本可能会在指定时间之后受到远程限制。</string>
<string name="update_keys">您应该保存并记住密钥的存储位置,并使用相同地签名密钥进行更新,与您以前的安装一样。</string> <string name="update_keys">您应该保存并记住密钥的存储位置,并使用相同地签名密钥进行更新,与您以前的安装一样。</string>
<string name="update_neverupdate">如果该系统运作良好,就不要去更新系统。</string> <string name="update_neverupdate">如果该系统运作良好,就不要去更新系统。</string>
<string name="update_askfriend">如果您在构建应用时遇到困难,您可以安装一个由朋友构建的应用程序。</string> <string name="update_askfriend">如果您在构建应用时遇到困难,您可以安装一个由朋友构建的应用程序。</string>
@ -119,7 +119,7 @@
<string name="sensitivity_label">敏感度插件</string> <string name="sensitivity_label">敏感度插件</string>
<string name="sensitivity_which">选择所有正确的答案。</string> <string name="sensitivity_which">选择所有正确的答案。</string>
<string name="sensitivity_adjust">灵敏度插件允许AndroidAPS临时调整胰岛素敏感度的短暂变化(例如激素变化或与输液部位吸收相关的问题)。</string> <string name="sensitivity_adjust">灵敏度插件允许AndroidAPS临时调整胰岛素敏感度的短暂变化(例如激素变化或与输液部位吸收相关的问题)。</string>
<string name="sensitivity_edit">灵敏度插件为用户提供基础率、 I:C比率和 ISF 的更改建议,可用来编辑配置文件。</string> <string name="sensitivity_edit">灵敏度插件为用户提供basal基础率I:C碳水化合物系数和ISF胰岛素敏感系数的更改建议,可用来编辑配置文件。</string>
<string name="sensitivity_cannula">记录输注导管更换会将Autosens比率重置回100%。</string> <string name="sensitivity_cannula">记录输注导管更换会将Autosens比率重置回100%。</string>
<string name="sensitivity_time">一些插件选项具有可配置的时间范围,可由用户设置。</string> <string name="sensitivity_time">一些插件选项具有可配置的时间范围,可由用户设置。</string>
<string name="sensitivity_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html</string> <string name="sensitivity_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html</string>
@ -195,13 +195,13 @@
<string name="profileswitchtime_iwant">如果您比平常早起 2 个小时您应该如何通知AndroidAPS应对个人日程表中的更改?</string> <string name="profileswitchtime_iwant">如果您比平常早起 2 个小时您应该如何通知AndroidAPS应对个人日程表中的更改?</string>
<string name="profileswitchtime_2">以增加2小时的方式启动个人配置文件切换</string> <string name="profileswitchtime_2">以增加2小时的方式启动个人配置文件切换</string>
<string name="profileswitchtime__2">以减少2小时的方式启动个人配置文件切换</string> <string name="profileswitchtime__2">以减少2小时的方式启动个人配置文件切换</string>
<string name="profileswitchtime_tt">设置一个马上吃饭的临时的目标血糖值。</string> <string name="profileswitchtime_tt">设置一个马上吃饭,临时的血糖目标值。</string>
<string name="profileswitchtime_100">将配置文件切换到100%以上。</string> <string name="profileswitchtime_100">将配置文件切换到100%以上。</string>
<string name="profileswitchtime_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html?highlight=profilewitch#timeshift</string> <string name="profileswitchtime_hint1">https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html?highlight=profilewitch#timeshift</string>
<string name="profileswitch4_label">修改配置文件</string> <string name="profileswitch4_label">修改配置文件</string>
<string name="profileswitch4_rates">基础率、胰岛素敏感系数ISF、胰岛素和碳水比率I:C等在配置文件中设定。</string> <string name="profileswitch4_rates">Basal基础率ISF胰岛素敏感系数I:C碳水化合物系数等应该在配置文件中设定。</string>
<string name="profileswitch4_internet">激活对Nightscout配置文件的更改需要您的AndroidAPS 手机启用互联网连接。</string> <string name="profileswitch4_internet">激活对Nightscout配置文件的更改需要您的AndroidAPS 手机启用互联网连接。</string>
<string name="profileswitch4_sufficient">编辑配置文件并修改参数,足以进行任何更改</string> <string name="profileswitch4_sufficient">编辑配置文件进行参数的修改,足以适应任何变化</string>
<string name="profileswitch4_multi">可以设置和选择多个配置文件,以适应不断变化的环境(例如激素变化、轮班工作、工作日/周末生活方式)。</string> <string name="profileswitch4_multi">可以设置和选择多个配置文件,以适应不断变化的环境(例如激素变化、轮班工作、工作日/周末生活方式)。</string>
<string name="basalhelp_hint1">https://androidaps.readthedocs.io/en/latest/EN/Module/module.html#good-individual-dosage-algorithm-for-your-diabetes-therapy</string> <string name="basalhelp_hint1">https://androidaps.readthedocs.io/en/latest/EN/Module/module.html#good-individual-dosage-algorithm-for-your-diabetes-therapy</string>
<string name="basalhelp_label">帮助调整基础率</string> <string name="basalhelp_label">帮助调整基础率</string>

View file

@ -136,6 +136,7 @@
<item>@string/biometric</item> <item>@string/biometric</item>
<item>@string/master_password</item> <item>@string/master_password</item>
<item>@string/custom_password</item> <item>@string/custom_password</item>
<item>@string/custom_pin</item>
</string-array> </string-array>
<string-array name="protectiontypeValues"> <string-array name="protectiontypeValues">
@ -143,6 +144,7 @@
<item>1</item> <item>1</item>
<item>2</item> <item>2</item>
<item>3</item> <item>3</item>
<item>4</item>
</string-array> </string-array>
</resources> </resources>

View file

@ -40,11 +40,6 @@
<color name="colorScheduled">#de7550</color> <color name="colorScheduled">#de7550</color>
<color name="colorActive">#25912e</color> <color name="colorActive">#25912e</color>
<color name="notificationUrgent">#ff0400</color>
<color name="notificationNormal">#ff5e55</color>
<color name="notificationLow">#ff827c</color>
<color name="notificationInfo">#009705</color>
<color name="deviationgrey">#c8666666</color> <color name="deviationgrey">#c8666666</color>
<color name="deviationgreen">#7200FF00</color> <color name="deviationgreen">#7200FF00</color>
<color name="deviationred">#72FF0000</color> <color name="deviationred">#72FF0000</color>

View file

@ -104,11 +104,11 @@
<string name="troubleshooting_wheretoask">Where can you look for help with AndroidAPS?</string> <string name="troubleshooting_wheretoask">Where can you look for help with AndroidAPS?</string>
<string name="troubleshooting_fb">You can ask for advice in the AndroidAPS Users Facebook group.</string> <string name="troubleshooting_fb">You can ask for advice in the AndroidAPS Users Facebook group.</string>
<string name="troubleshooting_wiki">You should read (and re-read) the AndroidAPS documentation.</string> <string name="troubleshooting_wiki">You should read (and re-read) the AndroidAPS documentation.</string>
<string name="troubleshooting_gitter">You can ask for advice and log technical problems or issues in the AndroidAPS Gitter room.</string> <string name="troubleshooting_gitter">You can ask for advice and log technical problems or issues in the AndroidAPS Discord.</string>
<string name="troubleshooting_yourendo">You should ask your diabetes clinic/endocrinologist.</string> <string name="troubleshooting_yourendo">You should ask your diabetes clinic/endocrinologist.</string>
<string name="troubleshooting_hint1">https://androidaps.readthedocs.io/en/latest/EN/Installing-AndroidAPS/Update-to-new-version.html#troubleshooting</string> <string name="troubleshooting_hint1">https://androidaps.readthedocs.io/en/latest/EN/Installing-AndroidAPS/Update-to-new-version.html#troubleshooting</string>
<string name="troubleshooting_hint2">https://www.facebook.com/groups/AndroidAPSUsers/</string> <string name="troubleshooting_hint2">https://www.facebook.com/groups/AndroidAPSUsers/</string>
<string name="troubleshooting_hint3">https://gitter.im/MilosKozak/AndroidAPS</string> <string name="troubleshooting_hint3">https://discord.gg/4fQUWHZ4Mw</string>
<string name="insulin_label">Insulin Plugins</string> <string name="insulin_label">Insulin Plugins</string>
<string name="insulin_ultrarapid">Which insulin should you use with the Ultra-Rapid Oref plugin?</string> <string name="insulin_ultrarapid">Which insulin should you use with the Ultra-Rapid Oref plugin?</string>
<string name="insulin_fiasp">Fiasp®</string> <string name="insulin_fiasp">Fiasp®</string>

View file

@ -46,10 +46,13 @@
android:title="@string/settings_protection" /> android:title="@string/settings_protection" />
<Preference <Preference
android:inputType="textPassword"
android:key="@string/key_settings_password" android:key="@string/key_settings_password"
android:title="@string/settings_password" /> android:title="@string/settings_password" />
<Preference
android:key="@string/key_settings_pin"
android:title="@string/settings_pin" />
<ListPreference <ListPreference
android:defaultValue="0" android:defaultValue="0"
android:entries="@array/protectiontype" android:entries="@array/protectiontype"
@ -58,10 +61,13 @@
android:title="@string/application_protection" /> android:title="@string/application_protection" />
<Preference <Preference
android:inputType="textPassword"
android:key="@string/key_application_password" android:key="@string/key_application_password"
android:title="@string/application_password" /> android:title="@string/application_password" />
<Preference
android:key="@string/key_application_pin"
android:title="@string/application_pin" />
<ListPreference <ListPreference
android:defaultValue="0" android:defaultValue="0"
android:entries="@array/protectiontype" android:entries="@array/protectiontype"
@ -70,10 +76,13 @@
android:title="@string/bolus_protection" /> android:title="@string/bolus_protection" />
<Preference <Preference
android:inputType="textPassword"
android:key="@string/key_bolus_password" android:key="@string/key_bolus_password"
android:title="@string/bolus_password" /> android:title="@string/bolus_password" />
<Preference
android:key="@string/key_bolus_pin"
android:title="@string/bolus_pin" />
</PreferenceCategory> </PreferenceCategory>
<info.nightscout.androidaps.skins.SkinListPreference <info.nightscout.androidaps.skins.SkinListPreference

View file

@ -1415,7 +1415,7 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
@NonNull @Override @NonNull @Override
public Constraint<Double> applyMaxIOBConstraints(@NonNull Constraint<Double> maxIob) { public Constraint<Double> applyMaxIOBConstraints(@NonNull Constraint<Double> maxIob) {
if (lowSuspendOnlyLoopEnforcedUntil > System.currentTimeMillis()) if (lowSuspendOnlyLoopEnforcedUntil > System.currentTimeMillis())
maxIob.setIfSmaller(getAapsLogger(), 0d, String.format(getRh().gs(R.string.limitingmaxiob), 0d, getRh().gs(R.string.unsafeusage)), this); maxIob.setIfSmaller(getAapsLogger(), 0d, getRh().gs(R.string.limitingmaxiob, 0d, getRh().gs(R.string.unsafeusage)), this);
return maxIob; return maxIob;
} }

View file

@ -48,7 +48,7 @@
<string name="combo_check_date">O último bólus tem mais de 24 horas ou está no futuro. Por favor, verifique se a data está definida corretamente.</string> <string name="combo_check_date">O último bólus tem mais de 24 horas ou está no futuro. Por favor, verifique se a data está definida corretamente.</string>
<string name="combo_suspious_bolus_time">Hora/data da entrega do bólus na bomba parece errado, insulina ativa parece estar provavelmente incorreto. Verifique hora/data na bomba.</string> <string name="combo_suspious_bolus_time">Hora/data da entrega do bólus na bomba parece errado, insulina ativa parece estar provavelmente incorreto. Verifique hora/data na bomba.</string>
<string name="combo_bolus_count">Contagem Bólus</string> <string name="combo_bolus_count">Contagem Bólus</string>
<string name="combo_tbr_count">Contagem Basal Teporária</string> <string name="combo_tbr_count">Contagem Basal Temporária</string>
<string name="bolusstopped">Bolus interrompido</string> <string name="bolusstopped">Bolus interrompido</string>
<string name="bolusstopping">Interrompendo bolus</string> <string name="bolusstopping">Interrompendo bolus</string>
<string name="pump_commerror_label">Contagem de erro comunicada</string> <string name="pump_commerror_label">Contagem de erro comunicada</string>

View file

@ -51,4 +51,10 @@
<string name="combo_tbr_count">Počet dočasných bazálov</string> <string name="combo_tbr_count">Počet dočasných bazálov</string>
<string name="bolusstopped">Bolus zastavený</string> <string name="bolusstopped">Bolus zastavený</string>
<string name="bolusstopping">Zastavenie bolusu</string> <string name="bolusstopping">Zastavenie bolusu</string>
<string name="pump_commerror_label">Počet chýb komun.</string>
<string name="show_comm_error_count_title">Zobr. počet chýb komun.</string>
<string name="show_comm_error_count_summary">Zobrazí počet chýb pri komunikácii s Ruffy. Číslo vyšše, ako 0 obvykle naznačuje problémy s Ruffy (môže byť nutné reštartovať).</string>
<string name="combo_error_display_never">Nikdy</string>
<string name="combo_error_display_error">Keď dôjde k chybe</string>
<string name="combo_error_display_always">Vždy</string>
</resources> </resources>

View file

@ -293,8 +293,8 @@ class ProfileViewerDialog : DaggerDialogFragment() {
val val1h = profile1.getTargetHighMgdlTimeFromMidnight(hour * 60 * 60) val val1h = profile1.getTargetHighMgdlTimeFromMidnight(hour * 60 * 60)
val val2l = profile2.getTargetLowMgdlTimeFromMidnight(hour * 60 * 60) val val2l = profile2.getTargetLowMgdlTimeFromMidnight(hour * 60 * 60)
val val2h = profile2.getTargetHighMgdlTimeFromMidnight(hour * 60 * 60) val val2h = profile2.getTargetHighMgdlTimeFromMidnight(hour * 60 * 60)
val txt1 = dateUtil.format_HH_MM(hour * 60 * 60) + " " + Profile.toUnitsString(val1l, val1l * Constants.MGDL_TO_MMOLL, units) + " - " + Profile.toUnitsString(val1h, val1h * Constants.MGDL_TO_MMOLL, units) + " " + units val txt1 = dateUtil.format_HH_MM(hour * 60 * 60) + " " + Profile.toUnitsString(val1l, val1l * Constants.MGDL_TO_MMOLL, units) + " - " + Profile.toUnitsString(val1h, val1h * Constants.MGDL_TO_MMOLL, units) + " " + units.asText
val txt2 = dateUtil.format_HH_MM(hour * 60 * 60) + " " + Profile.toUnitsString(val2l, val2l * Constants.MGDL_TO_MMOLL, units) + " - " + Profile.toUnitsString(val2h, val2h * Constants.MGDL_TO_MMOLL, units) + " " + units val txt2 = dateUtil.format_HH_MM(hour * 60 * 60) + " " + Profile.toUnitsString(val2l, val2l * Constants.MGDL_TO_MMOLL, units) + " - " + Profile.toUnitsString(val2h, val2h * Constants.MGDL_TO_MMOLL, units) + " " + units.asText
if (val1l != prev1l || val1h != prev1h || val2l != prev2l || val2h != prev2h) { if (val1l != prev1l || val1h != prev1h || val2l != prev2l || val2h != prev2h) {
s.append(formatColors(txt1, txt2)) s.append(formatColors(txt1, txt2))
s.append("<br>") s.append("<br>")

View file

@ -47,7 +47,7 @@ class EventPumpStatusChanged : EventStatus {
// status for startup wizard // status for startup wizard
override fun getStatus(rh: ResourceHelper): String { override fun getStatus(rh: ResourceHelper): String {
return when (status) { return when (status) {
Status.CONNECTING -> String.format(rh.gs(R.string.connectingfor), secondsElapsed) Status.CONNECTING -> rh.gs(R.string.connectingfor, secondsElapsed)
Status.HANDSHAKING -> rh.gs(R.string.handshaking) Status.HANDSHAKING -> rh.gs(R.string.handshaking)
Status.CONNECTED -> rh.gs(R.string.connected) Status.CONNECTED -> rh.gs(R.string.connected)
Status.PERFORMING -> performingAction Status.PERFORMING -> performingAction

View file

@ -97,7 +97,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) {
} }
val carbsRequiredText: String val carbsRequiredText: String
get() = String.format(rh.gs(R.string.carbsreq), carbsReq, carbsReqWithin) get() = rh.gs(R.string.carbsreq, carbsReq, carbsReqWithin)
override fun toString(): String { override fun toString(): String {
val pump = activePlugin.activePump val pump = activePlugin.activePump

View file

@ -94,9 +94,9 @@ class HardLimits @Inject constructor(
if (newValue < lowLimit || newValue > highLimit) { if (newValue < lowLimit || newValue > highLimit) {
newValue = max(newValue, lowLimit) newValue = max(newValue, lowLimit)
newValue = min(newValue, highLimit) newValue = min(newValue, highLimit)
var msg = String.format(rh.gs(R.string.valueoutofrange), rh.gs(valueName)) var msg = rh.gs(R.string.valueoutofrange, rh.gs(valueName))
msg += ".\n" msg += ".\n"
msg += String.format(rh.gs(R.string.valuelimitedto), value, newValue) msg += rh.gs(R.string.valuelimitedto, value, newValue)
aapsLogger.error(msg) aapsLogger.error(msg)
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(msg)).subscribe() disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(msg)).subscribe()
ToastUtils.showToastInUiThread(context, rxBus, msg, R.raw.error) ToastUtils.showToastInUiThread(context, rxBus, msg, R.raw.error)

View file

@ -2,8 +2,12 @@ package info.nightscout.androidaps.utils.protection
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.text.InputType
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.EditText import android.widget.EditText
import android.widget.TextView import android.widget.TextView
import androidx.annotation.StringRes import androidx.annotation.StringRes
@ -33,13 +37,12 @@ class PasswordCheck @Inject constructor(
Asks for "managed" kind of password, checking if it is valid. Asks for "managed" kind of password, checking if it is valid.
*/ */
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
fun queryPassword(context: Context, @StringRes labelId: Int, @StringRes preference: Int, ok: ((String) -> Unit)?, cancel: (() -> Unit)? = null, fail: (() -> Unit)? = null) { fun queryPassword(context: Context, @StringRes labelId: Int, @StringRes preference: Int, ok: ((String) -> Unit)?, cancel: (() -> Unit)? = null, fail: (() -> Unit)? = null, pinInput: Boolean = false) {
val password = sp.getString(preference, "") val password = sp.getString(preference, "")
if (password == "") { if (password == "") {
ok?.invoke("") ok?.invoke("")
return return
} }
val promptsView = LayoutInflater.from(context).inflate(R.layout.passwordprompt, null) val promptsView = LayoutInflater.from(context).inflate(R.layout.passwordprompt, null)
val alertDialogBuilder = AlertDialogHelper.Builder(context, R.style.DialogTheme) val alertDialogBuilder = AlertDialogHelper.Builder(context, R.style.DialogTheme)
alertDialogBuilder.setView(promptsView) alertDialogBuilder.setView(promptsView)
@ -48,40 +51,67 @@ class PasswordCheck @Inject constructor(
val userInput2 = promptsView.findViewById<View>(R.id.password_prompt_pass_confirm) as EditText val userInput2 = promptsView.findViewById<View>(R.id.password_prompt_pass_confirm) as EditText
userInput2.visibility = View.GONE userInput2.visibility = View.GONE
if (pinInput) {
userInput.setHint(R.string.pin_hint)
userInput.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
}
val autoFillHintPasswordKind = context.getString(preference) val autoFillHintPasswordKind = context.getString(preference)
userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}") userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}")
userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES
fun validatePassword(): Boolean {
val enteredPassword = userInput.text.toString()
if (cryptoUtil.checkPassword(enteredPassword, password)) {
val im = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
im.hideSoftInputFromWindow(userInput.windowToken, 0)
ok?.invoke(enteredPassword)
return true
}
val msg = if (pinInput) R.string.wrongpin else R.string.wrongpassword
ToastUtils.errorToast(context, context.getString(msg))
fail?.invoke()
return false
}
alertDialogBuilder alertDialogBuilder
.setCancelable(false) .setCancelable(false)
.setCustomTitle(AlertDialogHelper.buildCustomTitle(context, context.getString(labelId), R.drawable.ic_header_key)) .setCustomTitle(AlertDialogHelper.buildCustomTitle(context, context.getString(labelId), R.drawable.ic_header_key))
.setPositiveButton(context.getString(R.string.ok)) { _, _ -> .setPositiveButton(context.getString(R.string.ok)) { _, _ -> validatePassword() }
val enteredPassword = userInput.text.toString() .setNegativeButton(context.getString(R.string.cancel)) { dialog, _ ->
if (cryptoUtil.checkPassword(enteredPassword, password)) ok?.invoke(enteredPassword)
else {
ToastUtils.errorToast(context, context.getString(R.string.wrongpassword))
fail?.invoke()
}
}
.setNegativeButton(context.getString(R.string.cancel)
) { dialog, _ ->
cancel?.invoke() cancel?.invoke()
dialog.cancel() dialog.cancel()
} }
alertDialogBuilder.create().show() val alert = alertDialogBuilder.create().apply {
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
show()
}
userInput.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
if (validatePassword())
alert.dismiss()
true
} else {
false
}
}
} }
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
fun setPassword(context: Context, @StringRes labelId: Int, @StringRes preference: Int, ok: ((String) -> Unit)? = null, cancel: (() -> Unit)? = null, clear: (() -> Unit)? = null) { fun setPassword(context: Context, @StringRes labelId: Int, @StringRes preference: Int, ok: ((String) -> Unit)? = null, cancel: (() -> Unit)? = null, clear: (() -> Unit)? = null, pinInput: Boolean = false) {
val promptsView = LayoutInflater.from(context).inflate(R.layout.passwordprompt, null) val promptsView = LayoutInflater.from(context).inflate(R.layout.passwordprompt, null)
val alertDialogBuilder = AlertDialogHelper.Builder(context, R.style.DialogTheme) val alertDialogBuilder = AlertDialogHelper.Builder(context, R.style.DialogTheme)
alertDialogBuilder.setView(promptsView) alertDialogBuilder.setView(promptsView)
val userInput = promptsView.findViewById<View>(R.id.password_prompt_pass) as EditText val userInput = promptsView.findViewById<View>(R.id.password_prompt_pass) as EditText
val userInput2 = promptsView.findViewById<View>(R.id.password_prompt_pass_confirm) as EditText val userInput2 = promptsView.findViewById<View>(R.id.password_prompt_pass_confirm) as EditText
if (pinInput) {
userInput.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
userInput2.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
userInput.setHint(R.string.pin_hint)
userInput2.setHint(R.string.pin_hint)
}
val autoFillHintPasswordKind = context.getString(preference) val autoFillHintPasswordKind = context.getString(preference)
userInput.setAutofillHints(AUTOFILL_HINT_NEW_PASSWORD, "aaps_${autoFillHintPasswordKind}") userInput.setAutofillHints(AUTOFILL_HINT_NEW_PASSWORD, "aaps_${autoFillHintPasswordKind}")
userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES
@ -93,18 +123,22 @@ class PasswordCheck @Inject constructor(
val enteredPassword = userInput.text.toString() val enteredPassword = userInput.text.toString()
val enteredPassword2 = userInput2.text.toString() val enteredPassword2 = userInput2.text.toString()
if (enteredPassword != enteredPassword2) { if (enteredPassword != enteredPassword2) {
ToastUtils.errorToast(context, context.getString(R.string.passwords_dont_match)) val msg = if (pinInput) R.string.pin_dont_match else R.string.passwords_dont_match
ToastUtils.errorToast(context, context.getString(msg))
} else if (enteredPassword.isNotEmpty()) { } else if (enteredPassword.isNotEmpty()) {
sp.putString(preference, cryptoUtil.hashPassword(enteredPassword)) sp.putString(preference, cryptoUtil.hashPassword(enteredPassword))
ToastUtils.okToast(context, context.getString(R.string.password_set)) val msg = if (pinInput) R.string.pin_set else R.string.password_set
ToastUtils.okToast(context, context.getString(msg))
ok?.invoke(enteredPassword) ok?.invoke(enteredPassword)
} else { } else {
if (sp.contains(preference)) { if (sp.contains(preference)) {
sp.remove(preference) sp.remove(preference)
ToastUtils.graphicalToast(context, context.getString(R.string.password_cleared), R.drawable.ic_toast_delete_confirm) val msg = if (pinInput) R.string.pin_cleared else R.string.password_cleared
ToastUtils.graphicalToast(context, context.getString(msg), R.drawable.ic_toast_delete_confirm)
clear?.invoke() clear?.invoke()
} else { } else {
ToastUtils.warnToast(context, context.getString(R.string.password_not_changed)) val msg = if (pinInput) R.string.pin_not_changed else R.string.password_not_changed
ToastUtils.warnToast(context, context.getString(msg))
cancel?.invoke() cancel?.invoke()
} }
} }
@ -112,7 +146,8 @@ class PasswordCheck @Inject constructor(
} }
.setNegativeButton(context.getString(R.string.cancel) .setNegativeButton(context.getString(R.string.cancel)
) { dialog, _ -> ) { dialog, _ ->
ToastUtils.infoToast(context, context.getString(R.string.password_not_changed)) val msg = if (pinInput) R.string.pin_not_changed else R.string.password_not_changed
ToastUtils.infoToast(context, context.getString(msg))
cancel?.invoke() cancel?.invoke()
dialog.cancel() dialog.cancel()
} }
@ -149,20 +184,35 @@ class PasswordCheck @Inject constructor(
userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}") userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}")
userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES
alertDialogBuilder fun validatePassword() {
.setCancelable(false)
.setCustomTitle(AlertDialogHelper.buildCustomTitle(context, context.getString(labelId), R.drawable.ic_header_key))
.setPositiveButton(context.getString(R.string.ok)) { _, _ ->
val enteredPassword = userInput.text.toString() val enteredPassword = userInput.text.toString()
ok?.invoke(enteredPassword) ok?.invoke(enteredPassword)
} }
alertDialogBuilder
.setCancelable(false)
.setCustomTitle(AlertDialogHelper.buildCustomTitle(context, context.getString(labelId), R.drawable.ic_header_key))
.setPositiveButton(context.getString(R.string.ok)) { _, _ -> validatePassword() }
.setNegativeButton(context.getString(R.string.cancel) .setNegativeButton(context.getString(R.string.cancel)
) { dialog, _ -> ) { dialog, _ ->
cancel?.invoke() cancel?.invoke()
dialog.cancel() dialog.cancel()
} }
alertDialogBuilder.create().show() val alert = alertDialogBuilder.create().apply {
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
show()
}
userInput.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
validatePassword()
alert.dismiss()
true
} else {
false
}
}
} }
/** /**

View file

@ -22,7 +22,8 @@ class ProtectionCheck @Inject constructor(
NONE, NONE,
BIOMETRIC, BIOMETRIC,
MASTER_PASSWORD, MASTER_PASSWORD,
CUSTOM_PASSWORD CUSTOM_PASSWORD,
CUSTOM_PIN
} }
private val passwordsResourceIDs = listOf( private val passwordsResourceIDs = listOf(
@ -30,22 +31,33 @@ class ProtectionCheck @Inject constructor(
R.string.key_application_password, R.string.key_application_password,
R.string.key_bolus_password) R.string.key_bolus_password)
private val pinsResourceIDs = listOf(
R.string.key_settings_pin,
R.string.key_application_pin,
R.string.key_bolus_pin)
private val protectionTypeResourceIDs = listOf( private val protectionTypeResourceIDs = listOf(
R.string.key_settings_protection, R.string.key_settings_protection,
R.string.key_application_protection, R.string.key_application_protection,
R.string.key_bolus_protection) R.string.key_bolus_protection)
private val titleResourceIDs = listOf( private val titlePassResourceIDs = listOf(
R.string.settings_password, R.string.settings_password,
R.string.application_password, R.string.application_password,
R.string.bolus_password) R.string.bolus_password)
private val titlePinResourceIDs = listOf(
R.string.settings_pin,
R.string.application_pin,
R.string.bolus_pin)
fun isLocked(protection: Protection): Boolean { fun isLocked(protection: Protection): Boolean {
return when (ProtectionType.values()[sp.getInt(protectionTypeResourceIDs[protection.ordinal], ProtectionType.NONE.ordinal)]) { return when (ProtectionType.values()[sp.getInt(protectionTypeResourceIDs[protection.ordinal], ProtectionType.NONE.ordinal)]) {
ProtectionType.NONE -> false ProtectionType.NONE -> false
ProtectionType.BIOMETRIC -> true ProtectionType.BIOMETRIC -> true
ProtectionType.MASTER_PASSWORD -> sp.getString(R.string.key_master_password, "") != "" ProtectionType.MASTER_PASSWORD -> sp.getString(R.string.key_master_password, "") != ""
ProtectionType.CUSTOM_PASSWORD -> sp.getString(passwordsResourceIDs[protection.ordinal], "") != "" ProtectionType.CUSTOM_PASSWORD -> sp.getString(passwordsResourceIDs[protection.ordinal], "") != ""
ProtectionType.CUSTOM_PIN -> sp.getString(pinsResourceIDs[protection.ordinal], "") != ""
} }
} }
@ -55,11 +67,13 @@ class ProtectionCheck @Inject constructor(
ProtectionType.NONE -> ProtectionType.NONE ->
ok?.run() ok?.run()
ProtectionType.BIOMETRIC -> ProtectionType.BIOMETRIC ->
BiometricCheck.biometricPrompt(activity, titleResourceIDs[protection.ordinal], ok, cancel, fail, passwordCheck) BiometricCheck.biometricPrompt(activity, titlePassResourceIDs[protection.ordinal], ok, cancel, fail, passwordCheck)
ProtectionType.MASTER_PASSWORD -> ProtectionType.MASTER_PASSWORD ->
passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { ok?.run() }, { cancel?.run() }, { fail?.run() }) passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { ok?.run() }, { cancel?.run() }, { fail?.run() })
ProtectionType.CUSTOM_PASSWORD -> ProtectionType.CUSTOM_PASSWORD ->
passwordCheck.queryPassword(activity, titleResourceIDs[protection.ordinal], passwordsResourceIDs[protection.ordinal], { ok?.run() }, { cancel?.run() }, { fail?.run() }) passwordCheck.queryPassword(activity, titlePassResourceIDs[protection.ordinal], passwordsResourceIDs[protection.ordinal], { ok?.run() }, { cancel?.run() }, { fail?.run() })
ProtectionType.CUSTOM_PIN ->
passwordCheck.queryPassword(activity, titlePinResourceIDs[protection.ordinal], pinsResourceIDs[protection.ordinal], { ok?.run() }, { cancel?.run() }, { fail?.run() }, true)
} }
} }
} }

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.utils.resources package info.nightscout.androidaps.utils.resources
import android.content.Context
import android.content.res.AssetFileDescriptor import android.content.res.AssetFileDescriptor
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
@ -11,7 +12,7 @@ interface ResourceHelper {
fun gs(@StringRes id: Int, vararg args: Any?): String fun gs(@StringRes id: Int, vararg args: Any?): String
fun gq(@PluralsRes id: Int, quantity: Int, vararg args: Any?): String fun gq(@PluralsRes id: Int, quantity: Int, vararg args: Any?): String
fun gsNotLocalised(@StringRes id: Int, vararg args: Any?): String fun gsNotLocalised(@StringRes id: Int, vararg args: Any?): String
fun gc(@ColorRes id: Int): Int @ColorInt fun gc(@ColorRes id: Int): Int
fun gd(@DrawableRes id: Int): Drawable? fun gd(@DrawableRes id: Int): Drawable?
fun gb(@BoolRes id :Int) : Boolean fun gb(@BoolRes id :Int) : Boolean
fun gcs(@ColorRes id: Int): String fun gcs(@ColorRes id: Int): String
@ -23,4 +24,13 @@ interface ResourceHelper {
fun dpToPx(dp: Int): Int fun dpToPx(dp: Int): Int
fun dpToPx(dp: Float): Int fun dpToPx(dp: Float): Int
fun shortTextMode(): Boolean fun shortTextMode(): Boolean
/**
* Get Attribute Color based on theme style
*/
@ColorInt fun gac(@AttrRes attributeId: Int): Int
/**
* Get Attribute Color based on theme style for specified context
*/
@ColorInt fun gac(context: Context, @AttrRes attributeId: Int): Int
} }

View file

@ -0,0 +1,13 @@
package info.nightscout.androidaps.utils.resources
import android.content.Context
import android.util.TypedValue
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
@ColorInt
fun Context.getThemeColor(@AttrRes attribute: Int) =
TypedValue().let {
theme.resolveAttribute(attribute, it, true)
it.data
}

View file

@ -9,6 +9,7 @@ import android.graphics.BitmapFactory
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.util.DisplayMetrics import android.util.DisplayMetrics
import androidx.annotation.* import androidx.annotation.*
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
@ -83,4 +84,10 @@ class ResourceHelperImplementation @Inject constructor(private val context: Cont
} }
override fun shortTextMode(): Boolean = !gb(R.bool.isTablet) override fun shortTextMode(): Boolean = !gb(R.bool.isTablet)
override fun gac(context: Context, attributeId: Int): Int =
context.getThemeColor(attributeId)
override fun gac(attributeId: Int): Int =
ContextThemeWrapper(this.context, R.style.AppTheme).getThemeColor(attributeId)
} }

View file

@ -14,8 +14,7 @@
android:paddingEnd="10dp" android:paddingEnd="10dp"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/warningAccentText" android:textColor="@color/warningAccentText"
android:visibility="gone" android:visibility="gone" />
/>
<EditText <EditText
android:id="@+id/password_prompt_pass" android:id="@+id/password_prompt_pass"

View file

@ -4,6 +4,7 @@
<!-- General--> <!-- General-->
<string name="refresh">Obnoviť</string> <string name="refresh">Obnoviť</string>
<string name="error">Chyba</string> <string name="error">Chyba</string>
<string name="save">Uložiť</string>
<string name="not_set_short">Nenastavené</string> <string name="not_set_short">Nenastavené</string>
<string name="failedupdatebasalprofile">Chyba pri aktualizovaní bazálneho profilu</string> <string name="failedupdatebasalprofile">Chyba pri aktualizovaní bazálneho profilu</string>
<string name="profile_set_ok">Bazálny profil v pumpe aktualizovaný</string> <string name="profile_set_ok">Bazálny profil v pumpe aktualizovaný</string>
@ -376,6 +377,7 @@
<string name="uel_stat_reset">RESET ŠTATISTÍK</string> <string name="uel_stat_reset">RESET ŠTATISTÍK</string>
<string name="uel_delete_logs">VYMAZAŤ LOGY</string> <string name="uel_delete_logs">VYMAZAŤ LOGY</string>
<string name="uel_delete_future_treatments">VYMAZAŤ BUDÚCE OŠETRENIA</string> <string name="uel_delete_future_treatments">VYMAZAŤ BUDÚCE OŠETRENIA</string>
<string name="delete_future_treatments">Odstrániť ošetrenia v budúcnosti</string>
<string name="uel_export_settings">EXPORTOVAŤ NASTAVENIA</string> <string name="uel_export_settings">EXPORTOVAŤ NASTAVENIA</string>
<string name="uel_import_settings">IMPORTOVAŤ NASTAVENIA</string> <string name="uel_import_settings">IMPORTOVAŤ NASTAVENIA</string>
<string name="uel_reset_databases">RESETOVAŤ DATABÁZY</string> <string name="uel_reset_databases">RESETOVAŤ DATABÁZY</string>

View file

@ -7,4 +7,12 @@
<declare-styleable name="NumberPicker"> <declare-styleable name="NumberPicker">
<attr name="customContentDescription" format="string" /> <attr name="customContentDescription" format="string" />
</declare-styleable> </declare-styleable>
<!---Notification -->
<attr name="notificationUrgent" format="reference|color" />
<attr name="notificationNormal" format="reference|color" />
<attr name="notificationLow" format="reference|color" />
<attr name="notificationInfo" format="reference|color" />
<attr name="notificationAnnouncement" format="reference|color" />
</resources> </resources>

View file

@ -92,8 +92,14 @@
<color name="weekdayOutline">#1ea3e5</color> <color name="weekdayOutline">#1ea3e5</color>
<color name="weekendOutline">#1e88e5</color> <color name="weekendOutline">#1e88e5</color>
<!-- CareportalEvent--> <!-- Notification-->
<color name="notificationAnnouncement">#FF8C00</color> <color name="notificationAnnouncement">#FF8C00</color>
<color name="notificationUrgent">#ff0400</color>
<color name="notificationNormal">#ff5e55</color>
<color name="notificationLow">#ff827c</color>
<!-- Green Colors -->
<color name="notificationInfo">#009705</color>
<!-- Toasts--> <!-- Toasts-->
<color name="toastBorder">#666666</color> <color name="toastBorder">#666666</color>

View file

@ -7,11 +7,15 @@
<string name="bolus_protection">Bolus protection</string> <string name="bolus_protection">Bolus protection</string>
<string name="master_password">Master password</string> <string name="master_password">Master password</string>
<string name="settings_password">Settings password</string> <string name="settings_password">Settings password</string>
<string name="settings_pin">Settings PIN</string>
<string name="application_password">Application password</string> <string name="application_password">Application password</string>
<string name="application_pin">Application PIN</string>
<string name="bolus_password">Bolus password</string> <string name="bolus_password">Bolus password</string>
<string name="bolus_pin">Bolus PIN</string>
<string name="unlock_settings">Unlock settings</string> <string name="unlock_settings">Unlock settings</string>
<string name="biometric">Biometric</string> <string name="biometric">Biometric</string>
<string name="custom_password">Custom password</string> <string name="custom_password">Custom password</string>
<string name="custom_pin">Custom PIN</string>
<string name="noprotection">No protection</string> <string name="noprotection">No protection</string>
<string name="protection">Protection</string> <string name="protection">Protection</string>
<string name="master_password_missing">Master password is not set!\n\nPlease set your Master password in Preferences (%1$s &#8594; %2$s)</string> <string name="master_password_missing">Master password is not set!\n\nPlease set your Master password in Preferences (%1$s &#8594; %2$s)</string>
@ -19,15 +23,23 @@
<string name="unsecure_fallback_descriotion_biometric">In order to be effective, biometric protection needs a master password set for fallback.\n\nPlease set a master password!</string> <string name="unsecure_fallback_descriotion_biometric">In order to be effective, biometric protection needs a master password set for fallback.\n\nPlease set a master password!</string>
<string name="password_set">Password set!</string> <string name="password_set">Password set!</string>
<string name="pin_set">PIN set!</string>
<string name="password_not_set">Password not set</string> <string name="password_not_set">Password not set</string>
<string name="pin_not_set">PIN not set</string>
<string name="password_not_changed">Password not changed</string> <string name="password_not_changed">Password not changed</string>
<string name="pin_not_changed">PIN not changed</string>
<string name="password_cleared">Password cleared!</string> <string name="password_cleared">Password cleared!</string>
<string name="pin_cleared">PIN cleared!</string>
<string name="password_hint">Enter password here</string> <string name="password_hint">Enter password here</string>
<string name="pin_hint">Enter PIN here</string>
<string name="key_master_password" translatable="false">master_password</string> <string name="key_master_password" translatable="false">master_password</string>
<string name="key_settings_password" translatable="false">settings_password</string> <string name="key_settings_password" translatable="false">settings_password</string>
<string name="key_settings_pin" translatable="false">settings_pin</string>
<string name="key_application_password" translatable="false">application_password</string> <string name="key_application_password" translatable="false">application_password</string>
<string name="key_application_pin" translatable="false">application_pin</string>
<string name="key_bolus_password" translatable="false">bolus_password</string> <string name="key_bolus_password" translatable="false">bolus_password</string>
<string name="key_bolus_pin" translatable="false">bolus_pin</string>
<string name="key_settings_protection" translatable="false">settings_protection</string> <string name="key_settings_protection" translatable="false">settings_protection</string>
<string name="key_application_protection" translatable="false">application_protection</string> <string name="key_application_protection" translatable="false">application_protection</string>
<string name="key_bolus_protection" translatable="false">bolus_protection</string> <string name="key_bolus_protection" translatable="false">bolus_protection</string>

View file

@ -222,7 +222,9 @@
<!-- Protection--> <!-- Protection-->
<string name="wrongpassword">Wrong password</string> <string name="wrongpassword">Wrong password</string>
<string name="wrongpin">Wrong PIN</string>
<string name="passwords_dont_match">Passwords don\'t match</string> <string name="passwords_dont_match">Passwords don\'t match</string>
<string name="pin_dont_match">PINs don\'t match</string>
<!-- Profile--> <!-- Profile-->
<string name="basalprofilenotaligned">Basal values not aligned to hours: %1$s</string> <string name="basalprofilenotaligned">Basal values not aligned to hours: %1$s</string>

View file

@ -22,6 +22,12 @@
<item name="android:textColorSecondary">@color/white</item> <item name="android:textColorSecondary">@color/white</item>
<item name="android:textColorPrimary">@color/white</item> <item name="android:textColorPrimary">@color/white</item>
<item name="android:textColor">@color/white</item> <item name="android:textColor">@color/white</item>
<!---Notification -->
<item name="notificationUrgent">@color/notificationUrgent</item>
<item name="notificationNormal">@color/notificationNormal</item>
<item name="notificationLow">@color/notificationLow</item>
<item name="notificationInfo">@color/notificationInfo</item>
<item name="notificationAnnouncement">@color/notificationAnnouncement</item>
</style> </style>
<style name="AppTheme.NoActionBar" parent="Theme.MaterialComponents.NoActionBar"> <style name="AppTheme.NoActionBar" parent="Theme.MaterialComponents.NoActionBar">

View file

@ -456,21 +456,21 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
@NonNull @Override @NonNull @Override
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, @NonNull Profile profile) { public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, @NonNull Profile profile) {
absoluteRate.setIfSmaller(getAapsLogger(), danaPump.getMaxBasal(), String.format(getRh().gs(R.string.limitingbasalratio), danaPump.getMaxBasal(), getRh().gs(R.string.pumplimit)), this); absoluteRate.setIfSmaller(getAapsLogger(), danaPump.getMaxBasal(), getRh().gs(R.string.limitingbasalratio, danaPump.getMaxBasal(), getRh().gs(R.string.pumplimit)), this);
return absoluteRate; return absoluteRate;
} }
@NonNull @Override @NonNull @Override
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, @NonNull Profile profile) { public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, @NonNull Profile profile) {
percentRate.setIfGreater(getAapsLogger(), 0, String.format(getRh().gs(R.string.limitingpercentrate), 0, getRh().gs(R.string.itmustbepositivevalue)), this); percentRate.setIfGreater(getAapsLogger(), 0, getRh().gs(R.string.limitingpercentrate, 0, getRh().gs(R.string.itmustbepositivevalue)), this);
percentRate.setIfSmaller(getAapsLogger(), getPumpDescription().getMaxTempPercent(), String.format(getRh().gs(R.string.limitingpercentrate), getPumpDescription().getMaxTempPercent(), getRh().gs(R.string.pumplimit)), this); percentRate.setIfSmaller(getAapsLogger(), getPumpDescription().getMaxTempPercent(), getRh().gs(R.string.limitingpercentrate, getPumpDescription().getMaxTempPercent(), getRh().gs(R.string.pumplimit)), this);
return percentRate; return percentRate;
} }
@NonNull @Override @NonNull @Override
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) { public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
insulin.setIfSmaller(getAapsLogger(), danaPump.getMaxBolus(), String.format(getRh().gs(R.string.limitingbolus), danaPump.getMaxBolus(), getRh().gs(R.string.pumplimit)), this); insulin.setIfSmaller(getAapsLogger(), danaPump.getMaxBolus(), getRh().gs(R.string.limitingbolus, danaPump.getMaxBolus(), getRh().gs(R.string.pumplimit)), this);
return insulin; return insulin;
} }

View file

@ -302,7 +302,7 @@ class DanaRSPlugin @Inject constructor(
0x40 -> error = rh.gs(R.string.speederror) 0x40 -> error = rh.gs(R.string.speederror)
0x80 -> error = rh.gs(R.string.insulinlimitviolation) 0x80 -> error = rh.gs(R.string.insulinlimitviolation)
} }
result.comment = String.format(rh.gs(R.string.boluserrorcode), detailedBolusInfo.insulin, t.insulin, error) result.comment = rh.gs(R.string.boluserrorcode, detailedBolusInfo.insulin, t.insulin, error)
} else result.comment = rh.gs(R.string.ok) } else result.comment = rh.gs(R.string.ok)
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered) aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered)
result result

View file

@ -306,7 +306,7 @@ class DanaRSService : DaggerService() {
val expectedEnd = bolusStart + bolusDurationInMSec + 2000 val expectedEnd = bolusStart + bolusDurationInMSec + 2000
while (System.currentTimeMillis() < expectedEnd) { while (System.currentTimeMillis() < expectedEnd) {
val waitTime = expectedEnd - System.currentTimeMillis() val waitTime = expectedEnd - System.currentTimeMillis()
bolusingEvent.status = String.format(rh.gs(R.string.waitingforestimatedbolusend), waitTime / 1000) bolusingEvent.status = rh.gs(R.string.waitingforestimatedbolusend, waitTime / 1000)
rxBus.send(bolusingEvent) rxBus.send(bolusingEvent)
SystemClock.sleep(1000) SystemClock.sleep(1000)
} }

View file

@ -406,7 +406,7 @@ class DiaconnG8Service : DaggerService() {
val totalwaitTime = (expectedEnd - System.currentTimeMillis()) / 1000 val totalwaitTime = (expectedEnd - System.currentTimeMillis()) / 1000
while (!diaconnG8Pump.bolusDone) { while (!diaconnG8Pump.bolusDone) {
val waitTime = (expectedEnd - System.currentTimeMillis()) / 1000 val waitTime = (expectedEnd - System.currentTimeMillis()) / 1000
bolusingEvent.status = String.format(rh.gs(R.string.waitingforestimatedbolusend), if (waitTime < 0) 0 else waitTime) bolusingEvent.status = rh.gs(R.string.waitingforestimatedbolusend, if (waitTime < 0) 0 else waitTime)
var progressPecent = 0 var progressPecent = 0
if (totalwaitTime > waitTime) { if (totalwaitTime > waitTime) {
progressPecent = ((totalwaitTime - waitTime) * 100 / totalwaitTime).toInt() progressPecent = ((totalwaitTime - waitTime) * 100 / totalwaitTime).toInt()

View file

@ -1583,22 +1583,22 @@ public class LocalInsightPlugin extends PumpPluginBase implements Pump, Constrai
@NonNull @Override @NonNull @Override
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, @NonNull Profile profile) { public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, @NonNull Profile profile) {
percentRate.setIfGreater(getAapsLogger(), 0, String.format(rh.gs(R.string.limitingpercentrate), 0, rh.gs(R.string.itmustbepositivevalue)), this); percentRate.setIfGreater(getAapsLogger(), 0, rh.gs(R.string.limitingpercentrate, 0, rh.gs(R.string.itmustbepositivevalue)), this);
percentRate.setIfSmaller(getAapsLogger(), getPumpDescription().getMaxTempPercent(), String.format(rh.gs(R.string.limitingpercentrate), getPumpDescription().getMaxTempPercent(), rh.gs(R.string.pumplimit)), this); percentRate.setIfSmaller(getAapsLogger(), getPumpDescription().getMaxTempPercent(), rh.gs(R.string.limitingpercentrate, getPumpDescription().getMaxTempPercent(), rh.gs(R.string.pumplimit)), this);
return percentRate; return percentRate;
} }
@NonNull @Override @NonNull @Override
public Constraint<Double> applyBolusConstraints(@NonNull Constraint<Double> insulin) { public Constraint<Double> applyBolusConstraints(@NonNull Constraint<Double> insulin) {
if (!limitsFetched) return insulin; if (!limitsFetched) return insulin;
insulin.setIfSmaller(getAapsLogger(), maximumBolusAmount, String.format(rh.gs(R.string.limitingbolus), maximumBolusAmount, rh.gs(R.string.pumplimit)), this); insulin.setIfSmaller(getAapsLogger(), maximumBolusAmount, rh.gs(R.string.limitingbolus, maximumBolusAmount, rh.gs(R.string.pumplimit)), this);
if (insulin.value() < minimumBolusAmount) { if (insulin.value() < minimumBolusAmount) {
//TODO: Add function to Constraints or use different approach //TODO: Add function to Constraints or use different approach
// This only works if the interface of the InsightPlugin is called last. // This only works if the interface of the InsightPlugin is called last.
// If not, another constraint could theoretically set the value between 0 and minimumBolusAmount // If not, another constraint could theoretically set the value between 0 and minimumBolusAmount
insulin.set(getAapsLogger(), 0d, String.format(rh.gs(R.string.limitingbolus), minimumBolusAmount, rh.gs(R.string.pumplimit)), this); insulin.set(getAapsLogger(), 0d, rh.gs(R.string.limitingbolus, minimumBolusAmount, rh.gs(R.string.pumplimit)), this);
} }
return insulin; return insulin;
} }

View file

@ -16,8 +16,6 @@ import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.extensions.toStringFull import info.nightscout.androidaps.extensions.toStringFull
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.common.ManufacturerType import info.nightscout.androidaps.plugins.common.ManufacturerType
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
@ -52,6 +50,8 @@ import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.TimeChangeType import info.nightscout.androidaps.utils.TimeChangeType
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.core.Single
@ -119,10 +119,13 @@ class OmnipodDashPumpPlugin @Inject constructor(
updatePodWarnings() updatePodWarnings()
aapsLogger.info(LTag.PUMP, "statusChecker") aapsLogger.info(LTag.PUMP, "statusChecker")
try {
createFakeTBRWhenNoActivePod() createFakeTBRWhenNoActivePod()
.subscribeOn(aapsSchedulers.io) .subscribeOn(aapsSchedulers.io)
.doOnError { aapsLogger.warn(LTag.PUMP, "Error on createFakeTBRWhenNoActivePod=$it") } .blockingAwait()
.blockingSubscribe() } catch (e: Exception) {
aapsLogger.warn(LTag.PUMP, "Error on createFakeTBRWhenNoActivePod=$e")
}
handler.postDelayed(statusChecker, STATUS_CHECK_INTERVAL_MS) handler.postDelayed(statusChecker, STATUS_CHECK_INTERVAL_MS)
} }
} }
@ -247,10 +250,11 @@ class OmnipodDashPumpPlugin @Inject constructor(
try { try {
stopConnecting?.let { stopConnecting?.let {
omnipodManager.connect(it).ignoreElements() omnipodManager.connect(it).ignoreElements()
.doOnError { aapsLogger.info(LTag.PUMPCOMM, "connect error=$it") }
.doOnComplete { podStateManager.incrementSuccessfulConnectionAttemptsAfterRetries() } .doOnComplete { podStateManager.incrementSuccessfulConnectionAttemptsAfterRetries() }
.blockingSubscribe() .blockingAwait()
} }
} catch (e: Exception) {
aapsLogger.info(LTag.PUMPCOMM, "connect error=$e")
} finally { } finally {
synchronized(this) { synchronized(this) {
stopConnecting = null stopConnecting = null
@ -279,6 +283,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
return return
} }
try {
getPodStatus() getPodStatus()
.doOnComplete { .doOnComplete {
aapsLogger.info(LTag.PUMP, "getPumpStatus executed with success") aapsLogger.info(LTag.PUMP, "getPumpStatus executed with success")
@ -289,11 +294,10 @@ class OmnipodDashPumpPlugin @Inject constructor(
aapsLogger.info(LTag.PUMP, "recoverActivationFromPodStatus msg=$msg") aapsLogger.info(LTag.PUMP, "recoverActivationFromPodStatus msg=$msg")
} }
} }
}.blockingAwait()
} catch (e: Exception) {
aapsLogger.error(LTag.PUMP, "Error in getPumpStatus", e)
} }
.doOnError {
aapsLogger.error(LTag.PUMP, "Error in getPumpStatus", it)
}
.blockingSubscribe()
} }
private fun getPodStatus(): Completable = Completable.concat( private fun getPodStatus(): Completable = Completable.concat(
@ -564,7 +568,8 @@ class OmnipodDashPumpPlugin @Inject constructor(
.comment(rh.gs(R.string.omnipod_dash_not_enough_insulin)) .comment(rh.gs(R.string.omnipod_dash_not_enough_insulin))
} }
if (podStateManager.deliveryStatus == DeliveryStatus.BOLUS_AND_BASAL_ACTIVE || if (podStateManager.deliveryStatus == DeliveryStatus.BOLUS_AND_BASAL_ACTIVE ||
podStateManager.deliveryStatus == DeliveryStatus.BOLUS_AND_TEMP_BASAL_ACTIVE) { podStateManager.deliveryStatus == DeliveryStatus.BOLUS_AND_TEMP_BASAL_ACTIVE
) {
return PumpEnactResult(injector) return PumpEnactResult(injector)
.success(false) .success(false)
.enacted(false) .enacted(false)
@ -722,13 +727,13 @@ class OmnipodDashPumpPlugin @Inject constructor(
getPodStatus() getPodStatus()
var errorGettingStatus: Throwable? = null var errorGettingStatus: Throwable? = null
cmd try {
.doOnError { cmd.blockingAwait()
errorGettingStatus = it } catch (e: Exception) {
errorGettingStatus = e
aapsLogger.debug(LTag.PUMP, "waitForBolusDeliveryToComplete errorGettingStatus=$errorGettingStatus") aapsLogger.debug(LTag.PUMP, "waitForBolusDeliveryToComplete errorGettingStatus=$errorGettingStatus")
Thread.sleep(BOLUS_RETRY_INTERVAL_MS) // retry every 3 sec Thread.sleep(BOLUS_RETRY_INTERVAL_MS) // retry every 3 sec
} }
.blockingSubscribe()
if (errorGettingStatus != null) { if (errorGettingStatus != null) {
continue continue
} }

View file

@ -40,6 +40,7 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper 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.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
@ -64,6 +65,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
@Inject lateinit var omnipodDashPumpPlugin: OmnipodDashPumpPlugin @Inject lateinit var omnipodDashPumpPlugin: OmnipodDashPumpPlugin
@Inject lateinit var podStateManager: OmnipodDashPodStateManager @Inject lateinit var podStateManager: OmnipodDashPodStateManager
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var protectionCheck: ProtectionCheck
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var pumpSync: PumpSync @Inject lateinit var pumpSync: PumpSync
@ -93,8 +95,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
private var _podInfoBinding: OmnipodCommonOverviewPodInfoBinding? = null private var _podInfoBinding: OmnipodCommonOverviewPodInfoBinding? = null
private var _buttonBinding: OmnipodCommonOverviewButtonsBinding? = null private var _buttonBinding: OmnipodCommonOverviewButtonsBinding? = null
// These properties are only valid between onCreateView and // These properties are only valid between onCreateView and onDestroyView.
// onDestroyView.
val binding get() = _binding!! val binding get() = _binding!!
private val bluetoothStatusBinding get() = _bluetoothStatusBinding!! private val bluetoothStatusBinding get() = _bluetoothStatusBinding!!
private val podInfoBinding get() = _podInfoBinding!! private val podInfoBinding get() = _podInfoBinding!!
@ -112,8 +113,12 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
buttonBinding.buttonPodManagement.setOnClickListener { buttonBinding.buttonPodManagement.setOnClickListener {
// TODO add protection activity?.let { activity ->
startActivity(Intent(context, DashPodManagementActivity::class.java)) protectionCheck.queryProtection(
activity,
ProtectionCheck.Protection.PREFERENCES,
UIRunnable { startActivity(Intent(context, DashPodManagementActivity::class.java)) })
}
} }
buttonBinding.buttonResumeDelivery.setOnClickListener { buttonBinding.buttonResumeDelivery.setOnClickListener {

View file

@ -81,4 +81,5 @@
</plurals> </plurals>
<string name="orange_use_scanning_level">Použi skenovanie</string> <string name="orange_use_scanning_level">Použi skenovanie</string>
<string name="orange_use_scanning_level_summary">Skenuj, predtým, ako sa pripojíš k OrangeLinku. Malo by to zlepšiť stabilitu pripojenia (môže byť použité i s inými klonmi RileyLinku, ak je to potrebné).</string> <string name="orange_use_scanning_level_summary">Skenuj, predtým, ako sa pripojíš k OrangeLinku. Malo by to zlepšiť stabilitu pripojenia (môže byť použité i s inými klonmi RileyLinku, ak je to potrebné).</string>
<string name="rileylink_configuration">Konfigurácia RileyLinku</string>
</resources> </resources>