Refactor packages

This commit is contained in:
h4h13 2019-04-20 10:59:45 +05:30
parent c386e1fe93
commit 39b0b4c931
188 changed files with 440 additions and 835 deletions

View file

@ -0,0 +1,75 @@
package code.name.monkey.retromusic.adapter
import android.app.Activity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.adapter.CollageSongAdapter.CollageSongViewHolder
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import java.util.*
/**
* @author Hemanth S (h4h13).
*/
class CollageSongAdapter(private val activity: Activity, private val dataSet: ArrayList<Song>) : RecyclerView.Adapter<CollageSongViewHolder>() {
override fun onBindViewHolder(holder: CollageSongViewHolder, position: Int) {
holder.bindSongs()
if (dataSet.size > 8) {
for (i in 0 until dataSet.subList(0, 8).size) {
GlideApp.with(activity)
.asBitmapPalette()
.load(RetroGlideExtension.getSongModel(dataSet[i]))
.transition(RetroGlideExtension.getDefaultTransition())
.songOptions(dataSet[i])
.into(object : RetroMusicColoredTarget(holder.itemView.findViewById(holder.ids[i]) as ImageView) {
override fun onColorReady(color: Int) {
}
})
}
}
}
override fun getItemCount(): Int {
return 1
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CollageSongViewHolder {
return CollageSongViewHolder(LayoutInflater.from(activity).inflate(R.layout.item_collage, parent, false))
}
inner class CollageSongViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
val ids = arrayListOf(R.id.image_2, R.id.image_3, R.id.image_4, R.id.image_5, R.id.image_6, R.id.image_7, R.id.image_8, R.id.image_9)
private var textView: TextView = itemView.findViewById(R.id.image_1)
fun bindSongs() {
for (i in ids) {
val imageView = itemView.findViewById<ImageView>(i)
imageView.setOnClickListener {
textView.setOnClickListener { MusicPlayerRemote.openQueue(dataSet, 0, true) }
}
}
val context = itemView.context
val color = ThemeStore.accentColor(context);
textView.setOnClickListener { MusicPlayerRemote.openQueue(dataSet, 0, true) }
textView.setBackgroundColor(color);
textView.setTextColor(MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(color)))
}
}
}

View file

@ -0,0 +1,48 @@
package code.name.monkey.retromusic.adapter
import android.app.Activity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.model.Contributor
import code.name.monkey.retromusic.util.RetroUtil.openUrl
import code.name.monkey.retromusic.views.CircularImageView
class ContributorAdapter(private var contributors: List<Contributor>) : RecyclerView.Adapter<ContributorAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_contributor, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val contributor = contributors[position]
holder.bindData(contributor)
holder.itemView.setOnClickListener {
openUrl(it!!.context as Activity, contributors[position].link)
}
}
override fun getItemCount(): Int {
return contributors.size
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val title: TextView = itemView.findViewById(R.id.title)
val text: TextView = itemView.findViewById(R.id.text)
val image: CircularImageView = itemView.findViewById(R.id.image)
internal fun bindData(contributor: Contributor) {
title.text = contributor.name
text.text = contributor.summary
GlideApp.with(image.context)
.load(contributor.profileImage)
.error(R.drawable.ic_person_flat)
.placeholder(R.drawable.ic_person_flat)
.into(image)
}
}
}

View file

@ -0,0 +1,73 @@
package code.name.monkey.retromusic.adapter
import android.app.Activity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import java.util.ArrayList
import java.util.Locale
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.util.NavigationUtil
/**
* @author Hemanth S (h4h13).
*/
class GenreAdapter(private val mActivity: Activity, dataSet: ArrayList<Genre>, private val mItemLayoutRes: Int) : RecyclerView.Adapter<GenreAdapter.ViewHolder>() {
var dataSet = ArrayList<Genre>()
private set
init {
this.dataSet = dataSet
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GenreAdapter.ViewHolder {
return ViewHolder(LayoutInflater.from(mActivity).inflate(mItemLayoutRes, parent, false))
}
override fun onBindViewHolder(holder: GenreAdapter.ViewHolder, position: Int) {
val genre = dataSet[position]
if (holder.title != null) {
holder.title!!.text = genre.name
}
if (holder.text != null) {
holder.text!!.text = String.format(Locale.getDefault(), "%d %s", genre.songCount, if (genre.songCount > 1)
mActivity.getString(R.string.songs)
else
mActivity.getString(R.string.song))
}
if (holder.separator != null) {
holder.separator!!.visibility = View.GONE
}
}
override fun getItemCount(): Int {
return dataSet.size
}
fun swapDataSet(list: ArrayList<Genre>) {
dataSet = list
notifyDataSetChanged()
}
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
init {
if (menu != null) {
menu!!.visibility = View.GONE
}
assert(imageContainer != null)
imageContainer!!.visibility = View.GONE
}
override fun onClick(v: View?) {
super.onClick(v)
val genre = dataSet[adapterPosition]
NavigationUtil.goToGenre(mActivity, genre)
}
}
}

View file

@ -0,0 +1,210 @@
package code.name.monkey.retromusic.adapter
import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.IntDef
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.adapter.album.AlbumFullWidthAdapter
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.views.IconImageView
import code.name.monkey.retromusic.views.MetalRecyclerViewPager
import com.google.android.material.floatingactionbutton.FloatingActionButton
class HomeAdapter(private val activity: AppCompatActivity, private var homes: List<Home>, private val displayMetrics: DisplayMetrics) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun getItemViewType(position: Int): Int {
return homes[position].homeSection
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layout = LayoutInflater.from(activity).inflate(R.layout.section_recycler_view, parent, false)
return when (viewType) {
RECENT_ARTISTS, TOP_ARTISTS -> ArtistViewHolder(layout)
GENRES -> GenreViewHolder(layout)
PLAYLISTS -> PlaylistViewHolder(layout)
else -> {
AlbumViewHolder(LayoutInflater.from(activity).inflate(R.layout.metal_section_recycler_view, parent, false))
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val home = homes[position]
when (getItemViewType(position)) {
RECENT_ALBUMS, TOP_ALBUMS -> {
val viewHolder = holder as AlbumViewHolder
viewHolder.bindView(home)
}
RECENT_ARTISTS, TOP_ARTISTS -> {
val viewHolder = holder as ArtistViewHolder
viewHolder.bindView(home)
}
GENRES -> {
val viewHolder = holder as GenreViewHolder
viewHolder.bindView(home)
}
PLAYLISTS -> {
val viewHolder = holder as PlaylistViewHolder
viewHolder.bindView(home)
}
}
}
override fun getItemCount(): Int {
return homes.size
}
fun swapData(finalList: List<Home>) {
homes = finalList
notifyDataSetChanged()
}
companion object {
@IntDef(RECENT_ALBUMS, TOP_ALBUMS, RECENT_ARTISTS, TOP_ARTISTS, GENRES, PLAYLISTS)
@Retention(AnnotationRetention.SOURCE)
annotation class HomeSection
const val RECENT_ALBUMS = 0
const val TOP_ALBUMS = 1
const val RECENT_ARTISTS = 2
const val TOP_ARTISTS = 3
const val GENRES = 4
const val PLAYLISTS = 5
}
private inner class SuggestionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val icon: IconImageView = itemView.findViewById(R.id.sectionIcon)
private val ids: ArrayList<Int> = arrayListOf(R.id.image_1, R.id.image_2, R.id.image_3, R.id.image_4, R.id.image_5, R.id.image_6, R.id.image_7)
private var textView: TextView = itemView.findViewById(R.id.text)
private var playSuggestion: FloatingActionButton = itemView.findViewById(R.id.playSuggestions)
private var title: TextView = itemView.findViewById(R.id.sectionTitle)
fun bindView(home: Home) {
val dataSet = home.arrayList as ArrayList<Song>
for (id in 0 until ids.size) {
val imageView = itemView.findViewById<ImageView>(ids[id])
imageView.setOnClickListener {
MusicPlayerRemote.enqueue(dataSet[id])
}
GlideApp.with(activity)
.asBitmapPalette()
.load(RetroGlideExtension.getSongModel(dataSet[id]))
.transition(RetroGlideExtension.getDefaultTransition())
.songOptions(dataSet[id])
.into(object : RetroMusicColoredTarget(imageView) {
override fun onColorReady(color: Int) {
}
})
}
val color = ThemeStore.accentColor(activity)
textView.apply {
setBackgroundColor(color);
setTextColor(MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(color)))
}
title.text = activity.getString(home.title)
icon.setImageResource(home.icon)
playSuggestion.apply {
TintHelper.setTintAuto(this, MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(color)), false)
TintHelper.setTintAuto(this, color, true)
setOnClickListener { MusicPlayerRemote.openQueue(home.arrayList as ArrayList<Song>, 0, true) }
}
}
}
private inner class AlbumViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(home: Home) {
recyclerView.apply {
adapter = AlbumFullWidthAdapter(activity, home.arrayList as ArrayList<Album>, displayMetrics)
}
title.text = activity.getString(home.title)
icon.setImageResource(home.icon)
}
private val recyclerView: MetalRecyclerViewPager = view.findViewById(R.id.recyclerView)
private val title: TextView = view.findViewById(R.id.sectionTitle)
private val icon: IconImageView = itemView.findViewById(R.id.sectionIcon)
}
private inner class ArtistViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(home: Home) {
recyclerView.apply {
layoutManager = GridLayoutManager(activity, 1, GridLayoutManager.HORIZONTAL, false)
val artistAdapter = ArtistAdapter(activity, home.arrayList as ArrayList<Artist>, PreferenceUtil.getInstance().getHomeGridStyle(context!!), false, null)
adapter = artistAdapter
}
title.text = activity.getString(home.title)
icon.setImageResource(home.icon)
}
private val recyclerView: RecyclerView = view.findViewById(R.id.recyclerView)
private val title: TextView = view.findViewById(R.id.sectionTitle)
private val icon: IconImageView = itemView.findViewById(R.id.sectionIcon)
}
private inner class GenreViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(home: Home) {
recyclerView.apply {
val genreAdapter = GenreAdapter(activity, home.arrayList as ArrayList<Genre>, R.layout.item_list)
layoutManager = LinearLayoutManager(context)
adapter = genreAdapter
}
title.text = activity.getString(home.title)
icon.setImageResource(home.icon)
}
private val recyclerView: RecyclerView = view.findViewById(R.id.recyclerView)
private val title: TextView = view.findViewById(R.id.sectionTitle)
private val icon: IconImageView = itemView.findViewById(R.id.sectionIcon)
}
private inner class PlaylistViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(home: Home) {
val songs = PlaylistSongsLoader.getPlaylistSongList(activity, home.arrayList[0] as Playlist).blockingFirst()
recyclerView.apply {
val songAdapter = SongAdapter(activity, songs, R.layout.item_album_card, false, null)
layoutManager = GridLayoutManager(activity, 1, GridLayoutManager.HORIZONTAL, false)
adapter = songAdapter
}
title.text = activity.getString(home.title)
icon.setImageResource(home.icon)
}
private val recyclerView: RecyclerView = view.findViewById(R.id.recyclerView)
private val title: TextView = view.findViewById(R.id.sectionTitle)
private val icon: IconImageView = itemView.findViewById(R.id.sectionIcon)
}
}

