Cleanup extra content handling (#1536)
* BasicBottomSheet: remove unnecessary custom background
Fixes: 88c9a0d487
("app: refactor M3 themes and styles")
* FieldItemAdapter: fix typo ClipBoard -> Clipboard
* FieldItemAdapter: fix RV binding idempotency
* app: refactor FieldItemAdapter population logic
* DecryptActivityV2: wire in missing 'show password' toggle
This commit is contained in:
parent
223960d8d3
commit
67e70e5936
4 changed files with 38 additions and 41 deletions
|
@ -19,7 +19,7 @@ import dev.msfjarvis.aps.databinding.ItemFieldBinding
|
||||||
class FieldItemAdapter(
|
class FieldItemAdapter(
|
||||||
private var fieldItemList: List<FieldItem>,
|
private var fieldItemList: List<FieldItem>,
|
||||||
private val showPassword: Boolean,
|
private val showPassword: Boolean,
|
||||||
private val copyTextToClipBoard: (text: String?) -> Unit,
|
private val copyTextToClipboard: (text: String?) -> Unit,
|
||||||
) : RecyclerView.Adapter<FieldItemAdapter.FieldItemViewHolder>() {
|
) : RecyclerView.Adapter<FieldItemAdapter.FieldItemViewHolder>() {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FieldItemViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FieldItemViewHolder {
|
||||||
|
@ -28,7 +28,7 @@ class FieldItemAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: FieldItemViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: FieldItemViewHolder, position: Int) {
|
||||||
holder.bind(fieldItemList[position], showPassword, copyTextToClipBoard)
|
holder.bind(fieldItemList[position], showPassword, copyTextToClipboard)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
|
@ -50,15 +50,10 @@ class FieldItemAdapter(
|
||||||
notifyItemChanged(otpItemPosition)
|
notifyItemChanged(otpItemPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateItems(itemList: List<FieldItem>) {
|
|
||||||
fieldItemList = itemList
|
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
class FieldItemViewHolder(itemView: View, val binding: ItemFieldBinding) :
|
class FieldItemViewHolder(itemView: View, val binding: ItemFieldBinding) :
|
||||||
RecyclerView.ViewHolder(itemView) {
|
RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
fun bind(fieldItem: FieldItem, showPassword: Boolean, copyTextToClipBoard: (String?) -> Unit) {
|
fun bind(fieldItem: FieldItem, showPassword: Boolean, copyTextToClipboard: (String?) -> Unit) {
|
||||||
with(binding) {
|
with(binding) {
|
||||||
itemText.hint = fieldItem.key
|
itemText.hint = fieldItem.key
|
||||||
itemTextContainer.hint = fieldItem.key
|
itemTextContainer.hint = fieldItem.key
|
||||||
|
@ -70,19 +65,23 @@ class FieldItemAdapter(
|
||||||
endIconDrawable =
|
endIconDrawable =
|
||||||
ContextCompat.getDrawable(itemView.context, R.drawable.ic_content_copy)
|
ContextCompat.getDrawable(itemView.context, R.drawable.ic_content_copy)
|
||||||
endIconMode = TextInputLayout.END_ICON_CUSTOM
|
endIconMode = TextInputLayout.END_ICON_CUSTOM
|
||||||
setEndIconOnClickListener { copyTextToClipBoard(itemText.text.toString()) }
|
setEndIconOnClickListener { copyTextToClipboard(itemText.text.toString()) }
|
||||||
}
|
}
|
||||||
|
itemText.transformationMethod = null
|
||||||
}
|
}
|
||||||
FieldItem.ActionType.HIDE -> {
|
FieldItem.ActionType.HIDE -> {
|
||||||
itemTextContainer.apply {
|
itemTextContainer.apply {
|
||||||
endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE
|
endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE
|
||||||
setOnClickListener { copyTextToClipBoard(itemText.text.toString()) }
|
setOnClickListener { copyTextToClipboard(itemText.text.toString()) }
|
||||||
}
|
}
|
||||||
itemText.apply {
|
itemText.apply {
|
||||||
if (!showPassword) {
|
transformationMethod =
|
||||||
transformationMethod = PasswordTransformationMethod.getInstance()
|
if (!showPassword) {
|
||||||
}
|
PasswordTransformationMethod.getInstance()
|
||||||
setOnClickListener { copyTextToClipBoard(itemText.text.toString()) }
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
setOnClickListener { copyTextToClipboard(itemText.text.toString()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,9 +179,6 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound {
|
||||||
runCatching {
|
runCatching {
|
||||||
val showPassword = settings.getBoolean(PreferenceKeys.SHOW_PASSWORD, true)
|
val showPassword = settings.getBoolean(PreferenceKeys.SHOW_PASSWORD, true)
|
||||||
val entry = passwordEntryFactory.create(lifecycleScope, outputStream.toByteArray())
|
val entry = passwordEntryFactory.create(lifecycleScope, outputStream.toByteArray())
|
||||||
val items = arrayListOf<FieldItem>()
|
|
||||||
val adapter =
|
|
||||||
FieldItemAdapter(emptyList(), showPassword) { text -> copyTextToClipboard(text) }
|
|
||||||
|
|
||||||
if (settings.getBoolean(PreferenceKeys.COPY_ON_DECRYPT, false)) {
|
if (settings.getBoolean(PreferenceKeys.COPY_ON_DECRYPT, false)) {
|
||||||
copyPasswordToClipboard(entry.password)
|
copyPasswordToClipboard(entry.password)
|
||||||
|
@ -190,17 +187,13 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound {
|
||||||
passwordEntry = entry
|
passwordEntry = entry
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
|
|
||||||
|
val items = arrayListOf<FieldItem>()
|
||||||
if (!entry.password.isNullOrBlank()) {
|
if (!entry.password.isNullOrBlank()) {
|
||||||
items.add(FieldItem.createPasswordField(entry.password!!))
|
items.add(FieldItem.createPasswordField(entry.password!!))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.hasTotp()) {
|
if (entry.hasTotp()) {
|
||||||
launch {
|
items.add(FieldItem.createOtpField(entry.totp.value))
|
||||||
items.add(FieldItem.createOtpField(entry.totp.value))
|
|
||||||
entry.totp.collect { code ->
|
|
||||||
withContext(Dispatchers.Main) { adapter.updateOTPCode(code) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entry.username.isNullOrBlank()) {
|
if (!entry.username.isNullOrBlank()) {
|
||||||
|
@ -211,8 +204,17 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound {
|
||||||
items.add(FieldItem(key, value, FieldItem.ActionType.COPY))
|
items.add(FieldItem(key, value, FieldItem.ActionType.COPY))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val adapter =
|
||||||
|
FieldItemAdapter(items, showPassword) { text -> copyTextToClipboard(text) }
|
||||||
binding.recyclerView.adapter = adapter
|
binding.recyclerView.adapter = adapter
|
||||||
adapter.updateItems(items)
|
|
||||||
|
if (entry.hasTotp()) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
entry.totp.collect { code ->
|
||||||
|
withContext(Dispatchers.Main) { adapter.updateOTPCode(code) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.onFailure { e -> logcat(ERROR) { e.asLog() } }
|
.onFailure { e -> logcat(ERROR) { e.asLog() } }
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import dev.msfjarvis.aps.injection.password.PasswordEntryFactory
|
||||||
import dev.msfjarvis.aps.ui.adapters.FieldItemAdapter
|
import dev.msfjarvis.aps.ui.adapters.FieldItemAdapter
|
||||||
import dev.msfjarvis.aps.util.extensions.unsafeLazy
|
import dev.msfjarvis.aps.util.extensions.unsafeLazy
|
||||||
import dev.msfjarvis.aps.util.extensions.viewBinding
|
import dev.msfjarvis.aps.util.extensions.viewBinding
|
||||||
|
import dev.msfjarvis.aps.util.settings.PreferenceKeys
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -142,23 +143,18 @@ class DecryptActivityV2 : BasePgpActivity() {
|
||||||
}
|
}
|
||||||
startAutoDismissTimer()
|
startAutoDismissTimer()
|
||||||
|
|
||||||
|
val showPassword = settings.getBoolean(PreferenceKeys.SHOW_PASSWORD, true)
|
||||||
val entry = passwordEntryFactory.create(lifecycleScope, result.toByteArray())
|
val entry = passwordEntryFactory.create(lifecycleScope, result.toByteArray())
|
||||||
passwordEntry = entry
|
passwordEntry = entry
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
|
|
||||||
val items = arrayListOf<FieldItem>()
|
val items = arrayListOf<FieldItem>()
|
||||||
val adapter = FieldItemAdapter(emptyList(), true) { text -> copyTextToClipboard(text) }
|
|
||||||
if (!entry.password.isNullOrBlank()) {
|
if (!entry.password.isNullOrBlank()) {
|
||||||
items.add(FieldItem.createPasswordField(entry.password!!))
|
items.add(FieldItem.createPasswordField(entry.password!!))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.hasTotp()) {
|
if (entry.hasTotp()) {
|
||||||
lifecycleScope.launch {
|
items.add(FieldItem.createOtpField(entry.totp.value))
|
||||||
items.add(FieldItem.createOtpField(entry.totp.value))
|
|
||||||
entry.totp.collect { code ->
|
|
||||||
withContext(Dispatchers.Main) { adapter.updateOTPCode(code) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entry.username.isNullOrBlank()) {
|
if (!entry.username.isNullOrBlank()) {
|
||||||
|
@ -169,8 +165,16 @@ class DecryptActivityV2 : BasePgpActivity() {
|
||||||
items.add(FieldItem(key, value, FieldItem.ActionType.COPY))
|
items.add(FieldItem(key, value, FieldItem.ActionType.COPY))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val adapter = FieldItemAdapter(items, showPassword) { text -> copyTextToClipboard(text) }
|
||||||
binding.recyclerView.adapter = adapter
|
binding.recyclerView.adapter = adapter
|
||||||
adapter.updateItems(items)
|
|
||||||
|
if (entry.hasTotp()) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
entry.totp.collect { code ->
|
||||||
|
withContext(Dispatchers.Main) { adapter.updateOTPCode(code) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
package dev.msfjarvis.aps.ui.dialogs
|
package dev.msfjarvis.aps.ui.dialogs
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.GradientDrawable
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -20,13 +19,11 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import dev.msfjarvis.aps.R
|
import dev.msfjarvis.aps.R
|
||||||
import dev.msfjarvis.aps.databinding.BasicBottomSheetBinding
|
import dev.msfjarvis.aps.databinding.BasicBottomSheetBinding
|
||||||
import dev.msfjarvis.aps.ui.dialogs.BasicBottomSheet.Builder
|
|
||||||
import dev.msfjarvis.aps.util.extensions.resolveAttribute
|
|
||||||
import dev.msfjarvis.aps.util.extensions.viewBinding
|
import dev.msfjarvis.aps.util.extensions.viewBinding
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [BottomSheetDialogFragment] that exposes a simple [androidx.appcompat.app.AlertDialog] like API
|
* [BottomSheetDialogFragment] that exposes a simple [androidx.appcompat.app.AlertDialog] like API
|
||||||
* through [Builder] to create a similar UI, just at the bottom of the screen.
|
* through [BasicBottomSheet.Builder] to create a similar UI, just at the bottom of the screen.
|
||||||
*/
|
*/
|
||||||
class BasicBottomSheet
|
class BasicBottomSheet
|
||||||
private constructor(
|
private constructor(
|
||||||
|
@ -100,11 +97,6 @@ private constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
val gradientDrawable =
|
|
||||||
GradientDrawable().apply {
|
|
||||||
setColor(requireContext().resolveAttribute(android.R.attr.windowBackground))
|
|
||||||
}
|
|
||||||
view.background = gradientDrawable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dismiss() {
|
override fun dismiss() {
|
||||||
|
|
Loading…
Reference in a new issue