diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 381dffa690..ca2f66f536 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,5 +44,5 @@ Hints * 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 * 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 diff --git a/app/build.gradle b/app/build.gradle index e295eaf3c1..427013fd1a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -109,7 +109,7 @@ android { defaultConfig { multiDexEnabled true versionCode 1500 - version "3.0.0.1-dev-d" + version "3.0.0.1-dev-e" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.kt b/app/src/main/java/info/nightscout/androidaps/MainActivity.kt index f88ac370e7..dbd152c315 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.kt @@ -89,7 +89,7 @@ class MainActivity : NoSplashAppCompatActivity() { private var pluginPreferencesMenuItem: MenuItem? = null private var menu: Menu? = null private var menuOpen = false - + private var isProtectionCheckActive = false private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { @@ -168,10 +168,13 @@ class MainActivity : NoSplashAppCompatActivity() { override fun onResume() { super.onResume() - protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, null, - UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { finish() } }, - UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { finish() } } - ) + if (!isProtectionCheckActive) { + isProtectionCheckActive = true + 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() { @@ -417,6 +420,8 @@ class MainActivity : NoSplashAppCompatActivity() { // Add to crash log too FirebaseCrashlytics.getInstance().setCustomKey("HEAD", BuildConfig.HEAD) 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("Committed", BuildConfig.COMMITTED) FirebaseCrashlytics.getInstance().setCustomKey("Hash", hashes[0]) diff --git a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt index 8770925cb5..5da167b74b 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt @@ -8,17 +8,17 @@ import android.os.Bundle import androidx.annotation.XmlRes import androidx.preference.* import dagger.android.support.AndroidSupportInjection -import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.R import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin import info.nightscout.androidaps.danaRv2.DanaRv2Plugin import info.nightscout.androidaps.danar.DanaRPlugin import info.nightscout.androidaps.danars.DanaRSPlugin import info.nightscout.androidaps.diaconn.DiaconnG8Plugin -import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventRebuildTabs +import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploader 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.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin -import info.nightscout.androidaps.plugins.source.DexcomPlugin -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.plugins.source.* import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show 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.shared.SafeParse import info.nightscout.shared.sharedPreferences.SP 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_bolus_protection) == key) && 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 { val title = rh.gs(R.string.unsecure_fallback_biometric) @@ -249,9 +244,9 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang } // Master password erased with activated Biometric protection - val isBiometricActivated = sp.getInt(R.string.key_settings_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal || - sp.getInt(R.string.key_application_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal || - sp.getInt(R.string.key_bolus_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, NONE.ordinal) == 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) { activity?.let { val title = rh.gs(R.string.unsecure_fallback_biometric) @@ -322,26 +317,35 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang if (pref is ListPreference) { pref.setSummary(pref.entry) // Preferences - // Preferences if (pref.getKey() == rh.gs(R.string.key_settings_protection)) { 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 if (pref.getKey() == rh.gs(R.string.key_application_protection)) { 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 if (pref.getKey() == rh.gs(R.string.key_bolus_protection)) { 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.getKey().contains("password") || pref.getKey().contains("secret")) { + if (pref.getKey().contains("password") || pref.getKey().contains("pin") || pref.getKey().contains("secret")) { pref.setSummary("******") } else if (pref.text != null) { pref.dialogMessage = pref.dialogMessage @@ -357,7 +361,10 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang rh.gs(R.string.key_bolus_password), rh.gs(R.string.key_master_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) { @@ -365,7 +372,11 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang if (sp.getString(pref.key, "").startsWith("hmac:")) { pref.summary = "******" } else { - pref.summary = rh.gs(R.string.password_not_set) + if (pref.getKey().contains("pin")) { + pref.summary = rh.gs(R.string.pin_not_set) + }else { + pref.summary = rh.gs(R.string.password_not_set) + } } } } @@ -411,6 +422,18 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang passwordCheck.setPassword(context, R.string.application_password, R.string.key_application_password) 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 if (preference.key == rh.gs(R.string.key_statuslights_copy_ns)) { nsSettingStatus.copyStatusLightsNsSettings(context) diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt index c1ed8faf5b..16d41ef689 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt @@ -103,7 +103,7 @@ class TempTargetDialog : DialogFragmentWithDate() { val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList) 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.activity.setOnClickListener { shortClick(it) } binding.hypo.setOnClickListener { shortClick(it) } @@ -149,10 +149,6 @@ class TempTargetDialog : DialogFragmentWithDate() { binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble() binding.reason.setSelection(reasonList.indexOf(rh.gs(R.string.hypo))) } - - R.id.cancel -> { - binding.duration.value = 0.0 - } } } diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt index fbfc23c17b..36c8c90a1a 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt @@ -438,10 +438,10 @@ class WizardDialog : DaggerDialogFragment() { ) 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.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.iobInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB + wizard.insulinFromBasalIOB) @@ -464,7 +464,7 @@ class WizardDialog : DaggerDialogFragment() { // COB 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) } else { binding.cob.text = "" diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt index bb1dcae6ed..a91cf4fe54 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt @@ -109,29 +109,29 @@ class SafetyPlugin @Inject constructor( } override fun applyBasalConstraints(absoluteRate: Constraint, profile: Profile): Constraint { - 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) { var maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1.0) if (maxBasal < profile.getMaxDailyBasal()) { maxBasal = profile.getMaxDailyBasal() 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 val maxBasalMultiplier = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0) 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 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 // check for pump max if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { 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 @@ -151,19 +151,19 @@ class SafetyPlugin @Inject constructor( val pump = activePlugin.activePump 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() - 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) { 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 } override fun applyBolusConstraints(insulin: Constraint): Constraint { - 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) - insulin.setIfSmaller(aapsLogger, maxBolus, String.format(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, maxBolus, rh.gs(R.string.limitingbolus, maxBolus, rh.gs(R.string.maxvalueinpreferences)), this) + insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), rh.gs(R.string.limitingbolus, hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this) val pump = activePlugin.activePump val rounded = pump.pumpDescription.pumpType.determineCorrectBolusSize(insulin.value()) insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this) @@ -171,10 +171,10 @@ class SafetyPlugin @Inject constructor( } override fun applyExtendedBolusConstraints(insulin: Constraint): Constraint { - 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) - insulin.setIfSmaller(aapsLogger, maxBolus, String.format(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, maxBolus, rh.gs(R.string.limitingextendedbolus, maxBolus, rh.gs(R.string.maxvalueinpreferences)), this) + insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), rh.gs(R.string.limitingextendedbolus, hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this) val pump = activePlugin.activePump val rounded = pump.pumpDescription.pumpType.determineCorrectExtendedBolusSize(insulin.value()) insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this) @@ -182,9 +182,9 @@ class SafetyPlugin @Inject constructor( } override fun applyCarbsConstraints(carbs: Constraint): Constraint { - 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) - 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 } @@ -192,11 +192,11 @@ class SafetyPlugin @Inject constructor( 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 .key_openapsma_max_iob, 1.5) - maxIob.setIfSmaller(aapsLogger, maxIobPref, String.format(rh.gs(R.string.limitingiob), maxIobPref, rh.gs(R.string.maxvalueinpreferences)), this) - if (openAPSAMAPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobAMA(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobAMA(), rh.gs(R.string.hardlimit)), this) - if (openAPSSMBPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this) - if (OpenAPSSMBDynamicISFPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this) - if (apsMode == "lgs") maxIob.setIfSmaller(aapsLogger, HardLimits.MAX_IOB_LGS, String.format(rh.gs(R.string.limitingiob), HardLimits.MAX_IOB_LGS, rh.gs(R.string.lowglucosesuspend)), this) + maxIob.setIfSmaller(aapsLogger, maxIobPref, rh.gs(R.string.limitingiob, maxIobPref, rh.gs(R.string.maxvalueinpreferences)), 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(), 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, rh.gs(R.string.limitingiob, HardLimits.MAX_IOB_LGS, rh.gs(R.string.lowglucosesuspend)), this) return maxIob } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt index dc5805cfd1..54c21c929e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt @@ -157,10 +157,20 @@ class ActionsFragment : DaggerFragment() { cannulaOrPatch = view.findViewById(R.id.cannula_or_patch) profileSwitch?.setOnClickListener { - ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog") + activity?.let { activity -> + protectionCheck.queryProtection( + activity, + ProtectionCheck.Protection.BOLUS, + UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog")}) + } } tempTarget?.setOnClickListener { - TempTargetDialog().show(childFragmentManager, "Actions") + activity?.let { activity -> + protectionCheck.queryProtection( + activity, + ProtectionCheck.Protection.BOLUS, + UIRunnable { TempTargetDialog().show(childFragmentManager, "Actions") }) + } } extendedBolus?.setOnClickListener { activity?.let { activity -> @@ -187,7 +197,12 @@ class ActionsFragment : DaggerFragment() { } } setTempBasal?.setOnClickListener { - TempBasalDialog().show(childFragmentManager, "Actions") + activity?.let { activity -> + protectionCheck.queryProtection( + activity, + ProtectionCheck.Protection.BOLUS, + UIRunnable { TempBasalDialog().show(childFragmentManager, "Actions") }) + } } cancelTempBasal?.setOnClickListener { if (iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) != null) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt index 8d6cc9c91b..42ceaabc6c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt @@ -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.eros.history.database.ErosHistoryDatabase 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.rx.AapsSchedulers import io.reactivex.rxjava3.core.Completable.fromAction @@ -48,6 +49,7 @@ class MaintenanceFragment : DaggerFragment() { @Inject lateinit var diaconnDatabase: DiaconnHistoryDatabase @Inject lateinit var erosDatabase: ErosHistoryDatabase @Inject lateinit var dashDatabase: DashHistoryDatabase + @Inject lateinit var protectionCheck: ProtectionCheck @Inject lateinit var uel: UserEntryLogger @Inject lateinit var dataSyncSelector: DataSyncSelector @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 diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt index 5e66ac8260..087ec2f2ee 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.kt @@ -164,11 +164,11 @@ class NotificationStore @Inject constructor( @Suppress("SetTextI18n") holder.binding.text.text = dateUtil.timeString(notification.date) + " " + notification.text when (notification.level) { - Notification.URGENT -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationUrgent)) - Notification.NORMAL -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationNormal)) - Notification.LOW -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationLow)) - Notification.INFO -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationInfo)) - Notification.ANNOUNCEMENT -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationAnnouncement)) + Notification.URGENT -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationUrgent)) + Notification.NORMAL -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationNormal)) + Notification.LOW -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationLow)) + Notification.INFO -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationInfo)) + Notification.ANNOUNCEMENT -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationAnnouncement)) } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt index d2c12037ce..6952ea186e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt @@ -328,7 +328,7 @@ class SmsCommunicatorPlugin @Inject constructor( } else if (lastBG != null) { val agoMilliseconds = dateUtil.now() - lastBG.timestamp 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 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" -> { if (loop.enabled) { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { override fun run() { @@ -372,7 +372,7 @@ class SmsCommunicatorPlugin @Inject constructor( "ENABLE", "START" -> { if (!loop.enabled) { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { override fun run() { @@ -389,7 +389,7 @@ class SmsCommunicatorPlugin @Inject constructor( "STATUS" -> { 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.loopisdisabled) @@ -399,7 +399,7 @@ class SmsCommunicatorPlugin @Inject constructor( "RESUME" -> { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { override fun run() { @@ -436,7 +436,7 @@ class SmsCommunicatorPlugin @Inject constructor( return } else { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, duration) { override fun run() { @@ -515,7 +515,7 @@ class SmsCommunicatorPlugin @Inject constructor( receivedSms.processed = true } else if ((divided.size == 2) && (divided[1].equals("CONNECT", ignoreCase = true))) { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { override fun run() { @@ -548,7 +548,7 @@ class SmsCommunicatorPlugin @Inject constructor( return } else { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { override fun run() { @@ -601,7 +601,7 @@ class SmsCommunicatorPlugin @Inject constructor( if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.noprofile))) else { 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 val finalPercentage = percentage 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, receivedSms: Sms) { if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { override fun run() { @@ -662,14 +662,14 @@ class SmsCommunicatorPlugin @Inject constructor( else { tempBasalPct = constraintChecker.applyBasalPercentConstraints(Constraint(tempBasalPct), profile).value() 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasalPct, duration) { override fun run() { commandQueue.tempBasalPercent(anInteger(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() { override fun run() { 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) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) if (result.isPercent) @@ -706,15 +706,15 @@ class SmsCommunicatorPlugin @Inject constructor( else { tempBasal = constraintChecker.applyBasalConstraints(Constraint(tempBasal), profile).value() 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasal, duration) { override fun run() { commandQueue.tempBasalAbsolute(aDouble(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() { override fun run() { 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) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) if (result.isPercent) @@ -743,7 +743,7 @@ class SmsCommunicatorPlugin @Inject constructor( private fun processEXTENDED(divided: Array, receivedSms: Sms) { if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) { 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))) else { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, extended, duration) { override fun run() { commandQueue.extendedBolus(aDouble(), secondInteger(), object : Callback() { override fun run() { 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) replyText += "\n" + activePlugin.activePump.shortStatus(true) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) @@ -817,9 +817,9 @@ class SmsCommunicatorPlugin @Inject constructor( } else if (bolus > 0.0) { val passCode = generatePassCode() val reply = if (isMeal) - String.format(rh.gs(R.string.smscommunicator_mealbolusreplywithcode), bolus, passCode) + rh.gs(R.string.smscommunicator_mealbolusreplywithcode, bolus, passCode) else - String.format(rh.gs(R.string.smscommunicator_bolusreplywithcode), bolus, passCode) + rh.gs(R.string.smscommunicator_bolusreplywithcode, bolus, passCode) receivedSms.processed = true messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, bolus) { override fun run() { @@ -833,9 +833,9 @@ class SmsCommunicatorPlugin @Inject constructor( override fun run() { if (resultSuccess) { var replyText = if (isMeal) - String.format(rh.gs(R.string.smscommunicator_mealbolusdelivered), resultBolusDelivered) + rh.gs(R.string.smscommunicator_mealbolusdelivered, resultBolusDelivered) else - String.format(rh.gs(R.string.smscommunicator_bolusdelivered), resultBolusDelivered) + rh.gs(R.string.smscommunicator_bolusdelivered, resultBolusDelivered) replyText += "\n" + activePlugin.activePump.shortStatus(true) lastRemoteBolusTime = dateUtil.now() if (isMeal) { @@ -866,7 +866,7 @@ class SmsCommunicatorPlugin @Inject constructor( val tt = if (currentProfile.units == GlucoseUnit.MMOL) { DecimalFormatter.to1Decimal(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)) @@ -920,7 +920,7 @@ class SmsCommunicatorPlugin @Inject constructor( if (grams == 0) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrongformat))) else { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, grams, time) { override fun run() { @@ -930,7 +930,7 @@ class SmsCommunicatorPlugin @Inject constructor( commandQueue.bolus(detailedBolusInfo, object : Callback() { override fun run() { 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) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) 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) if (isMeal || isActivity || isHypo) { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { override fun run() { @@ -1009,7 +1009,7 @@ class SmsCommunicatorPlugin @Inject constructor( aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) }) 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)) uel.log(Action.TT, Sources.SMS, ValueWithUnit.fromGlucoseUnit(tt, units.asText), @@ -1018,7 +1018,7 @@ class SmsCommunicatorPlugin @Inject constructor( }) } else if (isStop) { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { override fun run() { @@ -1028,7 +1028,7 @@ class SmsCommunicatorPlugin @Inject constructor( }, { 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)) uel.log(Action.CANCEL_TT, Sources.SMS, rh.gs(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)) if (isStop) { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) { override fun run() { 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)) uel.log(Action.STOP_SMS, Sources.SMS, rh.gs(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]) if (cal > 0.0) { 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 messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false, cal) { override fun run() { @@ -1127,7 +1127,7 @@ class SmsCommunicatorPlugin @Inject constructor( } 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 { var s = str diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt index 481e904868..d4eb8a30e1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt @@ -111,7 +111,7 @@ class ActionStringHandler @Inject constructor( @Synchronized private fun handleInitiate(actionString: String) { //TODO: i18n - Log.i("ActionStringHandler", "handleInitiate actionString=" + actionString) + Log.i("ActionStringHandler", "handleInitiate actionString=$actionString") if (!sp.getBoolean(R.string.key_wear_control, false)) return lastBolusWizard = null var rTitle = rh.gs(R.string.confirm).uppercase() @@ -640,10 +640,10 @@ class ActionStringHandler @Inject constructor( var msg = "" //check for validity 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) { - msg += String.format(rh.gs(R.string.valueoutofrange), "Profile-Timeshift") + "\n" + msg += rh.gs(R.string.valueoutofrange, "Profile-Timeshift") + "\n" } val profile = profileFunction.getProfile() if (profile == null) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.kt index d6be8f54cd..43b4130778 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.kt @@ -95,7 +95,7 @@ class WearPlugin @Inject constructor( .toObservable(EventBolusRequested::class.java) .observeOn(aapsSchedulers.io) .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) intent.putExtra("progresspercent", 0) intent.putExtra("progressstatus", status) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt index 3a81af67d3..4888f2e96c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt @@ -29,6 +29,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.alertDialogs.OKDialog +import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.ui.TimeListEdit @@ -49,6 +50,7 @@ class LocalProfileFragment : DaggerFragment() { @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var localProfilePlugin: LocalProfilePlugin @Inject lateinit var hardLimits: HardLimits + @Inject lateinit var protectionCheck: ProtectionCheck @Inject lateinit var dateUtil: DateUtil @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var uel: UserEntryLogger @@ -88,8 +90,7 @@ class LocalProfileFragment : DaggerFragment() { private var _binding: LocalprofileFragmentBinding? = null - // This property is only valid between onCreateView and - // onDestroyView. + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { @@ -124,6 +125,23 @@ class LocalProfileFragment : DaggerFragment() { binding.target.visibility = View.VISIBLE } 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() { diff --git a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt index 3ccd6d6900..6d32d15594 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt @@ -113,7 +113,7 @@ class AndroidPermission @Inject constructor( @Synchronized fun notifyForBatteryOptimizationPermission(activity: FragmentActivity) { 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)) } rxBus.send(EventNewNotification(notification)) } else rxBus.send(EventDismissNotification(Notification.PERMISSION_BATTERY)) diff --git a/app/src/main/res/layout/dialog_wizard.xml b/app/src/main/res/layout/dialog_wizard.xml index 7818c89359..f9e3e57340 100644 --- a/app/src/main/res/layout/dialog_wizard.xml +++ b/app/src/main/res/layout/dialog_wizard.xml @@ -242,77 +242,67 @@ + android:layout_width="match_parent" + android:layout_height="45dp" + android:paddingHorizontal="10dp"> - - + android:scaleY="1.6" /> - - - diff --git a/app/src/main/res/layout/localprofile_fragment.xml b/app/src/main/res/layout/localprofile_fragment.xml index ae4db5ca29..ae7f788b54 100644 --- a/app/src/main/res/layout/localprofile_fragment.xml +++ b/app/src/main/res/layout/localprofile_fragment.xml @@ -10,353 +10,369 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - - - - + android:layout_gravity="center" + android:text="@string/unlock_settings" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginStart="5dp" + android:layout_marginEnd="5dp" + android:hint="@string/select_profile" + android:textColorHint="@color/white" + app:boxStrokeColor="@color/list_delimiter"> + + + + + android:layout_marginBottom="10dp" + android:orientation="horizontal"> - - - + android:layout_marginStart="10dp" + android:layout_weight="1" + android:ems="10" + android:importantForAutofill="no" + android:inputType="text" /> - - - - - - + android:gravity="start" + android:orientation="horizontal"> - + - + - + + + + + + + + android:orientation="horizontal" + android:paddingBottom="10dp" + android:weightSum="5"> - + - + - + + + + + + + android:layout_height="wrap_content" + android:orientation="vertical"> - + - + - + + + + + + + + + + + + android:id="@+id/ic" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical"> - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + android:orientation="horizontal"> + + + + + - diff --git a/app/src/main/res/layout/maintenance_fragment.xml b/app/src/main/res/layout/maintenance_fragment.xml index 2e994e142e..eed3be06d2 100644 --- a/app/src/main/res/layout/maintenance_fragment.xml +++ b/app/src/main/res/layout/maintenance_fragment.xml @@ -5,7 +5,16 @@ android:paddingTop="2dp" tools:context=".plugins.general.maintenance.MaintenanceFragment"> + + diff --git a/app/src/main/res/layout/overview_notification_item.xml b/app/src/main/res/layout/overview_notification_item.xml index 490092fce0..23d103abeb 100644 --- a/app/src/main/res/layout/overview_notification_item.xml +++ b/app/src/main/res/layout/overview_notification_item.xml @@ -7,7 +7,7 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="1dp" - card_view:cardBackgroundColor="@color/cardColorBackground" + card_view:cardBackgroundColor="@color/notificationUrgent" card_view:cardCornerRadius="6dp"> diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index 13ce767148..162f756ca6 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -267,6 +267,7 @@ KONF OKRUH OAPS + DYNISF LPRF PREH VPUM @@ -432,6 +433,7 @@ Povoliť vysielanie do iných aplikácií (napr. xDrip+). Nepovoľujte, pokiaľ máte nainštalovanú viac ako jednu AAPS, alebo NSClient inštanciu! Povoliť lokálne vysielanie. OpenAPS SMB + Dynamická ISF Povoliť UAM Povoliť SMB Použiť Super Mikro Bolusy namiesto dočasných bazálov, pre zrýchleniu účinku @@ -661,6 +663,9 @@ Citlivosť zvyšuje cieľ Ak je zistená vyššia citlivosť, zvýši cieľovú hladinu glykémie Vymazať udalosti \"AndroidAPS reštartovaný\" + Zobraziť neplatné + Skryť zneplatnené + Odstrániť položky Nájdené uložené nastavenia 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. Dáta ošetrení neúplné @@ -877,6 +882,8 @@ Prijať prepnutia profilov zadané prostredníctvom NS, alebo NSClienta Prijímať udalosti APS offline Prijať APS offline udalosti zadané prostredníctvom NS, alebo NSClienta + Prijímať dočasný bazál a predĺžený bolus + Prijať dočasný bazál a predĺžený bolus zadaný cez inú inštanciu Prijímať inzulín Prijať inzulín vložený cez NS, alebo NSClient (nie je dodaný, iba započítaný do IOB) Prijímať sacharidy @@ -969,4 +976,15 @@ Neznámy príkaz k akcii: Percentuálny podiel Predvolené aplikáciou + Vyberte profil pre úpravu + Obnoviť z Nightscoutu + Odstrániť vybrané položky + Vyberte pre odstránenie + Zmeny profilu + Dočasné ciele + Sacharidy a bolusy + Naozaj chcete odstrániť %1$d položku(y) + Skryť uzavretý okruh + Zobraziť uzavretý okruh + Vybrané: %1$d diff --git a/app/src/main/res/values-zh-rCN/exam.xml b/app/src/main/res/values-zh-rCN/exam.xml index 87ec82780f..137f0a8767 100644 --- a/app/src/main/res/values-zh-rCN/exam.xml +++ b/app/src/main/res/values-zh-rCN/exam.xml @@ -60,10 +60,10 @@ 等血糖值低于你的低血糖警戒线之后,吃15克速升的活性碳水合物。 https://androidaps.readthedocs.io/en/latest/EN/Usage/temptarget.html#activity-temp-target 禁用/暂停闭环 - 在禁用/暂停闭环时,是否可以输注胰岛素? - 是的,胰岛素基础率可以正常输注的。 + 在禁用/暂停闭环时,我是否接收了胰岛素输注? + 是的,胰岛素基础率仍在继续输注。 不,胰岛素停止输注。 - Basal(基础率),ISF(胰岛素敏感系数)和I:C(胰岛素:碳水)测试 + Basal基础率,ISF胰岛素敏感系数,I:C或ICR碳水化合物系数的测试 什么时候需要修订这些值? 在开始闭环之前。 当经常出现高血糖或低血糖时。 @@ -84,7 +84,7 @@ 一台 MiniMed 670G 泵。 https://androidaps.readthedocs.io/en/latest/EN/Module/module.html 一个智能手表. - 一个可正常使用的 CGM。 + 受支持的CGM血糖监测产品 先决条件 什么是建立和使用 AndroidAPS的基本条件? 验证参数信息用于个人配置文件(如ISF胰岛素敏感度系数、I:C胰岛素碳水比率、基础率、DIA胰岛素作用持续时间等等)。 @@ -93,9 +93,9 @@ 一台安装了动态血糖监测应用或兼容软件的手机/设备,用于接收血糖数据。 https://androidaps.readthedocs.io/en/latest/EN/Module/module.html 更新 AndroidAPS - 检查所有正确的答案. + 选择所有正确的答案. 您需要在您的计算机上安装和配置Git。 - 当更新的 AndroidAPS 版本发布时,先前的版本可能会在指定时间之后受到远程限制。 + 当AndroidAPS更新发布正式版本时,先前的版本可能会在指定时间之后受到远程限制。 您应该保存并记住密钥的存储位置,并使用相同地签名密钥进行更新,与您以前的安装一样。 如果该系统运作良好,就不要去更新系统。 如果您在构建应用时遇到困难,您可以安装一个由朋友构建的应用程序。 @@ -119,7 +119,7 @@ 敏感度插件 选择所有正确的答案。 灵敏度插件允许AndroidAPS临时调整胰岛素敏感度的短暂变化(例如激素变化或与输液部位吸收相关的问题)。 - 灵敏度插件为用户提供基础率、 I:C比率和 ISF 的更改建议,可用来编辑配置文件。 + 灵敏度插件为用户提供basal基础率,I:C碳水化合物系数和ISF胰岛素敏感系数的更改建议,可用来编辑配置文件。 记录输注导管更换会将Autosens比率重置回100%。 一些插件选项具有可配置的时间范围,可由用户设置。 https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html @@ -195,13 +195,13 @@ 如果您比平常早起 2 个小时,您应该如何通知AndroidAPS应对个人日程表中的更改? 以增加2小时的方式,启动个人配置文件切换 以减少2小时的方式,启动个人配置文件切换 - 设置一个马上吃饭的临时的目标血糖值。 + 设置一个马上吃饭,临时的血糖目标值。 将配置文件切换到100%以上。 https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html?highlight=profilewitch#timeshift 修改配置文件 - 基础率、胰岛素敏感系数ISF、胰岛素和碳水比率I:C等,应在配置文件中设定。 + Basal基础率,ISF胰岛素敏感系数,I:C碳水化合物系数等,应该在配置文件中设定。 激活对Nightscout配置文件的更改,需要您的AndroidAPS 手机启用互联网连接。 - 编辑配置文件并修改参数,足以进行任何更改。 + 编辑配置文件进行参数的修改,足以适应任何变化。 可以设置和选择多个配置文件,以适应不断变化的环境(例如激素变化、轮班工作、工作日/周末生活方式)。 https://androidaps.readthedocs.io/en/latest/EN/Module/module.html#good-individual-dosage-algorithm-for-your-diabetes-therapy 帮助调整基础率 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 0453fe87bb..0e006e2bbf 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -136,6 +136,7 @@ @string/biometric @string/master_password @string/custom_password + @string/custom_pin @@ -143,6 +144,7 @@ 1 2 3 + 4 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 334e809e1e..96670d632b 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -40,11 +40,6 @@ #de7550 #25912e - #ff0400 - #ff5e55 - #ff827c - #009705 - #c8666666 #7200FF00 #72FF0000 diff --git a/app/src/main/res/values/exam.xml b/app/src/main/res/values/exam.xml index 778e865cbf..d8285423fe 100644 --- a/app/src/main/res/values/exam.xml +++ b/app/src/main/res/values/exam.xml @@ -104,11 +104,11 @@ Where can you look for help with AndroidAPS? You can ask for advice in the AndroidAPS Users Facebook group. You should read (and re-read) the AndroidAPS documentation. - You can ask for advice and log technical problems or issues in the AndroidAPS Gitter room. + You can ask for advice and log technical problems or issues in the AndroidAPS Discord. You should ask your diabetes clinic/endocrinologist. https://androidaps.readthedocs.io/en/latest/EN/Installing-AndroidAPS/Update-to-new-version.html#troubleshooting https://www.facebook.com/groups/AndroidAPSUsers/ - https://gitter.im/MilosKozak/AndroidAPS + https://discord.gg/4fQUWHZ4Mw Insulin Plugins Which insulin should you use with the Ultra-Rapid Oref plugin? Fiasp® diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index ee1076fcab..6b43facf2d 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -46,10 +46,13 @@ android:title="@string/settings_protection" /> + + + + + + applyMaxIOBConstraints(@NonNull Constraint maxIob) { 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; } diff --git a/combo/src/main/res/values-pt-rBR/strings.xml b/combo/src/main/res/values-pt-rBR/strings.xml index a4a15441d4..82d4ed80ee 100644 --- a/combo/src/main/res/values-pt-rBR/strings.xml +++ b/combo/src/main/res/values-pt-rBR/strings.xml @@ -48,7 +48,7 @@ O último bólus tem mais de 24 horas ou está no futuro. Por favor, verifique se a data está definida corretamente. Hora/data da entrega do bólus na bomba parece errado, insulina ativa parece estar provavelmente incorreto. Verifique hora/data na bomba. Contagem Bólus - Contagem Basal Teporária + Contagem Basal Temporária Bolus interrompido Interrompendo bolus Contagem de erro comunicada diff --git a/combo/src/main/res/values-sk-rSK/strings.xml b/combo/src/main/res/values-sk-rSK/strings.xml index d6fae8cdb6..7fa36433e3 100644 --- a/combo/src/main/res/values-sk-rSK/strings.xml +++ b/combo/src/main/res/values-sk-rSK/strings.xml @@ -51,4 +51,10 @@ Počet dočasných bazálov Bolus zastavený Zastavenie bolusu + Počet chýb komun. + Zobr. počet chýb komun. + 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ť). + Nikdy + Keď dôjde k chybe + Vždy diff --git a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt index deb080e119..ecb60ee2f5 100644 --- a/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt +++ b/core/src/main/java/info/nightscout/androidaps/dialogs/ProfileViewerDialog.kt @@ -293,8 +293,8 @@ class ProfileViewerDialog : DaggerDialogFragment() { val val1h = profile1.getTargetHighMgdlTimeFromMidnight(hour * 60 * 60) val val2l = profile2.getTargetLowMgdlTimeFromMidnight(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 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 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.asText if (val1l != prev1l || val1h != prev1h || val2l != prev2l || val2h != prev2h) { s.append(formatColors(txt1, txt2)) s.append("
") diff --git a/core/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt b/core/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt index bb88afde62..1b6332a6d3 100644 --- a/core/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt +++ b/core/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt @@ -47,7 +47,7 @@ class EventPumpStatusChanged : EventStatus { // status for startup wizard override fun getStatus(rh: ResourceHelper): String { 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.CONNECTED -> rh.gs(R.string.connected) Status.PERFORMING -> performingAction diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt b/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt index 155fe96150..210141202d 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt @@ -97,7 +97,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) { } 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 { val pump = activePlugin.activePump diff --git a/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt b/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt index abd2c3be03..9c6fc45c17 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/HardLimits.kt @@ -94,9 +94,9 @@ class HardLimits @Inject constructor( if (newValue < lowLimit || newValue > highLimit) { newValue = max(newValue, lowLimit) 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 += String.format(rh.gs(R.string.valuelimitedto), value, newValue) + msg += rh.gs(R.string.valuelimitedto, value, newValue) aapsLogger.error(msg) disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(msg)).subscribe() ToastUtils.showToastInUiThread(context, rxBus, msg, R.raw.error) diff --git a/core/src/main/java/info/nightscout/androidaps/utils/protection/PasswordCheck.kt b/core/src/main/java/info/nightscout/androidaps/utils/protection/PasswordCheck.kt index c9099d0b54..a395cdc111 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/protection/PasswordCheck.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/protection/PasswordCheck.kt @@ -2,8 +2,12 @@ package info.nightscout.androidaps.utils.protection import android.annotation.SuppressLint import android.content.Context +import android.text.InputType import android.view.LayoutInflater 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.TextView import androidx.annotation.StringRes @@ -33,13 +37,12 @@ class PasswordCheck @Inject constructor( Asks for "managed" kind of password, checking if it is valid. */ @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, "") if (password == "") { ok?.invoke("") return } - val promptsView = LayoutInflater.from(context).inflate(R.layout.passwordprompt, null) val alertDialogBuilder = AlertDialogHelper.Builder(context, R.style.DialogTheme) alertDialogBuilder.setView(promptsView) @@ -48,40 +51,67 @@ class PasswordCheck @Inject constructor( val userInput2 = promptsView.findViewById(R.id.password_prompt_pass_confirm) as EditText 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) userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}") 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 .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() - 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, _ -> + .setPositiveButton(context.getString(R.string.ok)) { _, _ -> validatePassword() } + .setNegativeButton(context.getString(R.string.cancel)) { dialog, _ -> cancel?.invoke() 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") - 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 alertDialogBuilder = AlertDialogHelper.Builder(context, R.style.DialogTheme) alertDialogBuilder.setView(promptsView) val userInput = promptsView.findViewById(R.id.password_prompt_pass) as EditText val userInput2 = promptsView.findViewById(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) userInput.setAutofillHints(AUTOFILL_HINT_NEW_PASSWORD, "aaps_${autoFillHintPasswordKind}") userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES @@ -93,18 +123,22 @@ class PasswordCheck @Inject constructor( val enteredPassword = userInput.text.toString() val enteredPassword2 = userInput2.text.toString() 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()) { 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) } else { if (sp.contains(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() } 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() } } @@ -112,7 +146,8 @@ class PasswordCheck @Inject constructor( } .setNegativeButton(context.getString(R.string.cancel) ) { 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() dialog.cancel() } @@ -149,20 +184,35 @@ class PasswordCheck @Inject constructor( userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}") userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES + fun validatePassword() { + val enteredPassword = userInput.text.toString() + ok?.invoke(enteredPassword) + } + alertDialogBuilder .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() - ok?.invoke(enteredPassword) - } + .setPositiveButton(context.getString(R.string.ok)) { _, _ -> validatePassword() } .setNegativeButton(context.getString(R.string.cancel) ) { dialog, _ -> cancel?.invoke() 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 + } + } } /** diff --git a/core/src/main/java/info/nightscout/androidaps/utils/protection/ProtectionCheck.kt b/core/src/main/java/info/nightscout/androidaps/utils/protection/ProtectionCheck.kt index d06583e17d..7edc13830e 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/protection/ProtectionCheck.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/protection/ProtectionCheck.kt @@ -22,7 +22,8 @@ class ProtectionCheck @Inject constructor( NONE, BIOMETRIC, MASTER_PASSWORD, - CUSTOM_PASSWORD + CUSTOM_PASSWORD, + CUSTOM_PIN } private val passwordsResourceIDs = listOf( @@ -30,22 +31,33 @@ class ProtectionCheck @Inject constructor( R.string.key_application_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( R.string.key_settings_protection, R.string.key_application_protection, R.string.key_bolus_protection) - private val titleResourceIDs = listOf( + private val titlePassResourceIDs = listOf( R.string.settings_password, R.string.application_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 { return when (ProtectionType.values()[sp.getInt(protectionTypeResourceIDs[protection.ordinal], ProtectionType.NONE.ordinal)]) { ProtectionType.NONE -> false ProtectionType.BIOMETRIC -> true ProtectionType.MASTER_PASSWORD -> sp.getString(R.string.key_master_password, "") != "" 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 -> ok?.run() 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 -> passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { ok?.run() }, { cancel?.run() }, { fail?.run() }) 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) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelper.kt b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelper.kt index 8f6379d657..bdfdb76a92 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelper.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelper.kt @@ -1,5 +1,6 @@ package info.nightscout.androidaps.utils.resources +import android.content.Context import android.content.res.AssetFileDescriptor import android.graphics.Bitmap import android.graphics.drawable.Drawable @@ -11,7 +12,7 @@ interface ResourceHelper { fun gs(@StringRes id: 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 gc(@ColorRes id: Int): Int + @ColorInt fun gc(@ColorRes id: Int): Int fun gd(@DrawableRes id: Int): Drawable? fun gb(@BoolRes id :Int) : Boolean fun gcs(@ColorRes id: Int): String @@ -23,4 +24,13 @@ interface ResourceHelper { fun dpToPx(dp: Int): Int fun dpToPx(dp: Float): Int fun shortTextMode(): Boolean -} \ No newline at end of file + + /** + * 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 +} diff --git a/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperExtensions.kt b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperExtensions.kt new file mode 100644 index 0000000000..db31c42970 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperExtensions.kt @@ -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 + } diff --git a/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt index 86673862f4..0c6cd537b9 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt @@ -9,6 +9,7 @@ import android.graphics.BitmapFactory import android.graphics.drawable.Drawable import android.util.DisplayMetrics import androidx.annotation.* +import androidx.appcompat.view.ContextThemeWrapper import androidx.core.content.ContextCompat import info.nightscout.androidaps.core.R 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) -} \ No newline at end of file + + 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) +} diff --git a/core/src/main/res/layout/passwordprompt.xml b/core/src/main/res/layout/passwordprompt.xml index 90b14b14e4..ea4209edc3 100644 --- a/core/src/main/res/layout/passwordprompt.xml +++ b/core/src/main/res/layout/passwordprompt.xml @@ -14,8 +14,7 @@ android:paddingEnd="10dp" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/warningAccentText" - android:visibility="gone" - /> + android:visibility="gone" /> + android:inputType="textPassword" />
\ No newline at end of file diff --git a/core/src/main/res/values-sk-rSK/strings.xml b/core/src/main/res/values-sk-rSK/strings.xml index 9dd3823963..7c0a7758dc 100644 --- a/core/src/main/res/values-sk-rSK/strings.xml +++ b/core/src/main/res/values-sk-rSK/strings.xml @@ -4,6 +4,7 @@ Obnoviť Chyba + Uložiť Nenastavené Chyba pri aktualizovaní bazálneho profilu Bazálny profil v pumpe aktualizovaný @@ -376,6 +377,7 @@ RESET ŠTATISTÍK VYMAZAŤ LOGY VYMAZAŤ BUDÚCE OŠETRENIA + Odstrániť ošetrenia v budúcnosti EXPORTOVAŤ NASTAVENIA IMPORTOVAŤ NASTAVENIA RESETOVAŤ DATABÁZY diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index 85a25abfed..918e9b7114 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -7,4 +7,12 @@ + + + + + + + + \ No newline at end of file diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml index a6a7245cba..69de6e1abb 100644 --- a/core/src/main/res/values/colors.xml +++ b/core/src/main/res/values/colors.xml @@ -92,8 +92,14 @@ #1ea3e5 #1e88e5 - + #FF8C00 + #ff0400 + #ff5e55 + #ff827c + + + #009705 #666666 diff --git a/core/src/main/res/values/protection.xml b/core/src/main/res/values/protection.xml index 0b39654d2b..807106b726 100644 --- a/core/src/main/res/values/protection.xml +++ b/core/src/main/res/values/protection.xml @@ -7,11 +7,15 @@ Bolus protection Master password Settings password + Settings PIN Application password + Application PIN Bolus password + Bolus PIN Unlock settings Biometric Custom password + Custom PIN No protection Protection Master password is not set!\n\nPlease set your Master password in Preferences (%1$s → %2$s) @@ -19,15 +23,23 @@ In order to be effective, biometric protection needs a master password set for fallback.\n\nPlease set a master password! Password set! + PIN set! Password not set + PIN not set Password not changed + PIN not changed Password cleared! + PIN cleared! Enter password here + Enter PIN here master_password settings_password + settings_pin application_password + application_pin bolus_password + bolus_pin settings_protection application_protection bolus_protection diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ea72c80e9d..65ad75af76 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -222,7 +222,9 @@ Wrong password + Wrong PIN Passwords don\'t match + PINs don\'t match Basal values not aligned to hours: %1$s diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 31076be1d6..b22248a881 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -22,6 +22,12 @@ @color/white @color/white @color/white + + @color/notificationUrgent + @color/notificationNormal + @color/notificationLow + @color/notificationInfo + @color/notificationAnnouncement