View file

@ -0,0 +1,136 @@
package code.name.monkey.retromusic.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.util.Pair
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.menu.SongMenuHelper
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import java.util.*
class SearchAdapter(private val activity: AppCompatActivity, private var dataSet: List<Any>?) : RecyclerView.Adapter<SearchAdapter.ViewHolder>() {
fun swapDataSet(dataSet: ArrayList<Any>) {
this.dataSet = dataSet
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int {
if (dataSet!![position] is Album) return ALBUM
if (dataSet!![position] is Artist) return ARTIST
return if (dataSet!![position] is Song) SONG else HEADER
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return if (viewType == HEADER) ViewHolder(LayoutInflater.from(activity).inflate(R.layout.sub_header, parent, false), viewType) else ViewHolder(LayoutInflater.from(activity).inflate(R.layout.item_list, parent, false), viewType)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
when (getItemViewType(position)) {
ALBUM -> {
val album = dataSet!![position] as Album
holder.title!!.text = album.title
holder.text!!.text = album.artistName
GlideApp.with(activity)
.asDrawable()
.load(RetroGlideExtension.getSongModel(album.safeGetFirstSong()))
.transition(RetroGlideExtension.getDefaultTransition())
.songOptions(album.safeGetFirstSong())
.into(holder.image!!)
}
ARTIST -> {
val artist = dataSet!![position] as Artist
holder.title!!.text = artist.name
holder.text!!.text = MusicUtil.getArtistInfoString(activity, artist)
GlideApp.with(activity)
.asBitmap()
.load(RetroGlideExtension.getArtistModel(artist))
.transition(RetroGlideExtension.getDefaultTransition())
.artistOptions(artist)
.into(holder.image!!)
}
SONG -> {
val song = dataSet!![position] as Song
holder.title!!.text = song.title
holder.text!!.text = song.albumName
}
else -> {
holder.title!!.text = dataSet!![position].toString()
holder.title!!.setTextColor(ThemeStore.accentColor(activity))
}
}
}
override fun getItemCount(): Int {
return dataSet!!.size
}
inner class ViewHolder(itemView: View, itemViewType: Int) : MediaEntryViewHolder(itemView) {
init {
itemView.setOnLongClickListener(null)
if (itemViewType != HEADER) {
if (separator != null) {
separator!!.visibility = View.GONE
}
}
if (menu != null) {
if (itemViewType == SONG) {
menu!!.visibility = View.VISIBLE
menu!!.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
override val song: Song
get() = dataSet!![adapterPosition] as Song
})
} else {
menu!!.visibility = View.GONE
}
}
when (itemViewType) {
ALBUM -> setImageTransitionName(activity.getString(R.string.transition_album_art))
ARTIST -> setImageTransitionName(activity.getString(R.string.transition_artist_image))
else -> {
val container = itemView.findViewById<View>(R.id.image_container)
if (container != null) {
container.visibility = View.GONE
}
}
}
}
override fun onClick(v: View?) {
val item = dataSet!![adapterPosition]
when (itemViewType) {
ALBUM -> NavigationUtil.goToAlbum(activity, (item as Album).id, Pair.create(image, activity.resources.getString(R.string.transition_album_art)))
ARTIST -> NavigationUtil.goToArtist(activity, (item as Artist).id, Pair.create(image, activity.resources.getString(R.string.transition_artist_image)))
SONG -> {
val playList = ArrayList<Song>()
playList.add(item as Song)
MusicPlayerRemote.openQueue(playList, 0, true)
}
}
}
}
companion object {
private val HEADER = 0
private val ALBUM = 1
private val ARTIST = 2
private val SONG = 3
}
}

View file

@ -0,0 +1,188 @@
package code.name.monkey.retromusic.adapter
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.audiocover.AudioFileCover
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.GenericTransitionOptions
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.signature.MediaStoreSignature
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
import java.io.File
import java.text.DecimalFormat
import java.util.*
class SongFileAdapter(private val activity: AppCompatActivity, private var dataSet: List<File>?, @param:LayoutRes private val itemLayoutRes: Int, private val callbacks: Callbacks?, cabHolder: CabHolder?) : AbsMultiSelectAdapter<SongFileAdapter.ViewHolder, File>(activity, cabHolder, R.menu.menu_media_selection), FastScrollRecyclerView.SectionedAdapter {
init {
this.setHasStableIds(true)
}
override fun getItemViewType(position: Int): Int {
return if (dataSet!![position].isDirectory) FOLDER else FILE
}
override fun getItemId(position: Int): Long {
return dataSet!![position].hashCode().toLong()
}
fun swapDataSet(songFiles: List<File>) {
this.dataSet = songFiles
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, index: Int) {
val file = dataSet!![index]
holder.itemView.isActivated = isChecked(file)
if (holder.adapterPosition == itemCount - 1) {
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.GONE
}
} else {
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.VISIBLE
}
}
if (holder.title != null) {
holder.title!!.text = getFileTitle(file)
}
if (holder.text != null) {
if (holder.itemViewType == FILE) {
holder.text!!.text = getFileText(file)
} else {
holder.text!!.visibility = View.GONE
}
}
if (holder.image != null) {
loadFileImage(file, holder)
}
}
private fun getFileTitle(file: File): String {
return file.name
}
private fun getFileText(file: File): String? {
return if (file.isDirectory) null else readableFileSize(file.length())
}
private fun loadFileImage(file: File, holder: ViewHolder) {
val iconColor = ATHUtil.resolveColor(activity, R.attr.iconColor)
if (file.isDirectory) {
holder.image!!.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN)
holder.image!!.setImageResource(R.drawable.ic_folder_white_24dp)
} else {
val error = RetroUtil.getTintedVectorDrawable(activity, R.drawable.ic_file_music_white_24dp, iconColor)
GlideApp.with(activity)
.load(AudioFileCover(file.path))
.transition(GenericTransitionOptions.with<Drawable>(android.R.anim.fade_in))
.apply(RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.error(error)
.placeholder(error)
.signature(MediaStoreSignature("", file.lastModified(), 0)))
.into(holder.image!!)
}
}
override fun getItemCount(): Int {
return dataSet!!.size
}
override fun getIdentifier(position: Int): File? {
return dataSet!![position]
}
override fun getName(`object`: File): String {
return getFileTitle(`object`)
}
override fun onMultipleItemAction(menuItem: MenuItem, selection: ArrayList<File>) {
if (callbacks == null) return
callbacks.onMultipleItemAction(menuItem, selection)
}
override fun getSectionName(position: Int): String {
return dataSet!![position].name[0].toString().toUpperCase()
}
interface Callbacks {
fun onFileSelected(file: File)
fun onFileMenuClicked(file: File, view: View)
fun onMultipleItemAction(item: MenuItem, files: ArrayList<File>)
}
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
init {
if (menu != null && callbacks != null) {
menu!!.setOnClickListener { v ->
val position = adapterPosition
if (isPositionInRange(position)) {
callbacks.onFileMenuClicked(dataSet!![position], v)
}
}
}
if (imageTextContainer != null) {
imageTextContainer?.cardElevation = 0f
}
}
override fun onClick(v: View?) {
val position = adapterPosition
if (isPositionInRange(position)) {
if (isInQuickSelectMode) {
toggleChecked(position)
} else {
callbacks?.onFileSelected(dataSet!![position])
}
}
}
override fun onLongClick(v: View?): Boolean {
val position = adapterPosition
return isPositionInRange(position) && toggleChecked(position)
}
private fun isPositionInRange(position: Int): Boolean {
return position >= 0 && position < dataSet!!.size
}
}
companion object {
private const val FILE = 0
private const val FOLDER = 1
fun readableFileSize(size: Long): String {
if (size <= 0) return size.toString() + " B"
val units = arrayOf("B", "KB", "MB", "GB", "TB")
val digitGroups = (Math.log10(size.toDouble()) / Math.log10(1024.0)).toInt()
return DecimalFormat("#,##0.##").format(size / Math.pow(1024.0, digitGroups.toDouble())) + " " + units[digitGroups]
}
}
}

