Encapsulate adapters in AnimatedItemsAdapter

This commit is contained in:
J-Jamet
2020-08-18 16:33:48 +02:00
parent d1a2e50b8d
commit a382297edf
5 changed files with 98 additions and 131 deletions

View File

@@ -0,0 +1,70 @@
package com.kunzisoft.keepass.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.kunzisoft.keepass.view.collapse
abstract class AnimatedItemsAdapter<Item, T: RecyclerView.ViewHolder>(val context: Context)
: RecyclerView.Adapter<T>() {
protected val inflater: LayoutInflater = LayoutInflater.from(context)
var itemsList: MutableList<Item> = ArrayList()
private set
var onDeleteButtonClickListener: ((item: Item)->Unit)? = null
private var mItemToRemove: Item? = null
var onListSizeChangedListener: ((previousSize: Int, newSize: Int)->Unit)? = null
override fun getItemCount(): Int {
return itemsList.size
}
fun assignItems(items: List<Item>) {
val previousSize = itemsList.size
itemsList.apply {
clear()
addAll(items)
}
notifyDataSetChanged()
onListSizeChangedListener?.invoke(previousSize, itemsList.size)
}
fun onBindDeleteButton(holder: T, deleteButton: View, item: Item, position: Int) {
deleteButton.apply {
visibility = View.VISIBLE
if (mItemToRemove == item) {
holder.itemView.collapse(true) {
deleteItem(item)
}
setOnClickListener(null)
} else {
setOnClickListener {
onDeleteButtonClickListener?.invoke(item)
mItemToRemove = item
notifyItemChanged(position)
}
}
}
}
private fun deleteItem(item: Item) {
val previousSize = itemsList.size
val position = itemsList.indexOf(item)
if (position >= 0) {
itemsList.removeAt(position)
notifyItemRemoved(position)
mItemToRemove = null
for (i in 0 until itemsList.size) {
notifyItemChanged(i)
}
}
onListSizeChangedListener?.invoke(previousSize, itemsList.size)
}
fun clear() {
itemsList.clear()
}
}

View File

