mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
fix: Password color and entropy view
This commit is contained in:
@@ -6,7 +6,7 @@ KeePassDX(4.1.0)
|
|||||||
* Fix date fields #1695 #1710
|
* Fix date fields #1695 #1710
|
||||||
* Fix distinct domain names #1105 #1820
|
* Fix distinct domain names #1105 #1820
|
||||||
* Support otpauth://steam/Steam link #1289
|
* Support otpauth://steam/Steam link #1289
|
||||||
* Small fixes #1711 #1831 #1780 #1821 #1863 #1889
|
* Small fixes #1711 #1831 #1780 #1821 #1863 #1889 #1490 #1355
|
||||||
|
|
||||||
KeePassDX(4.0.8)
|
KeePassDX(4.0.8)
|
||||||
* Fix graphical bug that prevented databases from being opened on some versions of Android #1848 #1850
|
* Fix graphical bug that prevented databases from being opened on some versions of Android #1848 #1850
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package com.kunzisoft.keepass.password
|
|||||||
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.text.Editable
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
@@ -253,51 +254,62 @@ class PasswordGenerator(private val resources: Resources) {
|
|||||||
return charSet.toString()
|
return charSet.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun colorizedPassword(editable: Editable?) {
|
||||||
|
editable.toString().forEachIndexed { index, char ->
|
||||||
|
colorFromChar(char)?.let { color ->
|
||||||
|
editable?.setSpan(
|
||||||
|
ForegroundColorSpan(color),
|
||||||
|
index,
|
||||||
|
index + 1,
|
||||||
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getColorizedPassword(password: String): Spannable {
|
fun getColorizedPassword(password: String): Spannable {
|
||||||
val spannableString = SpannableStringBuilder()
|
val spannableString = SpannableStringBuilder()
|
||||||
if (password.isNotEmpty()) {
|
if (password.isNotEmpty()) {
|
||||||
password.forEach {
|
password.forEach { char ->
|
||||||
when {
|
colorFromChar(char)?.let { color ->
|
||||||
UPPERCASE_CHARS.contains(it)||
|
val spannableColorChar = SpannableString(char.toString())
|
||||||
LOWERCASE_CHARS.contains(it) -> {
|
spannableColorChar.setSpan(
|
||||||
spannableString.append(it)
|
ForegroundColorSpan(color),
|
||||||
}
|
0,
|
||||||
DIGIT_CHARS.contains(it) -> {
|
1,
|
||||||
// RED
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
spannableString.append(colorizeChar(it, Color.rgb(246, 79, 62)))
|
)
|
||||||
}
|
spannableString.append(spannableColorChar)
|
||||||
SPECIAL_CHARS.contains(it) -> {
|
} ?: spannableString.append(char)
|
||||||
// Blue
|
|
||||||
spannableString.append(colorizeChar(it, Color.rgb(39, 166, 228)))
|
|
||||||
}
|
|
||||||
MINUS_CHAR.contains(it)||
|
|
||||||
UNDERLINE_CHAR.contains(it)||
|
|
||||||
BRACKET_CHARS.contains(it) -> {
|
|
||||||
// Purple
|
|
||||||
spannableString.append(colorizeChar(it, Color.rgb(185, 38, 209)))
|
|
||||||
}
|
|
||||||
extendedChars().contains(it) -> {
|
|
||||||
// Green
|
|
||||||
spannableString.append(colorizeChar(it, Color.rgb(44, 181, 50)))
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
spannableString.append(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return spannableString
|
return spannableString
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun colorizeChar(char: Char, color: Int): Spannable {
|
private fun colorFromChar(char: Char): Int? {
|
||||||
val spannableColorChar = SpannableString(char.toString())
|
return when {
|
||||||
spannableColorChar.setSpan(
|
DIGIT_CHARS.contains(char) -> {
|
||||||
ForegroundColorSpan(color),
|
// RED
|
||||||
0,
|
Color.rgb(246, 79, 62)
|
||||||
1,
|
}
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
SPECIAL_CHARS.contains(char) -> {
|
||||||
)
|
// Blue
|
||||||
return spannableColorChar
|
Color.rgb(39, 166, 228)
|
||||||
|
}
|
||||||
|
MINUS_CHAR.contains(char)||
|
||||||
|
UNDERLINE_CHAR.contains(char)||
|
||||||
|
BRACKET_CHARS.contains(char) -> {
|
||||||
|
// Purple
|
||||||
|
Color.rgb(185, 38, 209)
|
||||||
|
}
|
||||||
|
extendedChars().contains(char) -> {
|
||||||
|
// Green
|
||||||
|
Color.rgb(44, 181, 50)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ import android.widget.TextView
|
|||||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.password.PasswordGenerator
|
|
||||||
import com.kunzisoft.keepass.password.PasswordEntropy
|
import com.kunzisoft.keepass.password.PasswordEntropy
|
||||||
|
import com.kunzisoft.keepass.password.PasswordGenerator
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
|
|
||||||
class PasswordEditView @JvmOverloads constructor(context: Context,
|
class PasswordEditView @JvmOverloads constructor(context: Context,
|
||||||
@@ -46,7 +46,6 @@ class PasswordEditView @JvmOverloads constructor(context: Context,
|
|||||||
|
|
||||||
private val passwordInputLayout: TextInputLayout
|
private val passwordInputLayout: TextInputLayout
|
||||||
private val passwordText: EditText
|
private val passwordText: EditText
|
||||||
private var textModified = false
|
|
||||||
private val passwordStrengthProgress: LinearProgressIndicator
|
private val passwordStrengthProgress: LinearProgressIndicator
|
||||||
private val passwordEntropy: TextView
|
private val passwordEntropy: TextView
|
||||||
|
|
||||||
@@ -76,22 +75,22 @@ class PasswordEditView @JvmOverloads constructor(context: Context,
|
|||||||
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?
|
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?
|
||||||
inflater?.inflate(R.layout.view_password_edit, this)
|
inflater?.inflate(R.layout.view_password_edit, this)
|
||||||
|
|
||||||
passwordInputLayout = findViewById(R.id.password_input_layout)
|
passwordInputLayout = findViewById(R.id.password_edit_input_layout)
|
||||||
passwordInputLayout?.hint = mViewHint
|
passwordInputLayout?.hint = mViewHint
|
||||||
passwordText = findViewById(R.id.password_text)
|
passwordText = findViewById(R.id.password_edit_text)
|
||||||
if (mShowPassword) {
|
if (mShowPassword) {
|
||||||
passwordText?.inputType = passwordText.inputType or
|
passwordText?.inputType = passwordText.inputType or
|
||||||
InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|
InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|
||||||
}
|
}
|
||||||
passwordText?.maxLines = mMaxLines
|
passwordText?.maxLines = mMaxLines
|
||||||
passwordText?.applyFontVisibility()
|
passwordText?.applyFontVisibility()
|
||||||
passwordStrengthProgress = findViewById(R.id.password_strength_progress)
|
passwordStrengthProgress = findViewById(R.id.password_edit_strength_progress)
|
||||||
passwordStrengthProgress?.apply {
|
passwordStrengthProgress?.apply {
|
||||||
setIndicatorColor(PasswordEntropy.Strength.RISKY.color)
|
setIndicatorColor(PasswordEntropy.Strength.RISKY.color)
|
||||||
progress = 0
|
progress = 0
|
||||||
max = 100
|
max = 100
|
||||||
}
|
}
|
||||||
passwordEntropy = findViewById(R.id.password_entropy)
|
passwordEntropy = findViewById(R.id.password_edit_entropy)
|
||||||
|
|
||||||
mPasswordEntropyCalculator = PasswordEntropy {
|
mPasswordEntropyCalculator = PasswordEntropy {
|
||||||
passwordText?.text?.toString()?.let { firstPassword ->
|
passwordText?.text?.toString()?.let { firstPassword ->
|
||||||
@@ -113,20 +112,11 @@ class PasswordEditView @JvmOverloads constructor(context: Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun afterTextChanged(editable: Editable) {
|
override fun afterTextChanged(editable: Editable) {
|
||||||
/* Fixme 1686
|
|
||||||
if (textModified) {
|
|
||||||
textModified = false
|
|
||||||
} else {
|
|
||||||
textModified = true
|
|
||||||
val selectionStart = passwordText.selectionStart
|
|
||||||
val selectionEnd = passwordText.selectionEnd
|
|
||||||
passwordString = editable.toString()
|
|
||||||
passwordText.setSelection(selectionStart, selectionEnd)
|
|
||||||
}*/
|
|
||||||
mPasswordTextWatchers.forEach {
|
mPasswordTextWatchers.forEach {
|
||||||
it.afterTextChanged(editable)
|
it.afterTextChanged(editable)
|
||||||
}
|
}
|
||||||
getEntropyStrength(editable.toString())
|
getEntropyStrength(editable.toString())
|
||||||
|
PasswordGenerator.colorizedPassword(editable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
passwordText?.addTextChangedListener(mPasswordTextWatcher)
|
passwordText?.addTextChangedListener(mPasswordTextWatcher)
|
||||||
|
|||||||
@@ -2,13 +2,19 @@ package com.kunzisoft.keepass.view
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.text.Spannable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.setPadding
|
import androidx.core.view.setPadding
|
||||||
|
import androidx.core.widget.TextViewCompat
|
||||||
|
import androidx.core.widget.doAfterTextChanged
|
||||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.password.PasswordEntropy
|
import com.kunzisoft.keepass.password.PasswordEntropy
|
||||||
|
import com.kunzisoft.keepass.password.PasswordGenerator
|
||||||
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
|
|
||||||
|
|
||||||
class PasswordTextEditFieldView @JvmOverloads constructor(context: Context,
|
class PasswordTextEditFieldView @JvmOverloads constructor(context: Context,
|
||||||
@@ -16,15 +22,23 @@ class PasswordTextEditFieldView @JvmOverloads constructor(context: Context,
|
|||||||
defStyle: Int = 0)
|
defStyle: Int = 0)
|
||||||
: TextEditFieldView(context, attrs, defStyle) {
|
: TextEditFieldView(context, attrs, defStyle) {
|
||||||
|
|
||||||
|
private var mPasswordEntropyCalculator: PasswordEntropy = PasswordEntropy {
|
||||||
|
valueView.text?.toString()?.let { firstPassword ->
|
||||||
|
getEntropyStrength(firstPassword)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private var isColorizedPasswordActivated = PreferencesUtil.colorizePassword(context)
|
||||||
|
|
||||||
private var passwordProgressViewId = ViewCompat.generateViewId()
|
private var passwordProgressViewId = ViewCompat.generateViewId()
|
||||||
private var passwordEntropyViewId = ViewCompat.generateViewId()
|
private var passwordEntropyViewId = ViewCompat.generateViewId()
|
||||||
|
|
||||||
private var mPasswordProgress = LinearProgressIndicator(context).apply {
|
private var mPasswordProgress = LinearProgressIndicator(context).apply {
|
||||||
layoutParams = LayoutParams(
|
layoutParams = LayoutParams(
|
||||||
LayoutParams.MATCH_PARENT,
|
LayoutParams.MATCH_PARENT,
|
||||||
LayoutParams.WRAP_CONTENT).apply {
|
LayoutParams.WRAP_CONTENT
|
||||||
addRule(ALIGN_PARENT_BOTTOM)
|
).apply {
|
||||||
}
|
addRule(ALIGN_PARENT_BOTTOM)
|
||||||
|
}
|
||||||
setPadding(
|
setPadding(
|
||||||
TypedValue.applyDimension(
|
TypedValue.applyDimension(
|
||||||
TypedValue.COMPLEX_UNIT_DIP,
|
TypedValue.COMPLEX_UNIT_DIP,
|
||||||
@@ -38,22 +52,30 @@ class PasswordTextEditFieldView @JvmOverloads constructor(context: Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val mPasswordEntropyView = TextView(context).apply {
|
private val mPasswordEntropyView = TextView(context).apply {
|
||||||
LayoutParams(
|
layoutParams = LayoutParams(
|
||||||
LayoutParams.WRAP_CONTENT,
|
LayoutParams.WRAP_CONTENT,
|
||||||
LayoutParams.WRAP_CONTENT).apply {
|
LayoutParams.WRAP_CONTENT
|
||||||
addRule(ALIGN_PARENT_BOTTOM or ALIGN_PARENT_RIGHT)
|
).apply {
|
||||||
}
|
addRule(ALIGN_PARENT_BOTTOM)
|
||||||
}
|
|
||||||
|
|
||||||
private var mPasswordEntropyCalculator: PasswordEntropy = PasswordEntropy {
|
|
||||||
valueView.text?.toString()?.let { firstPassword ->
|
|
||||||
getEntropyStrength(firstPassword)
|
|
||||||
}
|
}
|
||||||
|
setPadding(
|
||||||
|
TypedValue.applyDimension(
|
||||||
|
TypedValue.COMPLEX_UNIT_DIP,
|
||||||
|
4f,
|
||||||
|
context.resources.displayMetrics
|
||||||
|
).toInt()
|
||||||
|
)
|
||||||
|
TextViewCompat.setTextAppearance(this, R.style.KeepassDXStyle_Text_Indicator)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
buildViews()
|
buildViews()
|
||||||
|
|
||||||
|
valueView.doAfterTextChanged { editable ->
|
||||||
|
getEntropyStrength(editable.toString())
|
||||||
|
PasswordGenerator.colorizedPassword(editable)
|
||||||
|
}
|
||||||
|
|
||||||
addView(mPasswordProgress)
|
addView(mPasswordProgress)
|
||||||
addView(mPasswordEntropyView)
|
addView(mPasswordEntropyView)
|
||||||
}
|
}
|
||||||
@@ -71,9 +93,9 @@ class PasswordTextEditFieldView @JvmOverloads constructor(context: Context,
|
|||||||
mPasswordEntropyView.apply {
|
mPasswordEntropyView.apply {
|
||||||
id = passwordEntropyViewId
|
id = passwordEntropyViewId
|
||||||
layoutParams = (layoutParams as LayoutParams?)?.also {
|
layoutParams = (layoutParams as LayoutParams?)?.also {
|
||||||
it.addRule(LEFT_OF, actionImageButtonId)
|
it.addRule(ALIGN_RIGHT, passwordProgressViewId)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||||
it.addRule(START_OF, actionImageButtonId)
|
it.addRule(ALIGN_END, passwordProgressViewId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,6 +117,15 @@ class PasswordTextEditFieldView @JvmOverloads constructor(context: Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun spannableValue(value: String?): Spannable? {
|
||||||
|
if (value == null)
|
||||||
|
return null
|
||||||
|
return if (isColorizedPasswordActivated)
|
||||||
|
PasswordGenerator.getColorizedPassword(value)
|
||||||
|
else
|
||||||
|
super.spannableValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
override var label: String
|
override var label: String
|
||||||
get() {
|
get() {
|
||||||
return super.label
|
return super.label
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import com.kunzisoft.keepass.database.element.template.TemplateAttribute
|
|||||||
import com.kunzisoft.keepass.database.element.template.TemplateAttributeAction
|
import com.kunzisoft.keepass.database.element.template.TemplateAttributeAction
|
||||||
import com.kunzisoft.keepass.database.element.template.TemplateField
|
import com.kunzisoft.keepass.database.element.template.TemplateField
|
||||||
import com.kunzisoft.keepass.database.helper.getLocalizedName
|
import com.kunzisoft.keepass.database.helper.getLocalizedName
|
||||||
|
import com.kunzisoft.keepass.database.helper.isStandardPasswordName
|
||||||
import com.kunzisoft.keepass.model.DataDate
|
import com.kunzisoft.keepass.model.DataDate
|
||||||
import com.kunzisoft.keepass.model.DataTime
|
import com.kunzisoft.keepass.model.DataTime
|
||||||
import com.kunzisoft.keepass.otp.OtpEntryFields
|
import com.kunzisoft.keepass.otp.OtpEntryFields
|
||||||
@@ -113,7 +114,7 @@ class TemplateEditView @JvmOverloads constructor(context: Context,
|
|||||||
override fun buildLinearTextView(templateAttribute: TemplateAttribute,
|
override fun buildLinearTextView(templateAttribute: TemplateAttribute,
|
||||||
field: Field): TextEditFieldView? {
|
field: Field): TextEditFieldView? {
|
||||||
return context?.let {
|
return context?.let {
|
||||||
(if (templateAttribute.label == TemplateField.LABEL_PASSWORD)
|
(if (TemplateField.isStandardPasswordName(context, templateAttribute.label))
|
||||||
PasswordTextEditFieldView(it)
|
PasswordTextEditFieldView(it)
|
||||||
else TextEditFieldView(it)).apply {
|
else TextEditFieldView(it)).apply {
|
||||||
// hiddenProtectedValue (mHideProtectedValue) don't work with TextInputLayout
|
// hiddenProtectedValue (mHideProtectedValue) don't work with TextInputLayout
|
||||||
|
|||||||
@@ -8,23 +8,19 @@ import android.text.Spannable
|
|||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.ContextThemeWrapper
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
import androidx.appcompat.widget.AppCompatImageButton
|
import androidx.appcompat.widget.AppCompatImageButton
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.doAfterTextChanged
|
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.database.element.template.TemplateField
|
|
||||||
import com.kunzisoft.keepass.database.helper.isStandardPasswordName
|
|
||||||
import com.kunzisoft.keepass.password.PasswordGenerator
|
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
|
|
||||||
open class TextEditFieldView @JvmOverloads constructor(context: Context,
|
open class TextEditFieldView @JvmOverloads constructor(context: Context,
|
||||||
@@ -36,17 +32,16 @@ open class TextEditFieldView @JvmOverloads constructor(context: Context,
|
|||||||
private var valueViewId = ViewCompat.generateViewId()
|
private var valueViewId = ViewCompat.generateViewId()
|
||||||
protected var actionImageButtonId = ViewCompat.generateViewId()
|
protected var actionImageButtonId = ViewCompat.generateViewId()
|
||||||
|
|
||||||
private var textModified = false
|
private val labelView = TextInputLayout(context).apply {
|
||||||
private var isColorizedPasswordActivated = PreferencesUtil.colorizePassword(context)
|
|
||||||
|
|
||||||
protected val labelView = TextInputLayout(context).apply {
|
|
||||||
layoutParams = LayoutParams(
|
layoutParams = LayoutParams(
|
||||||
LayoutParams.MATCH_PARENT,
|
LayoutParams.MATCH_PARENT,
|
||||||
LayoutParams.WRAP_CONTENT)
|
LayoutParams.WRAP_CONTENT)
|
||||||
}
|
}
|
||||||
protected val valueView = TextInputEditText(
|
protected val valueView = TextInputEditText(
|
||||||
ContextThemeWrapper(getContext(),
|
ContextThemeWrapper(
|
||||||
R.style.KeepassDXStyle_TextInputLayout)
|
getContext(),
|
||||||
|
R.style.KeepassDXStyle_TextInputLayout
|
||||||
|
)
|
||||||
).apply {
|
).apply {
|
||||||
layoutParams = LinearLayout.LayoutParams(
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
LayoutParams.MATCH_PARENT,
|
LayoutParams.MATCH_PARENT,
|
||||||
@@ -62,7 +57,10 @@ open class TextEditFieldView @JvmOverloads constructor(context: Context,
|
|||||||
maxLines = 1
|
maxLines = 1
|
||||||
}
|
}
|
||||||
private var actionImageButton = AppCompatImageButton(
|
private var actionImageButton = AppCompatImageButton(
|
||||||
ContextThemeWrapper(context, R.style.KeepassDXStyle_ImageButton_Simple), null, 0).apply {
|
ContextThemeWrapper(
|
||||||
|
context,
|
||||||
|
R.style.KeepassDXStyle_ImageButton_Simple
|
||||||
|
), null, 0).apply {
|
||||||
layoutParams = LayoutParams(
|
layoutParams = LayoutParams(
|
||||||
LayoutParams.WRAP_CONTENT,
|
LayoutParams.WRAP_CONTENT,
|
||||||
LayoutParams.WRAP_CONTENT).also {
|
LayoutParams.WRAP_CONTENT).also {
|
||||||
@@ -83,21 +81,6 @@ open class TextEditFieldView @JvmOverloads constructor(context: Context,
|
|||||||
init {
|
init {
|
||||||
// Manually write view to avoid view id bugs
|
// Manually write view to avoid view id bugs
|
||||||
buildViews()
|
buildViews()
|
||||||
// To change the password color dynamically
|
|
||||||
/* Fixme 1686
|
|
||||||
valueView.doAfterTextChanged { editable ->
|
|
||||||
editable?.let { text ->
|
|
||||||
if (textModified) {
|
|
||||||
textModified = false
|
|
||||||
} else {
|
|
||||||
textModified = true
|
|
||||||
val selectionStart = valueView.selectionStart
|
|
||||||
val selectionEnd = valueView.selectionEnd
|
|
||||||
value = text.toString()
|
|
||||||
valueView.setSelection(selectionStart, selectionEnd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
labelView.addView(valueView)
|
labelView.addView(valueView)
|
||||||
addView(labelView)
|
addView(labelView)
|
||||||
addView(actionImageButton)
|
addView(actionImageButton)
|
||||||
@@ -130,15 +113,6 @@ open class TextEditFieldView @JvmOverloads constructor(context: Context,
|
|||||||
return actionImageButton
|
return actionImageButton
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun spannableValue(value: String?): Spannable? {
|
|
||||||
if (value == null)
|
|
||||||
return null
|
|
||||||
return if (isColorizedPasswordActivated && TemplateField.isStandardPasswordName(context, label))
|
|
||||||
PasswordGenerator.getColorizedPassword(value)
|
|
||||||
else
|
|
||||||
SpannableString(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override var label: String
|
override var label: String
|
||||||
get() {
|
get() {
|
||||||
return labelView.hint?.toString() ?: ""
|
return labelView.hint?.toString() ?: ""
|
||||||
@@ -152,6 +126,10 @@ open class TextEditFieldView @JvmOverloads constructor(context: Context,
|
|||||||
buildViews()
|
buildViews()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun spannableValue(value: String?): Spannable? {
|
||||||
|
return SpannableString(value)
|
||||||
|
}
|
||||||
|
|
||||||
override var value: String
|
override var value: String
|
||||||
get() {
|
get() {
|
||||||
return valueView.text?.toString() ?: ""
|
return valueView.text?.toString() ?: ""
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/password_input_layout"
|
android:id="@+id/password_edit_input_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
tools:ignore="UnusedAttribute">
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/password_text"
|
android:id="@+id/password_edit_text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ems="10"
|
android:ems="10"
|
||||||
@@ -31,23 +31,21 @@
|
|||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
android:id="@+id/password_strength_progress"
|
android:id="@+id/password_edit_strength_progress"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="1dp"
|
android:padding="1dp"
|
||||||
app:trackCornerRadius="8dp"
|
app:trackCornerRadius="8dp"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/password_input_layout"/>
|
app:layout_constraintBottom_toBottomOf="@+id/password_edit_input_layout"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/password_entropy"
|
android:id="@+id/password_edit_entropy"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:text="Entropy: 72.50 bit"
|
tools:text="Entropy: 72.50 bit"
|
||||||
android:textSize="11sp"
|
style="@style/KeepassDXStyle.Text.Indicator"
|
||||||
android:layout_margin="4dp"
|
android:padding="4dp"
|
||||||
android:textColor="?attr/colorSecondary"
|
app:layout_constraintBottom_toBottomOf="@+id/password_edit_input_layout"
|
||||||
android:textStyle="bold"
|
app:layout_constraintEnd_toEndOf="@+id/password_edit_input_layout" />
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/password_input_layout"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/password_input_layout" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -416,6 +416,13 @@
|
|||||||
<item name="backgroundTint">?attr/colorSecondary</item>
|
<item name="backgroundTint">?attr/colorSecondary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- Indicator -->
|
||||||
|
<style name="KeepassDXStyle.Text.Indicator" parent="KeepassDXStyle.Text">
|
||||||
|
<item name="android:textSize">11sp</item>
|
||||||
|
<item name="android:textColor">?attr/colorSecondary</item>
|
||||||
|
<item name="android:textStyle">bold</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<!-- Nodes Text Style -->
|
<!-- Nodes Text Style -->
|
||||||
<style name="KeepassDXStyle.Title.Entry" parent="KeepassDXStyle.Text">
|
<style name="KeepassDXStyle.Title.Entry" parent="KeepassDXStyle.Text">
|
||||||
<item name="android:textColor">@color/text_primary_color</item>
|
<item name="android:textColor">@color/text_primary_color</item>
|
||||||
|
|||||||
@@ -5,4 +5,4 @@
|
|||||||
* Fix date fields #1695 #1710
|
* Fix date fields #1695 #1710
|
||||||
* Fix distinct domain names #1105 #1820
|
* Fix distinct domain names #1105 #1820
|
||||||
* Support otpauth://steam/Steam link #1289
|
* Support otpauth://steam/Steam link #1289
|
||||||
* Small fixes #1711 #1831 #1780 #1821 #1863 #1889
|
* Small fixes #1711 #1831 #1780 #1821 #1863 #1889 #1490 #1355
|
||||||
@@ -5,4 +5,4 @@
|
|||||||
* Correction des champs date #1695 #1710
|
* Correction des champs date #1695 #1710
|
||||||
* Correction des noms de domaines #1105 #1820
|
* Correction des noms de domaines #1105 #1820
|
||||||
* Support des liens otpauth://steam/Steam #1289
|
* Support des liens otpauth://steam/Steam #1289
|
||||||
* Petites corrections #1711 #1831 #1780 #1821 #1863
|
* Petites corrections #1711 #1831 #1780 #1821 #1863 #1490 #1355
|
||||||
Reference in New Issue
Block a user