View file

@ -0,0 +1,20 @@
package code.name.monkey.retromusic.adapter
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.adapter.song.SongAdapter
import java.util.*
class SpanSongsAdapter(activity: AppCompatActivity, dataSet: ArrayList<Song>, itemLayoutRes: Int, usePalette: Boolean, cabHolder: CabHolder?) : SongAdapter(activity, dataSet, itemLayoutRes, usePalette, cabHolder) {
override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) {
super.onBindViewHolder(holder, position)
if (position == 0) {
val params = StaggeredGridLayoutManager.LayoutParams(StaggeredGridLayoutManager.LayoutParams.WRAP_CONTENT, StaggeredGridLayoutManager.LayoutParams.MATCH_PARENT)
params.isFullSpan = true
holder.itemView.layoutParams = params
}
}
}

View file

@ -0,0 +1,217 @@
package code.name.monkey.retromusic.adapter.album
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.core.util.Pair
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
import java.util.*
open class AlbumAdapter(protected val activity: AppCompatActivity,
dataSet: ArrayList<Album>,
@param:LayoutRes protected var itemLayoutRes: Int,
usePalette: Boolean,
cabHolder: CabHolder?) : AbsMultiSelectAdapter<AlbumAdapter.ViewHolder, Album>(activity, cabHolder, R.menu.menu_media_selection), FastScrollRecyclerView.SectionedAdapter {
var dataSet: ArrayList<Album>
protected set
protected var usePalette = false
init {
this.dataSet = dataSet
this.usePalette = usePalette
this.setHasStableIds(true)
}
fun useItemLayout(itemLayoutRes: Int) {
this.itemLayoutRes = itemLayoutRes
notifyDataSetChanged()
}
fun usePalette(usePalette: Boolean) {
this.usePalette = usePalette
notifyDataSetChanged()
}
fun swapDataSet(dataSet: ArrayList<Album>) {
this.dataSet = dataSet
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false)
return createViewHolder(view, viewType)
}
protected open fun createViewHolder(view: View, viewType: Int): ViewHolder {
return ViewHolder(view)
}
private fun getAlbumTitle(album: Album): String? {
return album.title
}
protected open fun getAlbumText(album: Album): String? {
return album.artistName
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val album = dataSet[position]
val isChecked = isChecked(album)
holder.itemView.isActivated = isChecked
if (holder.adapterPosition == itemCount - 1) {
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.GONE
}
} else {
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.GONE
}
}
if (holder.title != null) {
holder.title!!.text = getAlbumTitle(album)
}
if (holder.text != null) {
holder.text!!.text = getAlbumText(album)
}
if (holder.playSongs != null) {
holder.playSongs!!.setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) }
}
loadAlbumCover(album, holder)
}
protected open fun setColors(color: Int, holder: ViewHolder) {
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer!!.setBackgroundColor(color)
if (holder.title != null) {
holder.title!!.setTextColor(MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)))
}
if (holder.text != null) {
holder.text!!.setTextColor(MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)))
}
}
if (holder.mask != null) {
holder.mask!!.backgroundTintList = ColorStateList.valueOf(color)
}
}
protected open fun loadAlbumCover(album: Album, holder: ViewHolder) {
if (holder.image == null) {
return
}
GlideApp.with(activity)
.asBitmapPalette()
.load(RetroGlideExtension.getSongModel(album.safeGetFirstSong()))
.transition(RetroGlideExtension.getDefaultTransition())
.songOptions(album.safeGetFirstSong())
.dontAnimate()
.into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(color: Int) {
setColors(color, holder)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
setColors(defaultFooterColor, holder)
}
})
}
override fun getItemCount(): Int {
return dataSet.size
}
override fun getItemId(position: Int): Long {
return dataSet[position].id.toLong()
}
override fun getIdentifier(position: Int): Album? {
return dataSet[position]
}
override fun getName(album: Album): String {
return album.title!!
}
override fun onMultipleItemAction(menuItem: MenuItem,
selection: ArrayList<Album>) {
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.itemId)
}
private fun getSongList(albums: List<Album>): ArrayList<Song> {
val songs = ArrayList<Song>()
for (album in albums) {
songs.addAll(album.songs!!)
}
return songs
}
override fun getSectionName(position: Int): String {
var sectionName: String? = null
when (PreferenceUtil.getInstance().albumSortOrder) {
SortOrder.AlbumSortOrder.ALBUM_A_Z, SortOrder.AlbumSortOrder.ALBUM_Z_A -> sectionName = dataSet[position].title
SortOrder.AlbumSortOrder.ALBUM_ARTIST -> sectionName = dataSet[position].artistName
SortOrder.AlbumSortOrder.ALBUM_YEAR -> return MusicUtil.getYearString(dataSet[position].year)
}
return MusicUtil.getSectionName(sectionName)
}
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
init {
setImageTransitionName(activity.getString(R.string.transition_album_art))
if (menu != null) {
menu!!.visibility = View.GONE
}
}
override fun onClick(v: View?) {
super.onClick(v)
if (isInQuickSelectMode) {
toggleChecked(adapterPosition)
} else {
val albumPairs = arrayOf<Pair<*, *>>(Pair.create(image, activity.resources.getString(R.string.transition_album_art)))
NavigationUtil.goToAlbum(activity, dataSet[adapterPosition].id, *albumPairs)
}
}
override fun onLongClick(v: View?): Boolean {
toggleChecked(adapterPosition)
return super.onLongClick(v)
}
}
companion object {
val TAG: String = AlbumAdapter::class.java.simpleName
}
}

View file

