/* * GenericRowAdapter.kt * Copyright (C) 2009-2021 Ultrasonic developers * * Distributed under terms of the GNU GPLv3 license. */ package org.moire.ultrasonic.fragment import android.annotation.SuppressLint 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 import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import org.moire.ultrasonic.R import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.domain.Identifiable import org.moire.ultrasonic.domain.MusicFolder import org.moire.ultrasonic.view.SelectMusicFolderView /* * An abstract Adapter, which can be extended to display a List of in a RecyclerView */ abstract class GenericRowAdapter( val onItemClick: (T) -> Unit, val onContextMenuClick: (MenuItem, T) -> Boolean, private val onMusicFolderUpdate: (String?) -> Unit ) : ListAdapter(GenericDiffCallback()) { protected abstract val layout: Int protected abstract val contextMenuLayout: Int var folderHeaderEnabled: Boolean = true var selectFolderHeader: SelectMusicFolderView? = null var musicFolders: List = listOf() var selectedFolder: String? = null /** * Sets the content and state of the music folder selector row */ fun setFolderList(changedFolders: List, selectedId: String?) { musicFolders = changedFolders selectedFolder = selectedId selectFolderHeader?.setData( selectedFolder, musicFolders ) notifyDataSetChanged() } open fun newViewHolder(view: View): RecyclerView.ViewHolder { return ViewHolder(view) } override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): RecyclerView.ViewHolder { if (viewType == TYPE_ITEM) { val row = LayoutInflater.from(parent.context) .inflate(layout, parent, false) 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!! } } abstract override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) override fun getItemCount(): Int { if (selectFolderHeader != null) return currentList.size + 1 else return currentList.size } override fun getItemViewType(position: Int): Int { return if (position == 0 && folderHeaderEnabled) TYPE_HEADER else TYPE_ITEM } 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 -> onContextMenuClick(menuItem, currentList[position]) } popup.show() return true } /** * Holds the view properties of an Item row */ class ViewHolder( 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 /** * Calculates the differences between data sets */ class GenericDiffCallback : DiffUtil.ItemCallback() { @SuppressLint("DiffUtilEquals") override fun areContentsTheSame(oldItem: T, newItem: T): Boolean { return oldItem == newItem } override fun areItemsTheSame(oldItem: T, newItem: T): Boolean { return oldItem.id == newItem.id } } } }