feat: protection custom PIN
This commit is contained in:
parent
6b526f1a9c
commit
9ca96901b7
|
@ -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)
|
||||
|
|
|
@ -136,6 +136,7 @@
|
|||
<item>@string/biometric</item>
|
||||
<item>@string/master_password</item>
|
||||
<item>@string/custom_password</item>
|
||||
<item>@string/custom_pin</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="protectiontypeValues">
|
||||
|
@ -143,6 +144,7 @@
|
|||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -46,10 +46,13 @@
|
|||
android:title="@string/settings_protection" />
|
||||
|
||||
<Preference
|
||||
android:inputType="textPassword"
|
||||
android:key="@string/key_settings_password"
|
||||
android:title="@string/settings_password" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/key_settings_pin"
|
||||
android:title="@string/settings_pin" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/protectiontype"
|
||||
|
@ -58,10 +61,13 @@
|
|||
android:title="@string/application_protection" />
|
||||
|
||||
<Preference
|
||||
android:inputType="textPassword"
|
||||
android:key="@string/key_application_password"
|
||||
android:title="@string/application_password" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/key_application_pin"
|
||||
android:title="@string/application_pin" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/protectiontype"
|
||||
|
@ -70,10 +76,13 @@
|
|||
android:title="@string/bolus_protection" />
|
||||
|
||||
<Preference
|
||||
android:inputType="textPassword"
|
||||
android:key="@string/key_bolus_password"
|
||||
android:title="@string/bolus_password" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/key_bolus_pin"
|
||||
android:title="@string/bolus_pin" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<info.nightscout.androidaps.skins.SkinListPreference
|
||||
|
|
|
@ -2,6 +2,7 @@ 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.widget.EditText
|
||||
|
@ -33,13 +34,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,7 +48,10 @@ class PasswordCheck @Inject constructor(
|
|||
val userInput2 = promptsView.findViewById<View>(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
|
||||
|
@ -60,7 +63,8 @@ class PasswordCheck @Inject constructor(
|
|||
val enteredPassword = userInput.text.toString()
|
||||
if (cryptoUtil.checkPassword(enteredPassword, password)) ok?.invoke(enteredPassword)
|
||||
else {
|
||||
ToastUtils.errorToast(context, context.getString(R.string.wrongpassword))
|
||||
val msg = if (pinInput) R.string.wrongpin else R.string.wrongpassword
|
||||
ToastUtils.errorToast(context, context.getString(msg))
|
||||
fail?.invoke()
|
||||
}
|
||||
}
|
||||
|
@ -74,14 +78,19 @@ class PasswordCheck @Inject constructor(
|
|||
}
|
||||
|
||||
@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<View>(R.id.password_prompt_pass) 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)
|
||||
userInput.setAutofillHints(AUTOFILL_HINT_NEW_PASSWORD, "aaps_${autoFillHintPasswordKind}")
|
||||
userInput.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES
|
||||
|
@ -93,18 +102,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 +125,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()
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,8 +2,10 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:padding="10dp">
|
||||
android:padding="10dp"
|
||||
tools:context=".utils.protection.PasswordCheck">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/password_prompt_extra_message"
|
||||
|
|
|
@ -7,11 +7,15 @@
|
|||
<string name="bolus_protection">Bolus protection</string>
|
||||
<string name="master_password">Master 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_pin">Application PIN</string>
|
||||
<string name="bolus_password">Bolus password</string>
|
||||
<string name="bolus_pin">Bolus PIN</string>
|
||||
<string name="unlock_settings">Unlock settings</string>
|
||||
<string name="biometric">Biometric</string>
|
||||
<string name="custom_password">Custom password</string>
|
||||
<string name="custom_pin">Custom PIN</string>
|
||||
<string name="noprotection">No 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 → %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="password_set">Password set!</string>
|
||||
<string name="pin_set">PIN 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="pin_not_changed">PIN not changed</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="pin_hint">Enter PIN here</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_pin" translatable="false">settings_pin</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_pin" translatable="false">bolus_pin</string>
|
||||
<string name="key_settings_protection" translatable="false">settings_protection</string>
|
||||
<string name="key_application_protection" translatable="false">application_protection</string>
|
||||
<string name="key_bolus_protection" translatable="false">bolus_protection</string>
|
||||
|
|
|
@ -222,7 +222,9 @@
|
|||
|
||||
<!-- Protection-->
|
||||
<string name="wrongpassword">Wrong password</string>
|
||||
<string name="wrongpin">Wrong PIN</string>
|
||||
<string name="passwords_dont_match">Passwords don\'t match</string>
|
||||
<string name="pin_dont_match">PINs don\'t match</string>
|
||||
|
||||
<!-- Profile-->
|
||||
<string name="basalprofilenotaligned">Basal values not aligned to hours: %1$s</string>
|
||||
|
|
Loading…
Reference in a new issue