@ -0,0 +1,170 @@
package code.name.monkey.retromusic.adapter.album
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.misc.CustomFragmentStatePagerAdapter
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.activities.LyricsActivity
import code.name.monkey.retromusic.fragments.AlbumCoverStyle
import code.name.monkey.retromusic.util.PreferenceUtil
import java.util.*
class AlbumCoverPagerAdapter(fm: FragmentManager, private val dataSet: ArrayList<Song>) : CustomFragmentStatePagerAdapter(fm) {
private var currentColorReceiver: AlbumCoverFragment.ColorReceiver? = null
private var currentColorReceiverPosition = -1
override fun getItem(position: Int): Fragment {
return AlbumCoverFragment.newInstance(dataSet[position])
}
override fun getCount(): Int {
return dataSet.size
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val o = super.instantiateItem(container, position)
if (currentColorReceiver != null && currentColorReceiverPosition == position) {
receiveColor(currentColorReceiver!!, currentColorReceiverPosition)
}
return o
}
/**
* Only the latest passed [AlbumCoverFragment.ColorReceiver] is guaranteed to receive a
* response
*/
fun receiveColor(colorReceiver: AlbumCoverFragment.ColorReceiver, position: Int) {
if (getFragment(position) is AlbumCoverFragment) {
val fragment = getFragment(position) as AlbumCoverFragment
currentColorReceiver = null
currentColorReceiverPosition = -1
fragment.receiveColor(colorReceiver, position)
} else {
currentColorReceiver = colorReceiver
currentColorReceiverPosition = position
}
}
class AlbumCoverFragment : Fragment() {
lateinit var albumCover: ImageView
private var isColorReady: Boolean = false
private var color: Int = 0
private lateinit var song: Song
private var colorReceiver: ColorReceiver? = null
private var request: Int = 0
private val layout: Int
get() {
return when (PreferenceUtil.getInstance().albumCoverStyle) {
AlbumCoverStyle.NORMAL -> R.layout.fragment_album_cover
AlbumCoverStyle.FLAT -> R.layout.fragment_album_flat_cover
AlbumCoverStyle.CIRCLE -> R.layout.fragment_album_circle_cover
AlbumCoverStyle.CARD -> R.layout.fragment_album_card_cover
AlbumCoverStyle.MATERIAL -> R.layout.fragment_album_material_cover
AlbumCoverStyle.FULL -> R.layout.fragment_album_full_cover
AlbumCoverStyle.FULL_CARD -> R.layout.fragment_album_full_card_cover
else -> R.layout.fragment_album_cover
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments != null) {
song = arguments!!.getParcelable(SONG_ARG)!!
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val layout = layout
val view = inflater.inflate(layout, container, false)
albumCover = view.findViewById(R.id.player_image)
albumCover.setOnClickListener { startActivity(Intent(context, LyricsActivity::class.java)) }
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
loadAlbumCover()
}
override fun onDestroyView() {
super.onDestroyView()
colorReceiver = null
}
private fun loadAlbumCover() {
GlideApp.with(context!!)
.asBitmapPalette()
.load(RetroGlideExtension.getSongModel(song!!))
.transition(RetroGlideExtension.getDefaultTransition())
.songOptions(song)
.dontAnimate()
.into(object : RetroMusicColoredTarget(albumCover) {
override fun onColorReady(color: Int) {
setColor(color)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
setColor(defaultFooterColor)
}
})
}
private fun setColor(color: Int) {
this.color = color
isColorReady = true
if (colorReceiver != null) {
colorReceiver!!.onColorReady(color, request)
colorReceiver = null
}
}
internal fun receiveColor(colorReceiver: ColorReceiver, request: Int) {
if (isColorReady) {
colorReceiver.onColorReady(color, request)
} else {
this.colorReceiver = colorReceiver
this.request = request
}
}
interface ColorReceiver {
fun onColorReady(color: Int, request: Int)
}
companion object {
private const val SONG_ARG = "song"
fun newInstance(song: Song): AlbumCoverFragment {
val frag = AlbumCoverFragment()
val args = Bundle()
args.putParcelable(SONG_ARG, song)
frag.arguments = args
return frag
}
}
}
companion object {
val TAG: String = AlbumCoverPagerAdapter::class.java.simpleName
}
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (C) 2017. Alexander Bilchuk <a.bilchuk@sandrlab.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package code.name.monkey.retromusic.adapter.album
import android.app.Activity
import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.util.Pair
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.views.MetalRecyclerViewPager
class AlbumFullWidthAdapter(private val activity: Activity, private val dataSet: ArrayList<Album>, metrics: DisplayMetrics) :
MetalRecyclerViewPager.MetalAdapter<AlbumFullWidthAdapter.FullMetalViewHolder>(metrics) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FullMetalViewHolder {
return FullMetalViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.pager_item, parent, false))
}
override fun onBindViewHolder(holder: FullMetalViewHolder, position: Int) {
// don't forget about calling supper.onBindViewHolder!
super.onBindViewHolder(holder, position)
val album = dataSet[position]
if (holder.title != null) {
holder.title!!.text = getAlbumTitle(album)
}
if (holder.text != null) {
holder.text!!.text = getAlbumText(album)
}
if (holder.playSongs != null) {
holder.playSongs!!.setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) }
}
loadAlbumCover(album, holder)
}
private fun getAlbumTitle(album: Album): String? {
return album.title
}
private fun getAlbumText(album: Album): String? {
return album.artistName
}
private fun loadAlbumCover(album: Album, holder: FullMetalViewHolder) {
if (holder.image == null) {
return
}
GlideApp.with(activity)
.asBitmapPalette()
.load(RetroGlideExtension.getSongModel(album.safeGetFirstSong()))
.transition(RetroGlideExtension.getDefaultTransition())
.songOptions(album.safeGetFirstSong())
.dontAnimate()
.into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(color: Int) {
}
})
}
override fun getItemCount(): Int {
return dataSet.size
}
inner class FullMetalViewHolder(itemView: View) : MetalRecyclerViewPager.MetalViewHolder(itemView) {
override fun onClick(v: View?) {
val albumPairs = arrayOf<Pair<*, *>>(Pair.create(image, activity.resources.getString(R.string.transition_album_art)))
NavigationUtil.goToAlbum(activity, dataSet[adapterPosition].id, *albumPairs)
}
}
}

View file

@ -0,0 +1,75 @@
package code.name.monkey.retromusic.adapter.album
import android.graphics.drawable.Drawable
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.HorizontalAdapterHelper
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.util.MusicUtil
import java.util.*
class HorizontalAlbumAdapter(activity: AppCompatActivity, dataSet: ArrayList<Album>, usePalette: Boolean, cabHolder: CabHolder?) : AlbumAdapter(activity, dataSet, HorizontalAdapterHelper.LAYOUT_RES, usePalette, cabHolder) {
override fun createViewHolder(view: View, viewType: Int): ViewHolder {
val params = view.layoutParams as ViewGroup.MarginLayoutParams
HorizontalAdapterHelper.applyMarginToLayoutParams(activity, params, viewType)
return ViewHolder(view)
}
override fun setColors(color: Int, holder: ViewHolder) {
if (holder.title != null) {
holder.title!!.setTextColor(MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)))
}
if (holder.text != null) {
holder.text!!.setTextColor(MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)))
}
}
override fun loadAlbumCover(album: Album, holder: ViewHolder) {
if (holder.image == null) return
GlideApp.with(activity)
.asBitmapPalette()
.load(RetroGlideExtension.getSongModel(album.safeGetFirstSong()))
.transition(RetroGlideExtension.getDefaultTransition())
.songOptions(album.safeGetFirstSong())
.dontAnimate()
.into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(color: Int) {
if (usePalette)
setColors(color, holder)
else
setColors(albumArtistFooterColor, holder)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
setColors(albumArtistFooterColor, holder)
}
})
}
override fun getAlbumText(album: Album): String? {
return MusicUtil.getYearString(album.year)
}
override fun getItemViewType(position: Int): Int {
return HorizontalAdapterHelper.getItemViewtype(position, itemCount)
}
override fun getItemCount(): Int {
return dataSet.size
}
companion object {
val TAG: String = AlbumAdapter::class.java.simpleName
}
}

View file

@ -0,0 +1,161 @@
package code.name.monkey.retromusic.adapter.artist
import android.content.res.ColorStateList
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.core.util.Pair
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
import java.util.*
class ArtistAdapter(val activity: AppCompatActivity,
var dataSet: ArrayList<Artist>,
@LayoutRes var itemLayoutRes: Int,
var usePalette: Boolean,
cabHolder: CabHolder?) : AbsMultiSelectAdapter<ArtistAdapter.ViewHolder, Artist>(activity, cabHolder, R.menu.menu_media_selection), FastScrollRecyclerView.SectionedAdapter {
fun swapDataSet(dataSet: ArrayList<Artist>) {
this.dataSet = dataSet
notifyDataSetChanged()
}
fun usePalette(usePalette: Boolean) {
this.usePalette = usePalette
notifyDataSetChanged()
}
override fun getItemId(position: Int): Long {
return dataSet[position].id.toLong()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false)
return createViewHolder(view)
}
private fun createViewHolder(view: View): ViewHolder {
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val artist = dataSet[position]
val isChecked = isChecked(artist)
holder.itemView.isActivated = isChecked
if (holder.title != null) {
holder.title!!.text = artist.name
}
if (holder.text != null) {
holder.text!!.visibility = View.GONE
}
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.GONE
}
loadArtistImage(artist, holder)
}
fun setColors(color: Int, holder: ViewHolder) {
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer!!.setBackgroundColor(color)
if (holder.title != null) {
holder.title!!.setTextColor(
MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)))
}
}
if (holder.mask != null) {
holder.mask!!.backgroundTintList = ColorStateList.valueOf(color)
}
}
private fun loadArtistImage(artist: Artist, holder: ViewHolder) {
if (holder.image == null) {
return
}
GlideApp.with(activity)
.asBitmapPalette()
.load(RetroGlideExtension.getArtistModel(artist))
.transition(RetroGlideExtension.getDefaultTransition())
.artistOptions(artist)
.dontAnimate()
.into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(color: Int) {
setColors(color, holder)
}
})
}
override fun getItemCount(): Int {
return dataSet.size
}
override fun getIdentifier(position: Int): Artist? {
return dataSet[position]
}
override fun getName(artist: Artist): String {
return artist.name
}
override fun onMultipleItemAction(menuItem: MenuItem,
selection: ArrayList<Artist>) {
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.itemId)
}
private fun getSongList(artists: List<Artist>): ArrayList<Song> {
val songs = ArrayList<Song>()
for (artist in artists) {
songs.addAll(artist.songs) // maybe async in future?
}
return songs
}
override fun getSectionName(position: Int): String {
return MusicUtil.getSectionName(dataSet[position].name)
}
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
init {
setImageTransitionName(activity.getString(R.string.transition_artist_image))
if (menu != null) {
menu!!.visibility = View.GONE
}
}
override fun onClick(v: View?) {
super.onClick(v)
if (isInQuickSelectMode) {
toggleChecked(adapterPosition)
} else {
val artistPairs = arrayOf<Pair<*, *>>(Pair.create<ImageView, String>(image,
activity.resources.getString(R.string.transition_artist_image)))
NavigationUtil.goToArtist(activity, dataSet[adapterPosition].id, *artistPairs)
}
}
override fun onLongClick(v: View?): Boolean {
toggleChecked(adapterPosition)
return super.onLongClick(v)
}
}
}