@@ -21,7 +21,6 @@ package com.kunzisoft.keepass.adapters
import android.content.Context
import android.text.format.Formatter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ProgressBar
@@ -32,18 +31,11 @@ import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
import com.kunzisoft.keepass.model.AttachmentState
import com.kunzisoft.keepass.model.EntryAttachment
import com.kunzisoft.keepass.view.collapse
class EntryAttachmentsAdapter(val context: Context, private val editable: Boolean)
: RecyclerView.Adapter<EntryAttachmentsAdapter.EntryBinariesViewHolder>() {
class EntryAttachmentsItemsAdapter(context: Context, private val editable: Boolean)
: AnimatedItemsAdapter<EntryAttachment, EntryAttachmentsItemsAdapter.EntryBinariesViewHolder>(context) {
private val inflater: LayoutInflater = LayoutInflater.from(context)
var entryAttachmentsList: MutableList<EntryAttachment> = ArrayList()
var onItemClickListener: ((item: EntryAttachment)->Unit)? = null
var onDeleteButtonClickListener: ((item: EntryAttachment)->Unit)? = null
var onListSizeChangedListener: ((previousSize: Int, newSize: Int)->Unit)? = null
private var mAttachmentToRemove: EntryAttachment? = null
private val mDatabase = Database.getInstance()
@@ -52,7 +44,7 @@ class EntryAttachmentsAdapter(val context: Context, private val editable: Boolea
}
override fun onBindViewHolder(holder: EntryBinariesViewHolder, position: Int) {
val entryAttachment = entryAttachmentsList[position]
val entryAttachment = itemsList[position]
holder.itemView.visibility = View.VISIBLE
holder.binaryFileTitle.text = entryAttachment.name
@@ -72,18 +64,7 @@ class EntryAttachmentsAdapter(val context: Context, private val editable: Boolea
holder.binaryFileProgressContainer.visibility = View.GONE
holder.binaryFileDeleteButton.apply {
visibility = View.VISIBLE
if (mAttachmentToRemove == entryAttachment) {
holder.itemView.collapse(true) {
deleteAttachment(entryAttachment)
}
setOnClickListener(null)
} else {
setOnClickListener {
onDeleteButtonClickListener?.invoke(entryAttachment)
mAttachmentToRemove = entryAttachment
notifyItemChanged(position)
}
}
onBindDeleteButton(holder, this, entryAttachment, position)
}
} else {
holder.binaryFileProgressContainer.visibility = View.VISIBLE
@@ -101,46 +82,14 @@ class EntryAttachmentsAdapter(val context: Context, private val editable: Boolea
}
}
override fun getItemCount(): Int {
return entryAttachmentsList.size
}
fun assignAttachments(attachments: List<EntryAttachment>) {
val previousSize = entryAttachmentsList.size
entryAttachmentsList.apply {
clear()
addAll(attachments)
}
notifyDataSetChanged()
onListSizeChangedListener?.invoke(previousSize, entryAttachmentsList.size)
}
private fun deleteAttachment(attachment: EntryAttachment) {
val previousSize = entryAttachmentsList.size
val position = entryAttachmentsList.indexOf(attachment)
if (position >= 0) {
entryAttachmentsList.removeAt(position)
notifyItemRemoved(position)
mAttachmentToRemove = null
for (i in 0 until entryAttachmentsList.size) {
notifyItemChanged(i)
}
}
onListSizeChangedListener?.invoke(previousSize, entryAttachmentsList.size)
}
fun updateProgress(entryAttachment: EntryAttachment) {
val indexEntryAttachment = entryAttachmentsList.indexOfLast { current -> current.name == entryAttachment.name }
val indexEntryAttachment = itemsList.indexOfLast { current -> current.name == entryAttachment.name }
if (indexEntryAttachment != -1) {
entryAttachmentsList[indexEntryAttachment] = entryAttachment
itemsList[indexEntryAttachment] = entryAttachment
notifyItemChanged(indexEntryAttachment)
}
}
fun clear() {
entryAttachmentsList.clear()
}
inner class EntryBinariesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var binaryFileTitle: TextView = itemView.findViewById(R.id.item_attachment_title)

View File

@@ -20,7 +20,6 @@
package com.kunzisoft.keepass.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
@@ -32,16 +31,9 @@ import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.model.Field
import com.kunzisoft.keepass.view.applyFontVisibility
import com.kunzisoft.keepass.view.collapse
class EntryExtraFieldsAdapter(val context: Context)
: RecyclerView.Adapter<EntryExtraFieldsAdapter.EntryExtraFieldViewHolder>() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
var extraFieldsList: MutableList<Field> = ArrayList()
private set
var onDeleteButtonClickListener: ((item: Field)->Unit)? = null
var onListSizeChangedListener: ((previousSize: Int, newSize: Int)->Unit)? = null
class EntryExtraFieldsItemsAdapter(context: Context)
: AnimatedItemsAdapter<Field, EntryExtraFieldsItemsAdapter.EntryExtraFieldViewHolder>(context) {
var applyFontVisibility = false
set(value) {
@@ -49,7 +41,6 @@ class EntryExtraFieldsAdapter(val context: Context)
notifyDataSetChanged()
}
private var mValueViewInputType: Int = 0
private var mItemToRemove: Field? = null
private var mLastFocused: Field? = null
private var mLastFocusedTimestamp: Long = 0
@@ -62,7 +53,7 @@ class EntryExtraFieldsAdapter(val context: Context)
}
override fun onBindViewHolder(holder: EntryExtraFieldViewHolder, position: Int) {
val extraField = extraFieldsList[position]
val extraField = itemsList[position]
holder.itemView.visibility = View.VISIBLE
if (extraField.protectedValue.isProtected) {
@@ -94,18 +85,7 @@ class EntryExtraFieldsAdapter(val context: Context)
applyFontVisibility()
}
holder.extraFieldDeleteButton.apply {
if (mItemToRemove == extraField) {
holder.itemView.collapse(true) {
deleteExtraField(extraField)
}
setOnClickListener(null)
} else {
setOnClickListener {
onDeleteButtonClickListener?.invoke(extraField)
mItemToRemove = extraField
notifyItemChanged(position)
}
}
onBindDeleteButton(holder, this, extraField, position)
}
}
@@ -130,52 +110,20 @@ class EntryExtraFieldsAdapter(val context: Context)
}
}
override fun getItemCount(): Int {
return extraFieldsList.size
}
fun assignExtraFields(fields: List<Field>) {
val previousSize = extraFieldsList.size
extraFieldsList.apply {
clear()
addAll(fields)
}
notifyDataSetChanged()
onListSizeChangedListener?.invoke(previousSize, extraFieldsList.size)
}
fun putExtraField(field: Field) {
val previousSize = extraFieldsList.size
if (extraFieldsList.contains(field)) {
val index = extraFieldsList.indexOf(field)
extraFieldsList.removeAt(index)
extraFieldsList.add(index, field)
val previousSize = itemsList.size
if (itemsList.contains(field)) {
val index = itemsList.indexOf(field)
itemsList.removeAt(index)
itemsList.add(index, field)
focusField(field)
notifyItemChanged(index)
} else {
extraFieldsList.add(field)
itemsList.add(field)
focusField(field)
notifyItemInserted(extraFieldsList.indexOf(field))
notifyItemInserted(itemsList.indexOf(field))
}
onListSizeChangedListener?.invoke(previousSize, extraFieldsList.size)
}
private fun deleteExtraField(field: Field) {
val previousSize = extraFieldsList.size
val position = extraFieldsList.indexOf(field)
if (position >= 0) {
extraFieldsList.removeAt(position)
notifyItemRemoved(position)
mItemToRemove = null
for (i in 0 until extraFieldsList.size) {
notifyItemChanged(i)
}
}
onListSizeChangedListener?.invoke(previousSize, extraFieldsList.size)
}
fun clear() {
extraFieldsList.clear()
onListSizeChangedListener?.invoke(previousSize, itemsList.size)
}
inner class EntryExtraFieldViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

View File

@@ -33,7 +33,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SimpleItemAnimator
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.adapters.EntryAttachmentsAdapter
import com.kunzisoft.keepass.adapters.EntryAttachmentsItemsAdapter
import com.kunzisoft.keepass.adapters.EntryHistoryAdapter
import com.kunzisoft.keepass.database.element.DateInstant
import com.kunzisoft.keepass.database.element.Entry
@@ -84,7 +84,7 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
private val attachmentsContainerView: View
private val attachmentsListView: RecyclerView
private val attachmentsAdapter = EntryAttachmentsAdapter(context, false)
private val attachmentsAdapter = EntryAttachmentsItemsAdapter(context, false)
private val historyContainerView: View
private val historyListView: RecyclerView
@@ -367,7 +367,7 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
fun assignAttachments(attachments: ArrayList<EntryAttachment>,
onAttachmentClicked: (attachment: EntryAttachment)->Unit) {
showAttachments(attachments.isNotEmpty())
attachmentsAdapter.assignAttachments(attachments)
attachmentsAdapter.assignItems(attachments)
attachmentsAdapter.onItemClickListener = { item ->
onAttachmentClicked.invoke(item)
}

View File

@@ -31,8 +31,8 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SimpleItemAnimator
import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.adapters.EntryAttachmentsAdapter
import com.kunzisoft.keepass.adapters.EntryExtraFieldsAdapter
import com.kunzisoft.keepass.adapters.EntryAttachmentsItemsAdapter
import com.kunzisoft.keepass.adapters.EntryExtraFieldsItemsAdapter
import com.kunzisoft.keepass.database.element.DateInstant
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.icons.IconDrawableFactory
@@ -66,8 +66,8 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
private val attachmentsContainerView: View
private val attachmentsListView: RecyclerView
private val extraFieldsAdapter = EntryExtraFieldsAdapter(context)
private val attachmentsAdapter = EntryAttachmentsAdapter(context, true)
private val extraFieldsAdapter = EntryExtraFieldsItemsAdapter(context)
private val attachmentsAdapter = EntryAttachmentsItemsAdapter(context, true)
private var iconColor: Int = 0
private var expiresInstant: DateInstant = DateInstant(Instant.now().plus(Duration.standardDays(30)).toDate())
@@ -242,7 +242,7 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
*/
fun getExtraField(): MutableList<Field> {
return extraFieldsAdapter.extraFieldsList
return extraFieldsAdapter.itemsList
}
/**
@@ -250,7 +250,7 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
*/
fun assignExtraFields(fields: List<Field>) {
extraFieldsContainerView.visibility = if (fields.isEmpty()) View.GONE else View.VISIBLE
extraFieldsAdapter.assignExtraFields(fields)
extraFieldsAdapter.assignItems(fields)
}
/**
@@ -270,7 +270,7 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
fun assignAttachments(attachments: ArrayList<EntryAttachment>,
onDeleteItem: (attachment: EntryAttachment)->Unit) {
attachmentsContainerView.visibility = if (attachments.isEmpty()) View.GONE else View.VISIBLE
attachmentsAdapter.assignAttachments(attachments)
attachmentsAdapter.assignItems(attachments)
attachmentsAdapter.onDeleteButtonClickListener = { item ->
onDeleteItem.invoke(item)
}