2021-05-12 13:28:33 +02:00
|
|
|
/*
|
|
|
|
* GenericRowAdapter.kt
|
|
|
|
* Copyright (C) 2009-2021 Ultrasonic developers
|
|
|
|
*
|
|
|
|
* Distributed under terms of the GNU GPLv3 license.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package org.moire.ultrasonic.fragment
|
|
|
|
|
2021-10-14 19:25:25 +02:00
|
|
|
import android.annotation.SuppressLint
|
2021-05-12 13:28:33 +02:00
|
|
|
import android.view.LayoutInflater
|
|
|
|
import android.view.MenuInflater
|
|
|
|
import android.view.MenuItem
|
|
|
|
import android.view.View
|
|
|
|
import android.view.ViewGroup
|
|
|
|
import android.widget.ImageView
|
|
|
|
import android.widget.PopupMenu
|
|
|
|
import android.widget.RelativeLayout
|
|
|
|
import android.widget.TextView
|
2021-06-20 00:29:20 +02:00
|
|
|
import androidx.recyclerview.widget.DiffUtil
|
2021-06-20 08:24:14 +02:00
|
|
|
import androidx.recyclerview.widget.ListAdapter
|
2021-05-12 13:28:33 +02:00
|
|
|
import androidx.recyclerview.widget.RecyclerView
|
|
|
|
import org.moire.ultrasonic.R
|
|
|
|
import org.moire.ultrasonic.data.ActiveServerProvider
|
2021-10-14 19:25:25 +02:00
|
|
|
import org.moire.ultrasonic.domain.Identifiable
|
2021-05-17 17:14:04 +02:00
|
|
|
import org.moire.ultrasonic.domain.MusicFolder
|
2021-05-12 13:28:33 +02:00
|
|
|
import org.moire.ultrasonic.view.SelectMusicFolderView
|
|
|
|
|
|
|
|
/*
|
|
|
|
* An abstract Adapter, which can be extended to display a List of <T> in a RecyclerView
|
|
|
|
*/
|
2021-10-14 19:25:25 +02:00
|
|
|
abstract class GenericRowAdapter<T : Identifiable>(
|
2021-05-12 13:28:33 +02:00
|
|
|
val onItemClick: (T) -> Unit,
|
|
|
|
val onContextMenuClick: (MenuItem, T) -> Boolean,
|
2021-05-17 17:14:04 +02:00
|
|
|
private val onMusicFolderUpdate: (String?) -> Unit
|
2021-06-20 08:24:14 +02:00
|
|
|
) : ListAdapter<T, RecyclerView.ViewHolder>(GenericDiffCallback()) {
|
|
|
|
|
2021-05-12 13:28:33 +02:00
|
|
|
protected abstract val layout: Int
|
|
|
|
protected abstract val contextMenuLayout: Int
|
|
|
|
|
2021-05-17 17:14:04 +02:00
|
|
|
var folderHeaderEnabled: Boolean = true
|
|
|
|
var selectFolderHeader: SelectMusicFolderView? = null
|
|
|
|
var musicFolders: List<MusicFolder> = listOf()
|
|
|
|
var selectedFolder: String? = null
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the content and state of the music folder selector row
|
|
|
|
*/
|
|
|
|
fun setFolderList(changedFolders: List<MusicFolder>, selectedId: String?) {
|
|
|
|
musicFolders = changedFolders
|
|
|
|
selectedFolder = selectedId
|
|
|
|
|
|
|
|
selectFolderHeader?.setData(
|
|
|
|
selectedFolder,
|
|
|
|
musicFolders
|
|
|
|
)
|
|
|
|
|
|
|
|
notifyDataSetChanged()
|
|
|
|
}
|
|
|
|
|
|
|
|
open fun newViewHolder(view: View): RecyclerView.ViewHolder {
|
|
|
|
return ViewHolder(view)
|
|
|
|
}
|
|
|
|
|
2021-05-12 13:28:33 +02:00
|
|
|
override fun onCreateViewHolder(
|
|
|
|
parent: ViewGroup,
|
|
|
|
viewType: Int
|
|
|
|
): RecyclerView.ViewHolder {
|
|
|
|
if (viewType == TYPE_ITEM) {
|
|
|
|
val row = LayoutInflater.from(parent.context)
|
|
|
|
.inflate(layout, parent, false)
|
2021-05-17 17:14:04 +02:00
|
|
|
return newViewHolder(row)
|
|
|
|
} else {
|
|
|
|
val row = LayoutInflater.from(parent.context)
|
|
|
|
.inflate(
|
|
|
|
R.layout.select_folder_header, parent, false
|
|
|
|
)
|
|
|
|
selectFolderHeader = SelectMusicFolderView(parent.context, row, onMusicFolderUpdate)
|
|
|
|
|
|
|
|
if (musicFolders.isNotEmpty()) {
|
|
|
|
selectFolderHeader?.setData(
|
|
|
|
selectedFolder,
|
|
|
|
musicFolders
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return selectFolderHeader!!
|
2021-05-12 13:28:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
|
|
|
|
|
|
|
|
override fun getItemCount(): Int {
|
|
|
|
if (selectFolderHeader != null)
|
2021-10-14 19:25:25 +02:00
|
|
|
return currentList.size + 1
|
2021-05-12 13:28:33 +02:00
|
|
|
else
|
2021-10-14 19:25:25 +02:00
|
|
|
return currentList.size
|
2021-05-12 13:28:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun getItemViewType(position: Int): Int {
|
2021-05-17 17:14:04 +02:00
|
|
|
return if (position == 0 && folderHeaderEnabled) TYPE_HEADER else TYPE_ITEM
|
2021-05-12 13:28:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
internal fun createPopupMenu(view: View, position: Int): Boolean {
|
|
|
|
val popup = PopupMenu(view.context, view)
|
|
|
|
val inflater: MenuInflater = popup.menuInflater
|
|
|
|
inflater.inflate(contextMenuLayout, popup.menu)
|
|
|
|
|
|
|
|
val downloadMenuItem = popup.menu.findItem(R.id.menu_download)
|
|
|
|
downloadMenuItem?.isVisible = !ActiveServerProvider.isOffline()
|
|
|
|
|
|
|
|
popup.setOnMenuItemClickListener { menuItem ->
|
2021-10-14 19:25:25 +02:00
|
|
|
onContextMenuClick(menuItem, currentList[position])
|
2021-05-12 13:28:33 +02:00
|
|
|
}
|
|
|
|
popup.show()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Holds the view properties of an Item row
|
|
|
|
*/
|
2021-05-17 17:14:04 +02:00
|
|
|
class ViewHolder(
|
2021-05-12 13:28:33 +02:00
|
|
|
itemView: View
|
|
|
|
) : RecyclerView.ViewHolder(itemView) {
|
|
|
|
var section: TextView = itemView.findViewById(R.id.row_section)
|
|
|
|
var textView: TextView = itemView.findViewById(R.id.row_artist_name)
|
|
|
|
var layout: RelativeLayout = itemView.findViewById(R.id.row_artist_layout)
|
|
|
|
var coverArt: ImageView = itemView.findViewById(R.id.artist_coverart)
|
|
|
|
var coverArtId: String? = null
|
|
|
|
}
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
internal const val TYPE_HEADER = 0
|
|
|
|
internal const val TYPE_ITEM = 1
|
2021-06-20 08:24:14 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculates the differences between data sets
|
|
|
|
*/
|
2021-10-14 19:25:25 +02:00
|
|
|
class GenericDiffCallback<T : Identifiable> : DiffUtil.ItemCallback<T>() {
|
|
|
|
@SuppressLint("DiffUtilEquals")
|
2021-06-20 08:24:14 +02:00
|
|
|
override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
|
|
|
|
return oldItem == newItem
|
|
|
|
}
|
|
|
|
override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
|
|
|
|
return oldItem.id == newItem.id
|
|
|
|
}
|
|
|
|
}
|
2021-05-12 13:28:33 +02:00
|
|
|
}
|
|
|
|
}
|