View file

@ -0,0 +1,122 @@
package code.name.monkey.retromusic.adapter.base;
import android.content.Context;
import androidx.annotation.MenuRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;
import com.afollestad.materialcab.MaterialCab;
import java.util.ArrayList;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.interfaces.CabHolder;
public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder, I> extends RecyclerView.Adapter<VH> implements MaterialCab.Callback {
@Nullable
private final CabHolder cabHolder;
private final Context context;
private MaterialCab cab;
private ArrayList<I> checked;
private int menuRes;
public AbsMultiSelectAdapter(@NonNull Context context, @Nullable CabHolder cabHolder, @MenuRes int menuRes) {
this.cabHolder = cabHolder;
checked = new ArrayList<>();
this.menuRes = menuRes;
this.context = context;
}
protected void setMultiSelectMenuRes(@MenuRes int menuRes) {
this.menuRes = menuRes;
}
protected boolean toggleChecked(final int position) {
if (cabHolder != null) {
I identifier = getIdentifier(position);
if (identifier == null) return false;
if (!checked.remove(identifier)) checked.add(identifier);
notifyItemChanged(position);
updateCab();
return true;
}
return false;
}
protected void checkAll() {
if (cabHolder != null) {
checked.clear();
for (int i = 0; i < getItemCount(); i++) {
I identifier = getIdentifier(i);
if (identifier != null) {
checked.add(identifier);
}
}
notifyDataSetChanged();
updateCab();
}
}
private void updateCab() {
if (cabHolder != null) {
if (cab == null || !cab.isActive()) {
cab = cabHolder.openCab(menuRes, this);
}
final int size = checked.size();
if (size <= 0) cab.finish();
else if (size == 1) cab.setTitle(getName(checked.get(0)));
else cab.setTitle(context.getString(R.string.x_selected, size));
}
}
private void clearChecked() {
checked.clear();
notifyDataSetChanged();
}
protected boolean isChecked(I identifier) {
return checked.contains(identifier);
}
protected boolean isInQuickSelectMode() {
return cab != null && cab.isActive();
}
@Override
public boolean onCabCreated(MaterialCab materialCab, Menu menu) {
return true;
}
@Override
public boolean onCabItemClicked(MenuItem menuItem) {
if (menuItem.getItemId() == R.id.action_multi_select_adapter_check_all) {
checkAll();
} else {
onMultipleItemAction(menuItem, new ArrayList<>(checked));
cab.finish();
clearChecked();
}
return true;
}
@Override
public boolean onCabFinished(MaterialCab materialCab) {
clearChecked();
return true;
}
protected String getName(I object) {
return object.toString();
}
@Nullable
protected abstract I getIdentifier(int position);
protected abstract void onMultipleItemAction(MenuItem menuItem, ArrayList<I> selection);
}

View file

@ -0,0 +1,82 @@
package code.name.monkey.retromusic.adapter.base
import android.os.Build
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
open class MediaEntryViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener, View.OnLongClickListener {
override fun onLongClick(v: View?): Boolean {
return false
}
override fun onClick(v: View?) {
}
var image: ImageView? = null
var imageText: TextView? = null
var title: TextView? = null
var text: TextView? = null
var imageContainer: ViewGroup? = null
var imageContainerCard: CardView? = null
var menu: View? = null
var separator: View? = null
var shortSeparator: View? = null
var dragView: View? = null
var paletteColorContainer: View? = null
var time: TextView? = null
var recyclerView: RecyclerView? = null
var playSongs: ImageButton? = null
var mask: View? = null
var imageTextContainer: CardView? = null
init {
title = view.findViewById(R.id.title)
text = view.findViewById(R.id.text)
image = view.findViewById(R.id.image)
imageContainer = view.findViewById(R.id.image_container)
imageTextContainer = view.findViewById(R.id.image_text_container)
imageContainerCard = view.findViewById(R.id.image_container_card)
imageText = view.findViewById(R.id.image_text)
menu = view.findViewById(R.id.menu)
dragView = view.findViewById(R.id.drag_view)
separator = view.findViewById(R.id.separator)
shortSeparator = view.findViewById(R.id.short_separator)
paletteColorContainer = view.findViewById(R.id.palette_color_container)
time = view.findViewById(R.id.time);
recyclerView = view.findViewById(R.id.recycler_view)
mask = view.findViewById(R.id.mask)
playSongs = view.findViewById(R.id.playSongs)
view.setOnClickListener(this@MediaEntryViewHolder)
view.setOnLongClickListener(this)
if (imageTextContainer != null) {
imageTextContainer!!.setCardBackgroundColor(ThemeStore.primaryColor(itemView.context))
}
if (imageContainerCard != null) {
imageContainerCard!!.setCardBackgroundColor(ThemeStore.primaryColor(itemView.context))
}
}
fun setImageTransitionName(transitionName: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && image != null) {
image!!.transitionName = transitionName
}
}
}

View file

@ -0,0 +1,44 @@
package code.name.monkey.retromusic.adapter.playlist
import android.app.Activity
import android.app.Dialog
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import java.util.ArrayList
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.adapter.playlist.AddToPlaylist.ViewHolder
import code.name.monkey.retromusic.util.PlaylistsUtil
class AddToPlaylist(private val activity: Activity,
private val playlists: ArrayList<Playlist>, private val itemLayoutRes: Int,
private val songs: ArrayList<Song>, private val dialog: Dialog) : RecyclerView.Adapter<ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val playlist = playlists[position]
if (holder.title != null) {
holder.title!!.text = playlist.name
}
}
override fun getItemCount(): Int {
return playlists.size
}
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
override fun onClick(v: View?) {
super.onClick(v)
PlaylistsUtil.addToPlaylist(activity, songs, playlists[adapterPosition].id, true)
dialog.dismiss()
}
}
}

View file

