PlayerAndroid/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumCoverPagerAdapter.kt

222 lines
8.4 KiB
Kotlin

/*
* Copyright (c) 2020 Hemanth Savarla.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*/
package code.name.monkey.retromusic.adapter.album
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.app.ActivityOptionsCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.LyricsActivity
import code.name.monkey.retromusic.fragments.AlbumCoverStyle
import code.name.monkey.retromusic.fragments.NowPlayingScreen.*
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.misc.CustomFragmentStatePagerAdapter
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class AlbumCoverPagerAdapter(
fragmentManager: FragmentManager,
private val dataSet: List<Song>
) : CustomFragmentStatePagerAdapter(fragmentManager) {
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() {
private lateinit var albumCover: ImageView
private var isColorReady: Boolean = false
private lateinit var color: MediaNotificationProcessor
private lateinit var song: Song
private var colorReceiver: ColorReceiver? = null
private var request: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments != null) {
song = requireArguments().getParcelable(SONG_ARG)!!
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(getLayoutWithPlayerTheme(), container, false)
albumCover = view.findViewById(R.id.player_image)
albumCover.setOnClickListener {
val intent = Intent(requireContext(), LyricsActivity::class.java)
val activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
requireActivity(),
it,
"lyrics"
)
startActivity(intent, activityOptions.toBundle())
}
return view
}
private fun showLyricsDialog() {
lifecycleScope.launch(Dispatchers.IO) {
val data: String? = MusicUtil.getLyrics(song)
withContext(Dispatchers.Main) {
MaterialAlertDialogBuilder(
requireContext(),
R.style.ThemeOverlay_MaterialComponents_Dialog_Alert
).apply {
setTitle(song.title)
setMessage(if (data.isNullOrEmpty()) "No lyrics found" else data)
setNegativeButton(R.string.synced_lyrics) { _, _ ->
NavigationUtil.goToLyrics(requireActivity())
}
show()
}
}
}
}
private fun getLayoutWithPlayerTheme(): Int {
return when (PreferenceUtil.nowPlayingScreen) {
Card, Fit, Tiny, Classic, Gradient, Full -> R.layout.fragment_album_full_cover
else -> {
if (PreferenceUtil.isCarouselEffect) {
R.layout.fragment_album_carousel_cover
} else {
when (PreferenceUtil.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.FullCard -> R.layout.fragment_album_full_card_cover
}
}
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
loadAlbumCover()
}
override fun onDestroyView() {
super.onDestroyView()
colorReceiver = null
}
private fun loadAlbumCover() {
SongGlideRequest.Builder.from(Glide.with(requireContext()), song)
.checkIgnoreMediaStore(requireContext())
.generatePalette(requireContext()).build()
.into(object : RetroMusicColoredTarget(albumCover) {
override fun onColorReady(colors: MediaNotificationProcessor) {
setColor(colors)
}
})
}
private fun setColor(color: MediaNotificationProcessor) {
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: MediaNotificationProcessor, 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
}
}