DroidFS/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt

220 lines
8.8 KiB
Kotlin
Raw Normal View History

2020-07-17 16:35:39 +02:00
package sushi.hardcore.droidfs.adapters
2021-11-11 15:05:33 +01:00
import android.graphics.drawable.Drawable
2020-07-17 16:35:39 +02:00
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
2020-07-17 16:35:39 +02:00
import android.widget.TextView
2021-11-11 15:05:33 +01:00
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
2021-11-11 15:05:33 +01:00
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.DrawableImageViewTarget
import com.bumptech.glide.request.transition.Transition
import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.GocryptfsVolume
2020-07-17 16:35:39 +02:00
import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.explorers.ExplorerElement
import sushi.hardcore.droidfs.util.PathUtils
2020-07-17 16:35:39 +02:00
import java.text.DateFormat
import java.util.*
class ExplorerElementAdapter(
2021-11-11 15:05:33 +01:00
val activity: AppCompatActivity,
val gocryptfsVolume: GocryptfsVolume?,
val onExplorerElementClick: (Int) -> Unit,
val onExplorerElementLongClick: (Int) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
2021-11-11 15:05:33 +01:00
val dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault())
var explorerElements = listOf<ExplorerElement>()
2020-07-17 16:35:39 +02:00
val selectedItems: MutableList<Int> = ArrayList()
override fun getItemCount(): Int {
return explorerElements.size
2020-07-17 16:35:39 +02:00
}
private fun toggleSelection(position: Int): Boolean {
if (!explorerElements[position].isParentFolder) {
if (selectedItems.contains(position)) {
selectedItems.remove(position)
} else {
selectedItems.add(position)
return true
2020-07-17 16:35:39 +02:00
}
}
return false
2020-07-17 16:35:39 +02:00
}
private fun onItemClick(position: Int): Boolean {
onExplorerElementClick(position)
2020-07-17 16:35:39 +02:00
if (selectedItems.isNotEmpty()) {
return toggleSelection(position)
2020-07-17 16:35:39 +02:00
}
return false
2020-07-17 16:35:39 +02:00
}
private fun onItemLongClick(position: Int): Boolean {
onExplorerElementLongClick(position)
return toggleSelection(position)
2020-07-17 16:35:39 +02:00
}
fun selectAll() {
for (i in explorerElements.indices) {
if (!selectedItems.contains(i) && !explorerElements[i].isParentFolder) {
2020-07-17 16:35:39 +02:00
selectedItems.add(i)
}
}
notifyDataSetChanged()
2020-07-17 16:35:39 +02:00
}
fun unSelectAll() {
selectedItems.clear()
notifyDataSetChanged()
2020-07-17 16:35:39 +02:00
}
2021-11-11 15:05:33 +01:00
open class ExplorerElementViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val textElementName by lazy {
itemView.findViewById<TextView>(R.id.text_element_name)
}
protected val textElementSize: TextView by lazy {
itemView.findViewById(R.id.text_element_size)
}
protected val textElementMtime: TextView by lazy {
itemView.findViewById(R.id.text_element_mtime)
}
protected val icon: ImageView by lazy {
itemView.findViewById(R.id.icon_element)
}
private val selectableContainer: LinearLayout by lazy {
itemView.findViewById(R.id.selectable_container)
}
protected fun setBackground(isSelected: Boolean) {
itemView.setBackgroundResource(if (isSelected) { R.color.itemSelected } else { 0 })
}
open fun bind(explorerElement: ExplorerElement, position: Int) {
textElementName.text = explorerElement.name
2021-11-11 15:05:33 +01:00
(bindingAdapter as ExplorerElementAdapter?)?.let { adapter ->
selectableContainer.setOnClickListener {
setBackground(adapter.onItemClick(position))
}
selectableContainer.setOnLongClickListener {
setBackground(adapter.onItemLongClick(position))
true
}
}
}
}
2021-11-11 15:05:33 +01:00
open class RegularElementViewHolder(itemView: View) : ExplorerElementViewHolder(itemView) {
open fun bind(explorerElement: ExplorerElement, position: Int, isSelected: Boolean) {
super.bind(explorerElement, position)
textElementSize.text = PathUtils.formatSize(explorerElement.size)
2021-11-11 15:05:33 +01:00
(bindingAdapter as ExplorerElementAdapter?)?.let {
textElementMtime.text = it.dateFormat.format(explorerElement.mTime)
}
setBackground(isSelected)
}
}
2021-11-11 15:05:33 +01:00
class FileViewHolder(itemView: View) : RegularElementViewHolder(itemView) {
var displayThumbnail = true
var target: DrawableImageViewTarget? = null
private fun loadThumbnail(fullPath: String) {
(bindingAdapter as ExplorerElementAdapter?)?.let { adapter ->
adapter.gocryptfsVolume?.let { volume ->
displayThumbnail = true
Thread {
2022-02-18 15:53:48 +01:00
volume.loadWholeFile(fullPath, maxSize = 50_000_000).first?.let {
2021-11-11 15:05:33 +01:00
if (displayThumbnail) {
adapter.activity.runOnUiThread {
if (displayThumbnail) {
target = Glide.with(adapter.activity).load(it).into(object : DrawableImageViewTarget(icon) {
override fun onResourceReady(
resource: Drawable,
transition: Transition<in Drawable>?
) {
super.onResourceReady(resource, transition)
target = null
}
})
}
}
}
}
}.start()
}
}
}
override fun bind(explorerElement: ExplorerElement, position: Int, isSelected: Boolean) {
super.bind(explorerElement, position, isSelected)
2021-11-11 15:05:33 +01:00
icon.setImageResource(
when {
ConstValues.isImage(explorerElement.name) -> {
loadThumbnail(explorerElement.fullPath)
R.drawable.icon_file_image
}
ConstValues.isVideo(explorerElement.name) -> {
loadThumbnail(explorerElement.fullPath)
R.drawable.icon_file_video
}
ConstValues.isText(explorerElement.name) -> R.drawable.icon_file_text
2022-02-18 16:50:08 +01:00
ConstValues.isPDF(explorerElement.name) -> R.drawable.icon_file_pdf
2021-11-11 15:05:33 +01:00
ConstValues.isAudio(explorerElement.name) -> R.drawable.icon_file_audio
else -> R.drawable.icon_file_unknown
}
)
}
}
2021-11-11 15:05:33 +01:00
class DirectoryViewHolder(itemView: View) : RegularElementViewHolder(itemView) {
override fun bind(explorerElement: ExplorerElement, position: Int, isSelected: Boolean) {
super.bind(explorerElement, position, isSelected)
icon.setImageResource(R.drawable.icon_folder)
}
}
2021-11-11 15:05:33 +01:00
class ParentFolderViewHolder(itemView: View): ExplorerElementViewHolder(itemView) {
override fun bind(explorerElement: ExplorerElement, position: Int) {
super.bind(explorerElement, position)
textElementSize.text = ""
textElementMtime.setText(R.string.parent_folder)
icon.setImageResource(R.drawable.icon_folder)
}
}
2021-11-11 15:05:33 +01:00
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
if (holder is FileViewHolder) {
//cancel pending thumbnail display
holder.displayThumbnail = false
holder.target?.let {
Glide.with(activity).clear(it)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
2021-11-11 15:05:33 +01:00
val view = activity.layoutInflater.inflate(R.layout.adapter_explorer_element, parent, false)
return when (viewType) {
2021-11-11 15:05:33 +01:00
ExplorerElement.REGULAR_FILE_TYPE -> FileViewHolder(view)
ExplorerElement.DIRECTORY_TYPE -> DirectoryViewHolder(view)
ExplorerElement.PARENT_FOLDER_TYPE -> ParentFolderViewHolder(view)
else -> throw IllegalArgumentException()
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val element = explorerElements[position]
if (element.isParentFolder) {
(holder as ParentFolderViewHolder).bind(element, position)
} else {
(holder as RegularElementViewHolder).bind(element, position, selectedItems.contains(position))
}
}
override fun getItemViewType(position: Int): Int {
return explorerElements[position].elementType.toInt()
2020-07-17 16:35:39 +02:00
}
}