@ -0,0 +1,232 @@
package code.name.monkey.retromusic.adapter.playlist
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.ClearSmartPlaylistDialog
import code.name.monkey.retromusic.dialogs.DeletePlaylistDialog
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
import code.name.monkey.retromusic.model.AbsCustomPlaylist
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import java.util.*
class PlaylistAdapter(protected val activity: AppCompatActivity, dataSet: ArrayList<Playlist>,
@param:LayoutRes protected var itemLayoutRes: Int, cabHolder: CabHolder?) : AbsMultiSelectAdapter<PlaylistAdapter.ViewHolder, Playlist>(activity, cabHolder, R.menu.menu_playlists_selection) {
var dataSet: ArrayList<Playlist>
protected set
var songs = ArrayList<Song>()
init {
this.dataSet = dataSet
setHasStableIds(true)
}
fun swapDataSet(dataSet: ArrayList<Playlist>) {
this.dataSet = dataSet
notifyDataSetChanged()
}
override fun getItemId(position: Int): Long {
return dataSet[position].id.toLong()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(activity)
.inflate(itemLayoutRes, parent, false)
return createViewHolder(view)
}
protected fun createViewHolder(view: View): ViewHolder {
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
/* if (getItemViewType(position) == SMART_PLAYLIST) {
if (holder.viewList != null) {
holder.viewList.get(0).setOnClickListener(
v -> NavigationUtil.goToPlaylistNew(activity, new HistoryPlaylist(activity)));
holder.viewList.get(1).setOnClickListener(
v -> NavigationUtil.goToPlaylistNew(activity, new LastAddedPlaylist(activity)));
holder.viewList.get(2).setOnClickListener(
v -> NavigationUtil.goToPlaylistNew(activity, new MyTopTracksPlaylist(activity)));
}
return;
}*/
val playlist = dataSet[position]
val songs = getSongs(playlist)
holder.itemView.isActivated = isChecked(playlist)
if (holder.title != null) {
holder.title!!.text = playlist.name
}
if (holder.text != null) {
holder.text!!.text = String.format(Locale.getDefault(), "%d Songs", songs!!.size)
}
if (holder.image != null) {
holder.image!!.setImageDrawable(getIconRes(playlist))
}
if (holder.adapterPosition == itemCount - 1) {
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.GONE
}
} else {
if (holder.shortSeparator != null && dataSet[position] !is AbsSmartPlaylist) {
holder.shortSeparator!!.visibility = View.GONE
}
}
}
private fun getIconRes(playlist: Playlist): Drawable {
if (playlist is AbsSmartPlaylist) {
return TintHelper.createTintedDrawable(activity, playlist.iconRes, ATHUtil.resolveColor(activity, R.attr.iconColor))!!
}
return if (MusicUtil.isFavoritePlaylist(activity, playlist))
TintHelper.createTintedDrawable(activity, R.drawable.ic_favorite_white_24dp, ThemeStore.accentColor(activity))!!
else
TintHelper.createTintedDrawable(activity, R.drawable.ic_playlist_play_white_24dp, ATHUtil.resolveColor(activity, R.attr.iconColor))!!
}
override fun getItemViewType(position: Int): Int {
return if (dataSet[position] is AbsSmartPlaylist) SMART_PLAYLIST else DEFAULT_PLAYLIST
}
override fun getItemCount(): Int {
return dataSet.size
}
override fun getIdentifier(position: Int): Playlist? {
return dataSet[position]
}
override fun getName(playlist: Playlist): String {
return playlist.name
}
override fun onMultipleItemAction(menuItem: MenuItem, selection: ArrayList<Playlist>) {
when (menuItem.itemId) {
R.id.action_delete_playlist -> {
var i = 0
while (i < selection.size) {
val playlist = selection[i]
if (playlist is AbsSmartPlaylist) {
ClearSmartPlaylistDialog.create(playlist)
.show(activity.supportFragmentManager,
"CLEAR_PLAYLIST_" + playlist.name)
selection.remove(playlist)
i--
}
i++
}
if (selection.size > 0) {
DeletePlaylistDialog.create(selection)
.show(activity.supportFragmentManager, "DELETE_PLAYLIST")
}
}
else -> SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.itemId)
}
}
private fun getSongList(playlists: List<Playlist>): ArrayList<Song> {
val songs = ArrayList<Song>()
for (playlist in playlists) {
if (playlist is AbsCustomPlaylist) {
songs.addAll(playlist.getSongs(activity).blockingFirst())
} else {
songs
.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id).blockingFirst())
}
}
return songs
}
private fun getSongs(playlist: Playlist): ArrayList<Song>? {
val songs = ArrayList<Song>()
if (playlist is AbsSmartPlaylist) {
songs.addAll(playlist.getSongs(activity).blockingFirst())
} else {
songs.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id).blockingFirst())
}
return songs
}
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
init {
image?.apply {
val iconPadding = activity.resources.getDimensionPixelSize(R.dimen.list_item_image_icon_padding)
setPadding(iconPadding, iconPadding, iconPadding, iconPadding)
//setColorFilter(ATHUtil.resolveColor(activity, R.attr.iconColor), PorterDuff.Mode.SRC_IN)
}
menu?.setOnClickListener { view ->
val playlist = dataSet[adapterPosition]
val popupMenu = PopupMenu(activity, view)
popupMenu.inflate(if (itemViewType == SMART_PLAYLIST)
R.menu.menu_item_smart_playlist
else
R.menu.menu_item_playlist)
if (playlist is LastAddedPlaylist) {
popupMenu.menu.findItem(R.id.action_clear_playlist).isVisible = false
}
popupMenu.setOnMenuItemClickListener { item ->
if (item.itemId == R.id.action_clear_playlist) {
if (playlist is AbsSmartPlaylist) {
ClearSmartPlaylistDialog.create(playlist)
.show(activity.supportFragmentManager,
"CLEAR_SMART_PLAYLIST_" + playlist.name)
return@setOnMenuItemClickListener true
}
}
PlaylistMenuHelper.handleMenuClick(
activity, dataSet[adapterPosition], item)
}
popupMenu.show()
}
imageTextContainer?.cardElevation = 0f
}
override fun onClick(v: View?) {
if (isInQuickSelectMode) {
toggleChecked(adapterPosition)
} else {
val playlist = dataSet[adapterPosition]
NavigationUtil.goToPlaylistNew(activity, playlist)
}
}
override fun onLongClick(v: View?): Boolean {
toggleChecked(adapterPosition)
return true
}
}
companion object {
val TAG: String = PlaylistAdapter::class.java.simpleName
private const val SMART_PLAYLIST = 0
private const val DEFAULT_PLAYLIST = 1
}
}

View file

@ -0,0 +1,85 @@
package code.name.monkey.retromusic.adapter.song
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Song
import java.util.*
abstract class AbsOffsetSongAdapter : SongAdapter {
constructor(activity: AppCompatActivity, dataSet: ArrayList<Song>, @LayoutRes itemLayoutRes: Int, usePalette: Boolean, cabHolder: CabHolder?) : super(activity, dataSet, itemLayoutRes, usePalette, cabHolder)
constructor(activity: AppCompatActivity, dataSet: ArrayList<Song>, @LayoutRes itemLayoutRes: Int, usePalette: Boolean, cabHolder: CabHolder?, showSectionName: Boolean) : super(activity, dataSet, itemLayoutRes, usePalette, cabHolder, showSectionName) {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongAdapter.ViewHolder {
if (viewType == OFFSET_ITEM) {
val view = LayoutInflater.from(activity).inflate(R.layout.item_list_single_row, parent, false)
return createViewHolder(view)
}
return super.onCreateViewHolder(parent, viewType)
}
override fun createViewHolder(view: View): SongAdapter.ViewHolder {
return ViewHolder(view)
}
override fun getItemId(position: Int): Long {
var positionFinal = position
positionFinal--
return if (positionFinal < 0) -2 else super.getItemId(positionFinal)
}
override fun getIdentifier(position: Int): Song? {
var positionFinal = position
positionFinal--
return if (positionFinal < 0) null else super.getIdentifier(positionFinal)
}
override fun getItemCount(): Int {
val superItemCount = super.getItemCount()
return if (superItemCount == 0) 0 else superItemCount + 1
}
override fun getItemViewType(position: Int): Int {
return if (position == 0) OFFSET_ITEM else SONG
}
override fun getSectionName(position: Int): String {
var positionF = position
positionF--
return if (positionF < 0) "" else super.getSectionName(positionF)
}
open inner class ViewHolder(itemView: View) : SongAdapter.ViewHolder(itemView) {
override// could also return null, just to be safe return empty song
val song: Song
get() = if (itemViewType == OFFSET_ITEM) Song.emptySong else dataSet[adapterPosition - 1]
override fun onClick(v: View?) {
if (isInQuickSelectMode && itemViewType != OFFSET_ITEM) {
toggleChecked(adapterPosition)
} else {
MusicPlayerRemote.openQueue(dataSet, adapterPosition - 1, true)
}
}
override fun onLongClick(v: View?): Boolean {
if (itemViewType == OFFSET_ITEM) return false
toggleChecked(adapterPosition)
return true
}
}
companion object {
const val OFFSET_ITEM = 0
const val SONG = 1
}
}

View file

@ -0,0 +1,133 @@
package code.name.monkey.retromusic.adapter.song
import android.view.MenuItem
import android.view.View
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.RemoveFromPlaylistDialog
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.PlaylistSong
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.ViewUtil
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemViewHolder
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange
import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags
class OrderablePlaylistSongAdapter(activity: AppCompatActivity,
dataSet: ArrayList<Song>,
@LayoutRes itemLayoutRes: Int,
usePalette: Boolean,
cabHolder: CabHolder?,
private val onMoveItemListener: OnMoveItemListener?) : PlaylistSongAdapter(activity, dataSet, itemLayoutRes, usePalette, cabHolder), DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> {
init {
setMultiSelectMenuRes(code.name.monkey.retromusic.R.menu.menu_playlists_songs_selection)
}
override fun createViewHolder(view: View): SongAdapter.ViewHolder {
return ViewHolder(view)
}
override fun getItemId(position: Int): Long {
var positionFinal = position
positionFinal--
var long: Long = 0
if (positionFinal < 0) {
long = -2
} else {
if (dataSet[positionFinal] is PlaylistSong) {
long = (dataSet[positionFinal] as PlaylistSong).idInPlayList.toLong()
}
}
return long
}
override fun onMultipleItemAction(menuItem: MenuItem, selection: ArrayList<Song>) {
when (menuItem.itemId) {
R.id.action_remove_from_playlist -> {
RemoveFromPlaylistDialog.create(selection as ArrayList<PlaylistSong>).show(activity.supportFragmentManager, "ADD_PLAYLIST")
return
}
}
super.onMultipleItemAction(menuItem, selection)
}
override fun onCheckCanStartDrag(holder: ViewHolder, position: Int, x: Int, y: Int): Boolean {
return onMoveItemListener != null && position > 0 &&
(ViewUtil.hitTest(holder.dragView!!, x, y) || ViewUtil.hitTest(holder.image!!, x, y))
}
override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange {
return ItemDraggableRange(1, dataSet.size)
}
override fun onMoveItem(fromPosition: Int, toPosition: Int) {
if (onMoveItemListener != null && fromPosition != toPosition) {
onMoveItemListener.onMoveItem(fromPosition - 1, toPosition - 1)
}
}
override fun onCheckCanDrop(draggingPosition: Int, dropPosition: Int): Boolean {
return dropPosition > 0
}
override fun onItemDragStarted(position: Int) {
notifyDataSetChanged()
}
override fun onItemDragFinished(fromPosition: Int, toPosition: Int, result: Boolean) {
notifyDataSetChanged()
}
interface OnMoveItemListener {
fun onMoveItem(fromPosition: Int, toPosition: Int)
}
inner class ViewHolder(itemView: View) : PlaylistSongAdapter.ViewHolder(itemView), DraggableItemViewHolder {
@DraggableItemStateFlags
private var mDragStateFlags: Int = 0
override var songMenuRes: Int
get() = code.name.monkey.retromusic.R.menu.menu_item_playlist_song
set(value) {
super.songMenuRes = value
}
init {
if (dragView != null) {
if (onMoveItemListener != null) {
dragView!!.visibility = View.VISIBLE
} else {
dragView!!.visibility = View.GONE
}
}
}
override fun onSongMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) {
code.name.monkey.retromusic.R.id.action_remove_from_playlist -> {
RemoveFromPlaylistDialog.create(song as PlaylistSong).show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST")
return true
}
}
return super.onSongMenuItemClick(item)
}
@DraggableItemStateFlags
override fun getDragStateFlags(): Int {
return mDragStateFlags
}
override fun setDragStateFlags(@DraggableItemStateFlags flags: Int) {
mDragStateFlags = flags
}
}
companion object {
val TAG: String = OrderablePlaylistSongAdapter::class.java.simpleName
}
}

