For 10172: Set edit text listeners (#11196)
* Set edit text listeners * Set clearable icons and change with error states * Clear text buttons show and hide * Move error checks to afterTextChanged. Refactor. Remove unused color.master
parent
31edbc924c
commit
137d66a511
|
@ -7,30 +7,24 @@ package org.mozilla.fenix.settings.logins
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
|
import android.text.TextWatcher
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import kotlinx.android.synthetic.main.fragment_edit_login.*
|
||||||
import kotlinx.android.synthetic.main.fragment_edit_login.inputLayoutPassword
|
|
||||||
import kotlinx.android.synthetic.main.fragment_edit_login.inputLayoutUsername
|
|
||||||
import kotlinx.android.synthetic.main.fragment_edit_login.hostnameText
|
|
||||||
import kotlinx.android.synthetic.main.fragment_edit_login.usernameText
|
|
||||||
import kotlinx.android.synthetic.main.fragment_edit_login.passwordText
|
|
||||||
import kotlinx.android.synthetic.main.fragment_edit_login.clearUsernameTextButton
|
|
||||||
import kotlinx.android.synthetic.main.fragment_edit_login.clearPasswordTextButton
|
|
||||||
import kotlinx.android.synthetic.main.fragment_edit_login.revealPasswordButton
|
|
||||||
import kotlinx.coroutines.Deferred
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import mozilla.components.concept.storage.Login
|
import mozilla.components.concept.storage.Login
|
||||||
import mozilla.components.service.sync.logins.InvalidRecordException
|
import mozilla.components.service.sync.logins.InvalidRecordException
|
||||||
|
@ -38,7 +32,6 @@ import mozilla.components.service.sync.logins.LoginsStorageException
|
||||||
import mozilla.components.service.sync.logins.NoSuchRecordException
|
import mozilla.components.service.sync.logins.NoSuchRecordException
|
||||||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.components.FenixSnackbar
|
|
||||||
import org.mozilla.fenix.components.StoreProvider
|
import org.mozilla.fenix.components.StoreProvider
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
|
@ -55,10 +48,12 @@ class EditLoginFragment : Fragment(R.layout.fragment_edit_login) {
|
||||||
private lateinit var savedLoginsStore: LoginsFragmentStore
|
private lateinit var savedLoginsStore: LoginsFragmentStore
|
||||||
fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
|
fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
|
||||||
|
|
||||||
|
private lateinit var oldLogin: SavedLogin
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
|
oldLogin = args.savedLoginItem
|
||||||
savedLoginsStore = StoreProvider.get(this) {
|
savedLoginsStore = StoreProvider.get(this) {
|
||||||
LoginsFragmentStore(
|
LoginsFragmentStore(
|
||||||
LoginsListState(
|
LoginsListState(
|
||||||
|
@ -82,12 +77,16 @@ class EditLoginFragment : Fragment(R.layout.fragment_edit_login) {
|
||||||
hostnameText.isFocusable = false
|
hostnameText.isFocusable = false
|
||||||
|
|
||||||
usernameText.text = args.savedLoginItem.username.toEditable()
|
usernameText.text = args.savedLoginItem.username.toEditable()
|
||||||
passwordText.text = args.savedLoginItem.password!!.toEditable()
|
passwordText.text = args.savedLoginItem.password.toEditable()
|
||||||
|
|
||||||
// TODO: extend PasswordTransformationMethod() to change bullets to asterisks
|
// TODO: extend PasswordTransformationMethod() to change bullets to asterisks
|
||||||
passwordText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
|
passwordText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
|
||||||
|
passwordText.compoundDrawablePadding =
|
||||||
|
requireContext().resources
|
||||||
|
.getDimensionPixelOffset(R.dimen.saved_logins_end_icon_drawable_padding)
|
||||||
|
|
||||||
setUpClickListeners()
|
setUpClickListeners()
|
||||||
|
setUpTextListeners()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpClickListeners() {
|
private fun setUpClickListeners() {
|
||||||
|
@ -96,18 +95,100 @@ class EditLoginFragment : Fragment(R.layout.fragment_edit_login) {
|
||||||
usernameText.isCursorVisible = true
|
usernameText.isCursorVisible = true
|
||||||
usernameText.hasFocus()
|
usernameText.hasFocus()
|
||||||
inputLayoutUsername.hasFocus()
|
inputLayoutUsername.hasFocus()
|
||||||
|
it.isEnabled = false
|
||||||
}
|
}
|
||||||
clearPasswordTextButton.setOnClickListener {
|
clearPasswordTextButton.setOnClickListener {
|
||||||
passwordText.text?.clear()
|
passwordText.text?.clear()
|
||||||
passwordText.isCursorVisible = true
|
passwordText.isCursorVisible = true
|
||||||
passwordText.hasFocus()
|
passwordText.hasFocus()
|
||||||
inputLayoutPassword.hasFocus()
|
inputLayoutPassword.hasFocus()
|
||||||
|
it.isEnabled = false
|
||||||
}
|
}
|
||||||
revealPasswordButton.setOnClickListener {
|
revealPasswordButton.setOnClickListener {
|
||||||
togglePasswordReveal()
|
togglePasswordReveal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var firstClick = true
|
||||||
passwordText.setOnClickListener {
|
passwordText.setOnClickListener {
|
||||||
togglePasswordReveal()
|
if (firstClick) {
|
||||||
|
togglePasswordReveal()
|
||||||
|
firstClick = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setUpTextListeners() {
|
||||||
|
val frag = view?.findViewById<View>(R.id.editLoginFragment)
|
||||||
|
frag?.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
|
||||||
|
if (hasFocus) {
|
||||||
|
view?.hideKeyboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editLoginLayout.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
|
||||||
|
if (!hasFocus) {
|
||||||
|
view?.hideKeyboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usernameText.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun afterTextChanged(u: Editable?) {
|
||||||
|
if (u.toString() == oldLogin.username) {
|
||||||
|
inputLayoutUsername.error = null
|
||||||
|
inputLayoutUsername.errorIconDrawable = null
|
||||||
|
} else {
|
||||||
|
clearUsernameTextButton.isEnabled = true
|
||||||
|
// setDupeError() TODO in #10173
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beforeTextChanged(u: CharSequence?, start: Int, count: Int, after: Int) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(u: CharSequence?, start: Int, before: Int, count: Int) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
passwordText.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun afterTextChanged(p: Editable?) {
|
||||||
|
when {
|
||||||
|
p.toString().isEmpty() -> {
|
||||||
|
clearPasswordTextButton.isEnabled = false
|
||||||
|
setPasswordError()
|
||||||
|
}
|
||||||
|
p.toString() == oldLogin.password -> {
|
||||||
|
inputLayoutPassword.error = null
|
||||||
|
inputLayoutPassword.errorIconDrawable = null
|
||||||
|
clearPasswordTextButton.isEnabled = true
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
inputLayoutPassword.error = null
|
||||||
|
inputLayoutPassword.errorIconDrawable = null
|
||||||
|
clearPasswordTextButton.isEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beforeTextChanged(p: CharSequence?, start: Int, count: Int, after: Int) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(p: CharSequence?, start: Int, before: Int, count: Int) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setPasswordError() {
|
||||||
|
inputLayoutPassword?.let { layout ->
|
||||||
|
layout.error = context?.getString(R.string.saved_login_password_required)
|
||||||
|
layout.setErrorIconDrawable(R.drawable.mozac_ic_warning)
|
||||||
|
|
||||||
|
layout.errorIconDrawable?.setTint(
|
||||||
|
ContextCompat.getColor(requireContext(), R.color.design_default_color_error)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,26 +207,26 @@ class EditLoginFragment : Fragment(R.layout.fragment_edit_login) {
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
|
||||||
R.id.save_login_button -> {
|
R.id.save_login_button -> {
|
||||||
view?.hideKeyboard()
|
view?.hideKeyboard()
|
||||||
try {
|
if (!passwordText.text.isNullOrBlank()) {
|
||||||
if (!passwordText.text.isNullOrBlank()) {
|
try {
|
||||||
attemptSaveAndExit()
|
attemptSaveAndExit()
|
||||||
} else {
|
} catch (loginException: LoginsStorageException) {
|
||||||
view?.let {
|
when (loginException) {
|
||||||
FenixSnackbar.make(
|
is NoSuchRecordException,
|
||||||
view = it,
|
is InvalidRecordException -> {
|
||||||
duration = Snackbar.LENGTH_SHORT,
|
Log.e(
|
||||||
isDisplayedWithBrowserToolbar = false
|
"Edit login",
|
||||||
).setText(getString(R.string.saved_login_password_required)).show()
|
"Failed to save edited login.",
|
||||||
|
loginException
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> Log.e(
|
||||||
|
"Edit login",
|
||||||
|
"Failed to save edited login.",
|
||||||
|
loginException
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (loginException: LoginsStorageException) {
|
|
||||||
when (loginException) {
|
|
||||||
is NoSuchRecordException,
|
|
||||||
is InvalidRecordException -> {
|
|
||||||
Log.e("Edit login", "Failed to save edited login.", loginException)
|
|
||||||
}
|
|
||||||
else -> Log.e("Edit login", "Failed to save edited login.", loginException)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -158,9 +239,11 @@ class EditLoginFragment : Fragment(R.layout.fragment_edit_login) {
|
||||||
var saveLoginJob: Deferred<Unit>? = null
|
var saveLoginJob: Deferred<Unit>? = null
|
||||||
viewLifecycleOwner.lifecycleScope.launch(IO) {
|
viewLifecycleOwner.lifecycleScope.launch(IO) {
|
||||||
saveLoginJob = async {
|
saveLoginJob = async {
|
||||||
val oldLogin = requireContext().components.core.passwordsStorage.get(args.savedLoginItem.guid)
|
val oldLogin =
|
||||||
|
requireContext().components.core.passwordsStorage.get(args.savedLoginItem.guid)
|
||||||
|
|
||||||
// Update requires a Login type, which needs at least one of httpRealm or formActionOrigin
|
// Update requires a Login type, which needs at least one of
|
||||||
|
// httpRealm or formActionOrigin
|
||||||
val loginToSave = Login(
|
val loginToSave = Login(
|
||||||
guid = oldLogin?.guid,
|
guid = oldLogin?.guid,
|
||||||
origin = oldLogin?.origin!!,
|
origin = oldLogin?.origin!!,
|
||||||
|
|
|
@ -24,7 +24,7 @@ data class SavedLogin(
|
||||||
val guid: String,
|
val guid: String,
|
||||||
val origin: String,
|
val origin: String,
|
||||||
val username: String,
|
val username: String,
|
||||||
val password: String?,
|
val password: String,
|
||||||
val timeLastUsed: Long
|
val timeLastUsed: Long
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_enabled="true"
|
||||||
|
android:color="?primaryText" />
|
||||||
|
<item android:state_enabled="false"
|
||||||
|
android:color="@android:color/transparent" />
|
||||||
|
</selector>
|
|
@ -12,7 +12,9 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="72dp"
|
android:layout_marginStart="72dp"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
android:layout_marginTop="12dp" >
|
android:layout_marginTop="12dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/hostnameHeaderText"
|
android:id="@+id/hostnameHeaderText"
|
||||||
|
@ -125,7 +127,7 @@
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:cursorVisible="true"
|
android:cursorVisible="true"
|
||||||
android:textCursorDrawable="?primaryText"
|
android:textCursorDrawable="@null"
|
||||||
app:backgroundTint="?primaryText"
|
app:backgroundTint="?primaryText"
|
||||||
tools:ignore="Autofill"/>
|
tools:ignore="Autofill"/>
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
@ -135,9 +137,9 @@
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="30dp"
|
android:layout_height="30dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="@null"
|
||||||
android:contentDescription="@string/saved_login_copy_username"
|
android:contentDescription="@string/saved_login_copy_username"
|
||||||
app:tint="?android:colorAccent"
|
app:tint="@color/saved_login_clear_edit_text_tint"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/inputLayoutUsername"
|
app:layout_constraintBottom_toBottomOf="@id/inputLayoutUsername"
|
||||||
app:srcCompat="@drawable/ic_clear" />
|
app:srcCompat="@drawable/ic_clear" />
|
||||||
|
@ -186,6 +188,7 @@
|
||||||
android:colorControlActivated="?primaryText"
|
android:colorControlActivated="?primaryText"
|
||||||
android:colorControlHighlight="?primaryText"
|
android:colorControlHighlight="?primaryText"
|
||||||
android:cursorVisible="true"
|
android:cursorVisible="true"
|
||||||
|
android:textCursorDrawable="@null"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:fontFamily="sans-serif"
|
android:fontFamily="sans-serif"
|
||||||
|
@ -195,7 +198,6 @@
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:textColor="?primaryText"
|
android:textColor="?primaryText"
|
||||||
android:textCursorDrawable="?primaryText"
|
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="normal"
|
android:textStyle="normal"
|
||||||
app:backgroundTint="?primaryText"
|
app:backgroundTint="?primaryText"
|
||||||
|
@ -207,9 +209,9 @@
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="30dp"
|
android:layout_height="30dp"
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="@null"
|
||||||
android:contentDescription="@string/saved_login_reveal_password"
|
android:contentDescription="@string/saved_login_reveal_password"
|
||||||
app:tint="?android:colorAccent"
|
app:tint="?primaryText"
|
||||||
app:layout_constraintEnd_toStartOf="@id/clearPasswordTextButton"
|
app:layout_constraintEnd_toStartOf="@id/clearPasswordTextButton"
|
||||||
app:layout_constraintTop_toTopOf="@id/inputLayoutPassword"
|
app:layout_constraintTop_toTopOf="@id/inputLayoutPassword"
|
||||||
app:srcCompat="@drawable/mozac_ic_password_reveal" />
|
app:srcCompat="@drawable/mozac_ic_password_reveal" />
|
||||||
|
@ -218,9 +220,9 @@
|
||||||
android:id="@+id/clearPasswordTextButton"
|
android:id="@+id/clearPasswordTextButton"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="30dp"
|
android:layout_height="30dp"
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="@null"
|
||||||
android:contentDescription="@string/saved_logins_copy_password"
|
android:contentDescription="@string/saved_logins_copy_password"
|
||||||
app:tint="?android:colorAccent"
|
app:tint="@color/saved_login_clear_edit_text_tint"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/revealPasswordButton"
|
app:layout_constraintTop_toTopOf="@id/revealPasswordButton"
|
||||||
app:srcCompat="@drawable/ic_clear" />
|
app:srcCompat="@drawable/ic_clear" />
|
||||||
|
|
|
@ -124,7 +124,6 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="30dp"
|
android:layout_height="30dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:inputType="textPassword|text"
|
|
||||||
android:letterSpacing="0.01"
|
android:letterSpacing="0.01"
|
||||||
android:lineSpacingExtra="8sp"
|
android:lineSpacingExtra="8sp"
|
||||||
android:layout_marginTop="2dp"
|
android:layout_marginTop="2dp"
|
||||||
|
@ -142,7 +141,7 @@
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="30dp"
|
android:layout_height="30dp"
|
||||||
android:layout_marginBottom="2dp"
|
android:layout_marginBottom="2dp"
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="@null"
|
||||||
android:contentDescription="@string/saved_login_reveal_password"
|
android:contentDescription="@string/saved_login_reveal_password"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/passwordText"
|
app:layout_constraintBottom_toBottomOf="@id/passwordText"
|
||||||
app:layout_constraintEnd_toStartOf="@id/copyPassword"
|
app:layout_constraintEnd_toStartOf="@id/copyPassword"
|
||||||
|
@ -153,7 +152,7 @@
|
||||||
android:id="@+id/copyPassword"
|
android:id="@+id/copyPassword"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="30dp"
|
android:layout_height="30dp"
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="@null"
|
||||||
android:contentDescription="@string/saved_logins_copy_password"
|
android:contentDescription="@string/saved_logins_copy_password"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/revealPasswordButton"
|
app:layout_constraintBottom_toBottomOf="@id/revealPasswordButton"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
|
@ -154,6 +154,6 @@
|
||||||
<dimen name="saved_logins_sort_menu_dropdown_chevron_icon_margin_start">10dp</dimen>
|
<dimen name="saved_logins_sort_menu_dropdown_chevron_icon_margin_start">10dp</dimen>
|
||||||
<dimen name="saved_logins_sort_menu_dropdown_chevron_icon_size">12dp</dimen>
|
<dimen name="saved_logins_sort_menu_dropdown_chevron_icon_size">12dp</dimen>
|
||||||
<dimen name="saved_logins_detail_menu_vertical_padding">5dp</dimen>
|
<dimen name="saved_logins_detail_menu_vertical_padding">5dp</dimen>
|
||||||
|
<dimen name="saved_logins_end_icon_drawable_padding">16dp</dimen>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue