Otter-App-Android-Funkwhale/app/src/main/java/com/github/apognu/otter/fragments/TracksFragment.kt

229 lines
7.0 KiB
Kotlin
Raw Normal View History

2019-08-19 16:50:33 +02:00
package com.github.apognu.otter.fragments
import android.os.Bundle
2020-06-13 16:45:58 +02:00
import android.view.Gravity
2019-08-19 16:50:33 +02:00
import android.view.View
import androidx.appcompat.app.AppCompatDelegate
2020-06-13 16:45:58 +02:00
import androidx.appcompat.widget.PopupMenu
2019-08-19 16:50:33 +02:00
import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
2019-08-19 16:50:33 +02:00
import androidx.recyclerview.widget.RecyclerView
import com.github.apognu.otter.R
import com.github.apognu.otter.adapters.TracksAdapter
import com.github.apognu.otter.repositories.FavoritedRepository
2019-08-19 16:50:33 +02:00
import com.github.apognu.otter.repositories.FavoritesRepository
import com.github.apognu.otter.repositories.TracksRepository
import com.github.apognu.otter.utils.*
import com.google.android.exoplayer2.offline.Download
import com.preference.PowerPreference
2019-08-19 16:50:33 +02:00
import com.squareup.picasso.Picasso
2020-06-14 00:42:45 +02:00
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
2019-08-19 16:50:33 +02:00
import kotlinx.android.synthetic.main.fragment_tracks.*
import kotlinx.coroutines.Dispatchers.IO
2019-08-19 16:50:33 +02:00
import kotlinx.coroutines.Dispatchers.Main
2019-10-31 16:17:37 +01:00
import kotlinx.coroutines.flow.collect
2019-08-19 16:50:33 +02:00
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
2019-08-19 16:50:33 +02:00
class TracksFragment : OtterFragment<Track, TracksAdapter>() {
2019-08-19 16:50:33 +02:00
override val viewRes = R.layout.fragment_tracks
override val recycler: RecyclerView get() = tracks
lateinit var favoritesRepository: FavoritesRepository
lateinit var favoritedRepository: FavoritedRepository
2019-08-19 16:50:33 +02:00
2019-10-21 11:51:32 +02:00
private var albumId = 0
private var albumArtist = ""
private var albumTitle = ""
private var albumCover = ""
2019-08-19 16:50:33 +02:00
companion object {
fun new(album: Album): TracksFragment {
return TracksFragment().apply {
arguments = bundleOf(
"albumId" to album.id,
"albumArtist" to album.artist.name,
"albumTitle" to album.title,
2020-08-08 14:51:39 +02:00
"albumCover" to album.cover()
2019-08-19 16:50:33 +02:00
)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.apply {
albumId = getInt("albumId")
albumArtist = getString("albumArtist") ?: ""
albumTitle = getString("albumTitle") ?: ""
albumCover = getString("albumCover") ?: ""
}
adapter = TracksAdapter(context, FavoriteListener())
repository = TracksRepository(context, albumId)
favoritesRepository = FavoritesRepository(context)
favoritedRepository = FavoritedRepository(context)
2019-08-19 16:50:33 +02:00
watchEventBus()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Picasso.get()
2019-10-22 21:56:33 +02:00
.maybeLoad(maybeNormalizeUrl(albumCover))
2019-08-19 16:50:33 +02:00
.noFade()
.fit()
.centerCrop()
2020-06-14 00:42:45 +02:00
.transform(RoundedCornersTransformation(16, 0))
2019-08-19 16:50:33 +02:00
.into(cover)
artist.text = albumArtist
title.text = albumTitle
}
override fun onResume() {
super.onResume()
lifecycleScope.launch(Main) {
2019-08-19 16:50:33 +02:00
RequestBus.send(Request.GetCurrentTrack).wait<Response.CurrentTrack>()?.let { response ->
adapter.currentTrack = response.track
adapter.notifyDataSetChanged()
2019-08-19 16:50:33 +02:00
}
refreshDownloadedTracks()
2019-08-19 16:50:33 +02:00
}
var coverHeight: Float? = null
scroller.setOnScrollChangeListener { _: View?, _: Int, scrollY: Int, _: Int, _: Int ->
if (coverHeight == null) {
coverHeight = cover.measuredHeight.toFloat()
}
cover.translationY = (scrollY / 2).toFloat()
coverHeight?.let { height ->
cover.alpha = (height - scrollY.toFloat()) / height
}
}
when (PowerPreference.getDefaultFile().getString("play_order")) {
"in_order" -> play.text = getString(R.string.playback_play)
else -> play.text = getString(R.string.playback_shuffle)
}
2019-08-19 16:50:33 +02:00
play.setOnClickListener {
when (PowerPreference.getDefaultFile().getString("play_order")) {
"in_order" -> CommandBus.send(Command.ReplaceQueue(adapter.data))
else -> CommandBus.send(Command.ReplaceQueue(adapter.data.shuffled()))
}
2019-08-19 16:50:33 +02:00
context.toast("All tracks were added to your queue")
}
2020-06-13 16:45:58 +02:00
context?.let { context ->
actions.setOnClickListener {
PopupMenu(context, actions, Gravity.START, R.attr.actionOverflowMenuStyle, 0).apply {
inflate(R.menu.album)
2019-08-19 16:50:33 +02:00
menu.findItem(R.id.play_secondary)?.let { item ->
when (PowerPreference.getDefaultFile().getString("play_order")) {
"in_order" -> item.title = getString(R.string.playback_shuffle)
else -> item.title = getString(R.string.playback_play)
}
}
2020-06-13 16:45:58 +02:00
setOnMenuItemClickListener {
when (it.itemId) {
R.id.play_secondary -> when (PowerPreference.getDefaultFile().getString("play_order")) {
"in_order" -> CommandBus.send(Command.ReplaceQueue(adapter.data.shuffled()))
else -> CommandBus.send(Command.ReplaceQueue(adapter.data))
}
2020-06-13 16:45:58 +02:00
R.id.add_to_queue -> {
when (PowerPreference.getDefaultFile().getString("play_order")) {
"in_order" -> CommandBus.send(Command.AddToQueue(adapter.data))
else -> CommandBus.send(Command.AddToQueue(adapter.data.shuffled()))
}
2020-06-13 16:45:58 +02:00
context.toast("All tracks were added to your queue")
}
R.id.download -> CommandBus.send(Command.PinTracks(adapter.data))
}
true
}
show()
}
}
2019-08-19 16:50:33 +02:00
}
}
private fun watchEventBus() {
lifecycleScope.launch(IO) {
2019-10-31 16:17:37 +01:00
EventBus.get().collect { message ->
2019-08-19 16:50:33 +02:00
when (message) {
is Event.DownloadChanged -> refreshDownloadedTrack(message.download)
}
}
}
lifecycleScope.launch(Main) {
CommandBus.get().collect { command ->
when (command) {
is Command.RefreshTrack -> refreshCurrentTrack(command.track)
}
}
}
}
private suspend fun refreshDownloadedTracks() {
val downloaded = TracksRepository.getDownloadedIds() ?: listOf()
withContext(Main) {
adapter.data = adapter.data.map {
it.downloaded = downloaded.contains(it.id)
it
}.toMutableList()
adapter.notifyDataSetChanged()
}
}
private suspend fun refreshDownloadedTrack(download: Download) {
if (download.state == Download.STATE_COMPLETED) {
download.getMetadata()?.let { info ->
adapter.data.withIndex().associate { it.value to it.index }.filter { it.key.id == info.id }.toList().getOrNull(0)?.let { match ->
withContext(Main) {
adapter.data[match.second].downloaded = true
adapter.notifyItemChanged(match.second)
}
2019-08-19 16:50:33 +02:00
}
}
}
}
private fun refreshCurrentTrack(track: Track?) {
track?.let {
adapter.currentTrack?.current = false
adapter.currentTrack = track.apply {
current = true
}
adapter.notifyDataSetChanged()
}
}
2019-08-19 16:50:33 +02:00
inner class FavoriteListener : TracksAdapter.OnFavoriteListener {
override fun onToggleFavorite(id: Int, state: Boolean) {
when (state) {
true -> favoritesRepository.addFavorite(id)
false -> favoritesRepository.deleteFavorite(id)
}
}
}
}