View file

@ -0,0 +1,201 @@
package code.name.monkey.retromusic.adapter.song
import android.graphics.Color
import android.graphics.PorterDuff
import android.view.MenuItem
import android.view.View
import android.widget.ImageView
import androidx.annotation.ColorInt
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.ViewUtil
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemViewHolder
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange
import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags
import java.util.*
class PlayingQueueAdapter : SongAdapter, DraggableItemAdapter<PlayingQueueAdapter.ViewHolder> {
private var current: Int = 0
private var color = -1
constructor(activity: AppCompatActivity, dataSet: ArrayList<Song>, current: Int,
@LayoutRes itemLayoutRes: Int) : super(activity, dataSet, itemLayoutRes, false, null) {
this.current = current
}
constructor(activity: AppCompatActivity,
dataSet: ArrayList<Song>, current: Int,
@LayoutRes itemLayoutRes: Int,
@ColorInt color: Int) : super(activity, dataSet, itemLayoutRes, false, null) {
this.current = current
this.color = color
}
override fun createViewHolder(view: View): SongAdapter.ViewHolder {
return ViewHolder(view)
}
override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) {
super.onBindViewHolder(holder, position)
if (holder.imageText != null) {
holder.imageText!!.text = (position - current).toString()
}
if (holder.time != null) {
holder.time!!.text = MusicUtil.getReadableDurationString(dataSet[position].duration)
}
if (holder.itemViewType == HISTORY || holder.itemViewType == CURRENT) {
setAlpha(holder, 0.5f)
}
if (usePalette) {
setColor(holder, Color.WHITE)
}
}
private fun setColor(holder: SongAdapter.ViewHolder, white: Int) {
if (holder.title != null) {
holder.title!!.setTextColor(white)
if (color != -1) {
holder.title!!.setTextColor(color)
}
}
if (holder.text != null) {
holder.text!!.setTextColor(white)
}
if (holder.time != null) {
holder.time!!.setTextColor(white)
}
if (holder.imageText != null) {
holder.imageText!!.setTextColor(white)
}
if (holder.menu != null) {
(holder.menu as ImageView).setColorFilter(white, PorterDuff.Mode.SRC_IN)
}
}
override fun usePalette(usePalette: Boolean) {
super.usePalette(usePalette)
this.usePalette = usePalette
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int {
if (position < current) {
return HISTORY
} else if (position > current) {
return UP_NEXT
}
return CURRENT
}
override fun loadAlbumCover(song: Song, holder: SongAdapter.ViewHolder) {
// We don't want to load it in this adapter
}
fun swapDataSet(dataSet: ArrayList<Song>, position: Int) {
this.dataSet = dataSet
current = position
notifyDataSetChanged()
}
fun setCurrent(current: Int) {
this.current = current
notifyDataSetChanged()
}
private fun setAlpha(holder: SongAdapter.ViewHolder, alpha: Float) {
if (holder.image != null) {
holder.image!!.alpha = alpha
}
if (holder.title != null) {
holder.title!!.alpha = alpha
}
if (holder.text != null) {
holder.text!!.alpha = alpha
}
if (holder.imageText != null) {
holder.imageText!!.alpha = alpha
}
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer!!.alpha = alpha
}
}
override fun onCheckCanStartDrag(holder: ViewHolder, position: Int, x: Int, y: Int): Boolean {
return ViewUtil.hitTest(holder.imageText!!, x, y) || ViewUtil.hitTest(holder.dragView!!, x, y)
}
override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange? {
return null
}
override fun onMoveItem(fromPosition: Int, toPosition: Int) {
MusicPlayerRemote.moveSong(fromPosition, toPosition)
}
override fun onCheckCanDrop(draggingPosition: Int, dropPosition: Int): Boolean {
return true
}
override fun onItemDragStarted(position: Int) {
notifyDataSetChanged()
}
override fun onItemDragFinished(fromPosition: Int, toPosition: Int, result: Boolean) {
notifyDataSetChanged()
}
inner class ViewHolder(itemView: View) : SongAdapter.ViewHolder(itemView), DraggableItemViewHolder {
@DraggableItemStateFlags
private var mDragStateFlags: Int = 0
override var songMenuRes: Int
get() = R.menu.menu_item_playing_queue_song
set(value: Int) {
super.songMenuRes = value
}
init {
if (imageText != null) {
imageText!!.visibility = View.VISIBLE
}
if (dragView != null) {
dragView!!.visibility = View.VISIBLE
}
}
override fun onSongMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_remove_from_playing_queue -> {
MusicPlayerRemote.removeFromQueue(adapterPosition)
return true
}
}
return super.onSongMenuItemClick(item)
}
@DraggableItemStateFlags
override fun getDragStateFlags(): Int {
return mDragStateFlags
}
override fun setDragStateFlags(@DraggableItemStateFlags flags: Int) {
mDragStateFlags = flags
}
}
companion object {
private const val HISTORY = 0
private const val CURRENT = 1
private const val UP_NEXT = 2
}
}

View file

@ -0,0 +1,84 @@
package code.name.monkey.retromusic.adapter.song
import android.view.MenuItem
import android.view.View
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.core.util.Pair
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import java.util.*
open class PlaylistSongAdapter(activity: AppCompatActivity, dataSet: ArrayList<Song>, @LayoutRes itemLayoutRes: Int, usePalette: Boolean, cabHolder: CabHolder?) : AbsOffsetSongAdapter(activity, dataSet, itemLayoutRes, usePalette, cabHolder, false) {
init {
this.setMultiSelectMenuRes(R.menu.menu_cannot_delete_single_songs_playlist_songs_selection)
}
override fun createViewHolder(view: View): SongAdapter.ViewHolder {
return ViewHolder(view)
}
override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) {
if (holder.itemViewType == AbsOffsetSongAdapter.OFFSET_ITEM) {
val textColor = ThemeStore.textColorSecondary(activity)
if (holder.title != null) {
holder.title!!.text = MusicUtil.getPlaylistInfoString(activity, dataSet)
holder.title!!.setTextColor(textColor)
}
if (holder.text != null) {
holder.text!!.visibility = View.GONE
}
if (holder.menu != null) {
holder.menu!!.visibility = View.GONE
}
if (holder.image != null) {
val padding = activity.resources.getDimensionPixelSize(R.dimen.default_item_margin) / 2
holder.image!!.setPadding(padding, padding, padding, padding)
holder.image!!.setColorFilter(textColor)
holder.image!!.setImageResource(R.drawable.ic_timer_white_24dp)
}
if (holder.dragView != null) {
holder.dragView!!.visibility = View.GONE
}
if (holder.separator != null) {
holder.separator!!.visibility = View.GONE
}
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.GONE
}
} else {
super.onBindViewHolder(holder, position - 1)
}
}
open inner class ViewHolder(itemView: View) : AbsOffsetSongAdapter.ViewHolder(itemView) {
override var songMenuRes: Int
get() = R.menu.menu_item_cannot_delete_single_songs_playlist_song
set(value) {
super.songMenuRes = value
}
override fun onSongMenuItemClick(item: MenuItem): Boolean {
if (item.itemId == R.id.action_go_to_album) {
val albumPairs = arrayOf<Pair<*, *>>(Pair.create(image, activity.getString(R.string.transition_album_art)))
NavigationUtil.goToAlbum(activity, dataSet[adapterPosition - 1].albumId, *albumPairs)
return true
}
return super.onSongMenuItemClick(item)
}
}
companion object {
val TAG = PlaylistSongAdapter::class.java.simpleName
}
}

View file

@ -0,0 +1,64 @@
package code.name.monkey.retromusic.adapter.song
import android.view.View
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Song
import java.util.*
class ShuffleButtonSongAdapter(activity: AppCompatActivity,
dataSet: ArrayList<Song>,
@LayoutRes itemLayoutRes: Int,
usePalette: Boolean,
cabHolder: CabHolder?) : AbsOffsetSongAdapter(activity, dataSet, itemLayoutRes, usePalette, cabHolder) {
override fun createViewHolder(view: View): SongAdapter.ViewHolder {
return ViewHolder(view)
}
override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) {
if (holder.itemViewType == AbsOffsetSongAdapter.OFFSET_ITEM) {
val accentColor = ThemeStore.accentColor(activity.applicationContext)
if (holder.title != null) {
holder.title!!.text = activity.resources.getString(R.string.action_shuffle_all)
holder.title!!.setTextColor(accentColor)
}
if (holder.text != null) {
holder.text!!.visibility = View.GONE
}
if (holder.menu != null) {
holder.menu!!.visibility = View.GONE
}
if (holder.image != null) {
val padding = activity.resources.getDimensionPixelSize(R.dimen.default_item_margin) / 2
holder.image!!.setPadding(padding, padding, padding, padding)
holder.image!!.setColorFilter(accentColor)
holder.image!!.setImageResource(R.drawable.ic_shuffle_white_24dp)
}
if (holder.separator != null) {
holder.separator!!.visibility = View.GONE
}
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.GONE
}
} else {
super.onBindViewHolder(holder, position - 1)
}
}
inner class ViewHolder(itemView: View) : AbsOffsetSongAdapter.ViewHolder(itemView) {
override fun onClick(v: View?) {
if (itemViewType == AbsOffsetSongAdapter.OFFSET_ITEM) {
MusicPlayerRemote.openAndShuffleQueue(dataSet, true)
return
}
super.onClick(v)
}
}
}

View file

@ -0,0 +1,68 @@
package code.name.monkey.retromusic.adapter.song
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import java.util.*
class SimpleSongAdapter(context: AppCompatActivity,
songs: ArrayList<Song>,
@LayoutRes i: Int,
val useNumbers: Boolean) : SongAdapter(context, songs, i, false, null) {
private var textColor: Int = 0
init {
textColor = ThemeStore.textColorPrimary(context)
}
override fun swapDataSet(dataSet: ArrayList<Song>) {
this.dataSet.clear()
this.dataSet = dataSet
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
super.onBindViewHolder(holder, position)
val fixedTrackNumber = MusicUtil.getFixedTrackNumber(dataSet[position].trackNumber)
if (holder.imageText != null) {
if (useNumbers) {
holder.imageText!!.text = (position + 1).toString()
} else {
holder.imageText!!.text = if (fixedTrackNumber > 0) fixedTrackNumber.toString() else "-"
}
holder.imageText!!.setTextColor(textColor)
}
if (holder.time != null) {
holder.time!!.text = MusicUtil.getReadableDurationString(dataSet[position].duration)
holder.time!!.setTextColor(textColor)
}
if (holder.title != null) {
holder.title!!.setTextColor(textColor)
}
if (holder.menu != null) {
TintHelper.setTintAuto(holder.menu!!, textColor, false)
}
}
override fun getItemCount(): Int {
return dataSet.size
}
fun setTextColor(textColor: Int) {
this.textColor = textColor
notifyDataSetChanged()
}
}

View file

@ -0,0 +1,232 @@
package code.name.monkey.retromusic.adapter.song
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.core.util.Pair
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.helper.menu.SongMenuHelper
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import com.afollestad.materialcab.MaterialCab
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
import java.util.*
/**
* Created by hemanths on 13/08/17.
*/
open class SongAdapter @JvmOverloads constructor(protected val activity: AppCompatActivity, dataSet: ArrayList<Song>,
@param:LayoutRes protected var itemLayoutRes: Int, usePalette: Boolean, cabHolder: CabHolder?,
showSectionName: Boolean = true) : AbsMultiSelectAdapter<SongAdapter.ViewHolder, Song>(activity, cabHolder, R.menu.menu_media_selection), MaterialCab.Callback, FastScrollRecyclerView.SectionedAdapter {
var dataSet: ArrayList<Song>
protected var usePalette = false
private var showSectionName = true
init {
this.dataSet = dataSet
this.usePalette = usePalette
this.showSectionName = showSectionName
this.setHasStableIds(true)
}
open fun swapDataSet(dataSet: ArrayList<Song>) {
this.dataSet = dataSet
notifyDataSetChanged()
}
open fun usePalette(usePalette: Boolean) {
this.usePalette = usePalette
notifyDataSetChanged()
}
override fun getItemId(position: Int): Long {
return dataSet[position].id.toLong()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false)
return createViewHolder(view)
}
protected open fun createViewHolder(view: View): ViewHolder {
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val song = dataSet[position]
val isChecked = isChecked(song)
holder.itemView.isActivated = isChecked
if (holder.adapterPosition == itemCount - 1) {
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.GONE
}
} else {
if (holder.shortSeparator != null) {
holder.shortSeparator!!.visibility = View.GONE
}
}
if (holder.title != null) {
holder.title!!.text = getSongTitle(song)
}
if (holder.text != null) {
holder.text!!.text = getSongText(song)
}
loadAlbumCover(song, holder)
}
private fun setColors(color: Int, holder: ViewHolder) {
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer!!.setBackgroundColor(color)
if (holder.title != null) {
holder.title!!.setTextColor(MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)))
}
if (holder.text != null) {
holder.text!!.setTextColor(MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)))
}
}
}
protected open fun loadAlbumCover(song: Song, holder: ViewHolder) {
if (holder.image == null) {
return
}
GlideApp.with(activity).asBitmapPalette()
.load(RetroGlideExtension.getSongModel(song))
.transition(RetroGlideExtension.getDefaultTransition())
.songOptions(song)
.into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(color: Int) {
setColors(color, holder)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
setColors(defaultFooterColor, holder)
}
})
}
private fun getSongTitle(song: Song): String? {
return song.title
}
private fun getSongText(song: Song): String? {
return song.artistName
}
override fun getItemCount(): Int {
return dataSet.size
}
override fun getIdentifier(position: Int): Song? {
return dataSet[position]
}
override fun getName(song: Song): String {
return song.title
}
override fun onMultipleItemAction(menuItem: MenuItem,
selection: ArrayList<Song>) {
SongsMenuHelper.handleMenuClick(activity, selection, menuItem.itemId)
}
override fun getSectionName(position: Int): String {
if (!showSectionName) {
return ""
}
val sectionName: String? = when (PreferenceUtil.getInstance().songSortOrder) {
SortOrder.SongSortOrder.SONG_A_Z, SortOrder.SongSortOrder.SONG_Z_A -> dataSet[position].title
SortOrder.SongSortOrder.SONG_ALBUM -> dataSet[position].albumName
SortOrder.SongSortOrder.SONG_ARTIST -> dataSet[position].artistName
SortOrder.SongSortOrder.SONG_YEAR -> return MusicUtil.getYearString(dataSet[position].year)
SortOrder.SongSortOrder.COMPOSER -> dataSet[position].composer
else -> {
return ""
}
}
return MusicUtil.getSectionName(sectionName)
}
open inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
protected open var songMenuRes = SongMenuHelper.MENU_RES
protected open val song: Song
get() = dataSet[adapterPosition]
init {
setImageTransitionName(activity.getString(R.string.transition_album_art))
if (menu != null) {
menu!!.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
override val song: Song
get() = this@ViewHolder.song
override val menuRes: Int
get() = songMenuRes
override fun onMenuItemClick(item: MenuItem): Boolean {
return onSongMenuItemClick(item) || super.onMenuItemClick(item)
}
})
}
}
protected open fun onSongMenuItemClick(item: MenuItem): Boolean {
if (image != null && image!!.visibility == View.VISIBLE) {
when (item.itemId) {
R.id.action_go_to_album -> {
val albumPairs = arrayOf<Pair<*, *>>(Pair.create(imageContainer,
activity.resources.getString(R.string.transition_album_art)))
NavigationUtil.goToAlbum(activity, song.albumId, *albumPairs)
return true
}
}
}
return false
}
override fun onClick(v: View?) {
if (isInQuickSelectMode) {
toggleChecked(adapterPosition)
} else {
MusicPlayerRemote.openQueue(dataSet, adapterPosition, true)
}
}
override fun onLongClick(v: View?): Boolean {
return toggleChecked(adapterPosition)
}
}
companion object {
val TAG: String = SongAdapter::class.java.simpleName
}
}