2021-07-12 10:14:26 +02:00
|
|
|
package audio.funkwhale.ffa.activities
|
2019-08-19 16:50:33 +02:00
|
|
|
|
|
|
|
import android.animation.Animator
|
|
|
|
import android.animation.AnimatorListenerAdapter
|
2019-10-24 12:35:34 +02:00
|
|
|
import android.animation.ObjectAnimator
|
2019-08-19 16:50:33 +02:00
|
|
|
import android.annotation.SuppressLint
|
|
|
|
import android.content.Intent
|
2019-11-05 21:23:29 +01:00
|
|
|
import android.graphics.Bitmap
|
2020-07-10 17:18:29 +02:00
|
|
|
import android.os.Build
|
2019-08-19 16:50:33 +02:00
|
|
|
import android.os.Bundle
|
2019-11-05 21:23:29 +01:00
|
|
|
import android.util.DisplayMetrics
|
|
|
|
import android.view.*
|
2019-10-24 12:35:34 +02:00
|
|
|
import android.view.animation.AccelerateDecelerateInterpolator
|
2019-08-19 16:50:33 +02:00
|
|
|
import android.widget.SeekBar
|
|
|
|
import androidx.appcompat.app.AppCompatActivity
|
2020-05-29 21:40:01 +02:00
|
|
|
import androidx.appcompat.widget.PopupMenu
|
2020-05-29 23:42:03 +02:00
|
|
|
import androidx.core.content.ContextCompat
|
2019-11-05 21:23:29 +01:00
|
|
|
import androidx.core.graphics.drawable.toDrawable
|
2019-08-19 16:50:33 +02:00
|
|
|
import androidx.fragment.app.DialogFragment
|
|
|
|
import androidx.fragment.app.Fragment
|
|
|
|
import androidx.fragment.app.FragmentManager
|
2020-09-04 16:56:31 +02:00
|
|
|
import androidx.lifecycle.Lifecycle
|
2020-06-25 01:26:15 +02:00
|
|
|
import androidx.lifecycle.lifecycleScope
|
2021-07-21 09:11:07 +02:00
|
|
|
import audio.funkwhale.ffa.FFA
|
2021-07-16 10:03:52 +02:00
|
|
|
import audio.funkwhale.ffa.R
|
|
|
|
import audio.funkwhale.ffa.databinding.ActivityMainBinding
|
|
|
|
import audio.funkwhale.ffa.fragments.*
|
|
|
|
import audio.funkwhale.ffa.playback.MediaControlsManager
|
|
|
|
import audio.funkwhale.ffa.playback.PinService
|
|
|
|
import audio.funkwhale.ffa.playback.PlayerService
|
|
|
|
import audio.funkwhale.ffa.repositories.FavoritedRepository
|
|
|
|
import audio.funkwhale.ffa.repositories.FavoritesRepository
|
|
|
|
import audio.funkwhale.ffa.repositories.Repository
|
|
|
|
import audio.funkwhale.ffa.utils.*
|
|
|
|
import audio.funkwhale.ffa.views.DisableableFrameLayout
|
2020-06-01 16:31:58 +02:00
|
|
|
import com.github.kittinunf.fuel.Fuel
|
|
|
|
import com.github.kittinunf.fuel.coroutines.awaitStringResponse
|
2020-05-29 23:42:03 +02:00
|
|
|
import com.google.android.exoplayer2.Player
|
2020-06-13 16:09:48 +02:00
|
|
|
import com.google.android.exoplayer2.offline.DownloadService
|
2020-06-01 16:31:58 +02:00
|
|
|
import com.google.gson.Gson
|
2019-08-19 16:50:33 +02:00
|
|
|
import com.preference.PowerPreference
|
|
|
|
import com.squareup.picasso.Picasso
|
2020-06-14 00:42:45 +02:00
|
|
|
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
|
2020-06-25 01:26:15 +02:00
|
|
|
import kotlinx.coroutines.Dispatchers.Default
|
2019-08-19 16:50:33 +02:00
|
|
|
import kotlinx.coroutines.Dispatchers.IO
|
|
|
|
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
|
2019-11-05 21:23:29 +01:00
|
|
|
import kotlinx.coroutines.withContext
|
2019-08-19 16:50:33 +02:00
|
|
|
|
|
|
|
class MainActivity : AppCompatActivity() {
|
2019-10-23 20:21:18 +02:00
|
|
|
enum class ResultCode(val code: Int) {
|
|
|
|
LOGOUT(1001)
|
|
|
|
}
|
|
|
|
|
2019-08-19 16:50:33 +02:00
|
|
|
private val favoriteRepository = FavoritesRepository(this)
|
2020-07-11 16:56:09 +02:00
|
|
|
private val favoritedRepository = FavoritedRepository(this)
|
2020-09-03 12:09:56 +02:00
|
|
|
private var menu: Menu? = null
|
2019-08-19 16:50:33 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
private lateinit var binding: ActivityMainBinding
|
|
|
|
|
2019-08-19 16:50:33 +02:00
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
|
|
|
|
AppContext.init(this)
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
|
|
|
|
|
|
|
setContentView(binding.root)
|
|
|
|
|
|
|
|
setSupportActionBar(binding.appbar)
|
2019-08-19 16:50:33 +02:00
|
|
|
|
|
|
|
when (intent.action) {
|
|
|
|
MediaControlsManager.NOTIFICATION_ACTION_OPEN_QUEUE.toString() -> launchDialog(QueueFragment())
|
|
|
|
}
|
|
|
|
|
|
|
|
supportFragmentManager
|
|
|
|
.beginTransaction()
|
|
|
|
.replace(R.id.container, BrowseFragment())
|
|
|
|
.commit()
|
2020-06-20 22:10:13 +02:00
|
|
|
|
2020-06-25 01:26:15 +02:00
|
|
|
watchEventBus()
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onResume() {
|
|
|
|
super.onResume()
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
(binding.container as? DisableableFrameLayout)?.setShouldRegisterTouch { _ ->
|
|
|
|
if (binding.nowPlaying.isOpened()) {
|
|
|
|
binding.nowPlaying.close()
|
2020-07-12 19:05:51 +02:00
|
|
|
|
|
|
|
return@setShouldRegisterTouch false
|
2020-07-12 18:55:52 +02:00
|
|
|
}
|
2020-07-12 19:05:51 +02:00
|
|
|
|
|
|
|
true
|
2020-07-12 18:55:52 +02:00
|
|
|
}
|
|
|
|
|
2020-07-11 16:56:09 +02:00
|
|
|
favoritedRepository.update(this, lifecycleScope)
|
2020-07-10 15:08:08 +02:00
|
|
|
|
2019-10-31 00:46:35 +01:00
|
|
|
startService(Intent(this, PlayerService::class.java))
|
2020-06-13 16:09:48 +02:00
|
|
|
DownloadService.start(this, PinService::class.java)
|
2019-10-31 00:46:35 +01:00
|
|
|
|
2020-06-25 01:26:15 +02:00
|
|
|
CommandBus.send(Command.RefreshService)
|
|
|
|
|
|
|
|
lifecycleScope.launch(IO) {
|
2020-06-21 13:36:42 +02:00
|
|
|
Userinfo.get()
|
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
with(binding) {
|
2019-08-19 16:50:33 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
nowPlayingContainer?.nowPlayingToggle?.setOnClickListener {
|
|
|
|
CommandBus.send(Command.ToggleState)
|
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
nowPlayingContainer?.nowPlayingNext?.setOnClickListener {
|
|
|
|
CommandBus.send(Command.NextTrack)
|
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
nowPlayingContainer?.nowPlayingDetailsPrevious?.setOnClickListener {
|
|
|
|
CommandBus.send(Command.PreviousTrack)
|
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
nowPlayingContainer?.nowPlayingDetailsNext?.setOnClickListener {
|
|
|
|
CommandBus.send(Command.NextTrack)
|
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
nowPlayingContainer?.nowPlayingDetailsToggle?.setOnClickListener {
|
|
|
|
CommandBus.send(Command.ToggleState)
|
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsProgress?.setOnSeekBarChangeListener(object :
|
|
|
|
SeekBar.OnSeekBarChangeListener {
|
|
|
|
override fun onStopTrackingTouch(view: SeekBar?) {}
|
2019-08-19 16:50:33 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
override fun onStartTrackingTouch(view: SeekBar?) {}
|
|
|
|
|
|
|
|
override fun onProgressChanged(view: SeekBar?, progress: Int, fromUser: Boolean) {
|
|
|
|
if (fromUser) {
|
|
|
|
CommandBus.send(Command.Seek(progress))
|
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
2021-07-16 10:03:52 +02:00
|
|
|
})
|
2019-11-05 21:23:29 +01:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
landscapeQueue?.let {
|
|
|
|
supportFragmentManager.beginTransaction()
|
|
|
|
.replace(R.id.landscape_queue, LandscapeQueueFragment()).commit()
|
|
|
|
}
|
2019-11-05 21:23:29 +01:00
|
|
|
}
|
2020-06-20 15:42:10 +02:00
|
|
|
}
|
|
|
|
|
2019-08-19 16:50:33 +02:00
|
|
|
override fun onBackPressed() {
|
2021-07-16 10:03:52 +02:00
|
|
|
if (binding.nowPlaying.isOpened()) {
|
|
|
|
binding.nowPlaying.close()
|
2019-08-19 16:50:33 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
super.onBackPressed()
|
|
|
|
}
|
|
|
|
|
2020-09-03 12:09:56 +02:00
|
|
|
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
|
|
|
|
this.menu = menu
|
|
|
|
|
|
|
|
return super.onPrepareOptionsMenu(menu)
|
|
|
|
}
|
|
|
|
|
2019-08-19 16:50:33 +02:00
|
|
|
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
|
|
|
menuInflater.inflate(R.menu.toolbar, menu)
|
|
|
|
|
2020-09-03 22:53:06 +02:00
|
|
|
menu?.findItem(R.id.nav_all_music)?.let {
|
|
|
|
it.isChecked = Settings.getScopes().contains("all")
|
|
|
|
it.isEnabled = !it.isChecked
|
|
|
|
}
|
|
|
|
|
2020-09-03 12:09:56 +02:00
|
|
|
menu?.findItem(R.id.nav_my_music)?.isChecked = Settings.getScopes().contains("me")
|
|
|
|
menu?.findItem(R.id.nav_followed)?.isChecked = Settings.getScopes().contains("subscribed")
|
2020-06-13 18:34:28 +02:00
|
|
|
|
2019-08-19 16:50:33 +02:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
|
|
when (item.itemId) {
|
|
|
|
android.R.id.home -> {
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlaying.close()
|
2019-08-19 16:50:33 +02:00
|
|
|
|
|
|
|
(supportFragmentManager.fragments.last() as? BrowseFragment)?.let {
|
|
|
|
it.selectTabAt(0)
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
launchFragment(BrowseFragment())
|
|
|
|
}
|
|
|
|
|
|
|
|
R.id.nav_queue -> launchDialog(QueueFragment())
|
|
|
|
R.id.nav_search -> startActivity(Intent(this, SearchActivity::class.java))
|
2020-09-03 12:09:56 +02:00
|
|
|
R.id.nav_all_music, R.id.nav_my_music, R.id.nav_followed -> {
|
|
|
|
menu?.let { menu ->
|
|
|
|
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW)
|
|
|
|
item.actionView = View(this)
|
|
|
|
item.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
|
|
|
|
override fun onMenuItemActionExpand(item: MenuItem?) = false
|
|
|
|
override fun onMenuItemActionCollapse(item: MenuItem?) = false
|
|
|
|
})
|
2020-06-13 18:34:28 +02:00
|
|
|
|
2020-09-03 12:09:56 +02:00
|
|
|
item.isChecked = !item.isChecked
|
|
|
|
|
|
|
|
val scopes = Settings.getScopes().toMutableSet()
|
|
|
|
|
|
|
|
val new = when (item.itemId) {
|
|
|
|
R.id.nav_my_music -> "me"
|
|
|
|
R.id.nav_followed -> "subscribed"
|
|
|
|
|
|
|
|
else -> {
|
2020-09-03 22:53:06 +02:00
|
|
|
menu.findItem(R.id.nav_all_music).isEnabled = false
|
2020-09-03 12:09:56 +02:00
|
|
|
menu.findItem(R.id.nav_my_music).isChecked = false
|
|
|
|
menu.findItem(R.id.nav_followed).isChecked = false
|
2021-07-01 13:25:09 +02:00
|
|
|
PowerPreference.getDefaultFile().setString("scope", "all")
|
2020-09-03 12:09:56 +02:00
|
|
|
EventBus.send(Event.ListingsChanged)
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-03 22:53:06 +02:00
|
|
|
menu.findItem(R.id.nav_all_music).let {
|
|
|
|
it.isChecked = false
|
|
|
|
it.isEnabled = true
|
|
|
|
}
|
2020-09-03 12:09:56 +02:00
|
|
|
|
|
|
|
scopes.remove("all")
|
|
|
|
|
|
|
|
when (item.isChecked) {
|
|
|
|
true -> scopes.add(new)
|
|
|
|
false -> scopes.remove(new)
|
|
|
|
}
|
|
|
|
|
2020-09-03 22:53:06 +02:00
|
|
|
if (scopes.isEmpty()) {
|
|
|
|
menu.findItem(R.id.nav_all_music).let {
|
|
|
|
it.isChecked = true
|
|
|
|
it.isEnabled = false
|
|
|
|
}
|
|
|
|
|
|
|
|
scopes.add("all")
|
|
|
|
}
|
|
|
|
|
2021-07-01 13:25:09 +02:00
|
|
|
PowerPreference.getDefaultFile().setString("scope", scopes.joinToString(","))
|
2020-09-03 12:09:56 +02:00
|
|
|
EventBus.send(Event.ListingsChanged)
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
2020-06-13 18:34:28 +02:00
|
|
|
}
|
2020-06-13 16:09:48 +02:00
|
|
|
R.id.nav_downloads -> startActivity(Intent(this, DownloadsActivity::class.java))
|
2019-10-23 20:21:18 +02:00
|
|
|
R.id.settings -> startActivityForResult(Intent(this, SettingsActivity::class.java), 0)
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2019-10-23 20:21:18 +02:00
|
|
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
|
|
super.onActivityResult(requestCode, resultCode, data)
|
|
|
|
|
|
|
|
if (resultCode == ResultCode.LOGOUT.code) {
|
|
|
|
Intent(this, LoginActivity::class.java).apply {
|
2021-07-21 09:11:07 +02:00
|
|
|
FFA.get().deleteAllData()
|
2020-08-29 15:14:59 +02:00
|
|
|
|
2021-07-01 13:25:09 +02:00
|
|
|
flags =
|
|
|
|
Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
2019-10-23 20:21:18 +02:00
|
|
|
|
2020-07-11 21:05:19 +02:00
|
|
|
stopService(Intent(this@MainActivity, PlayerService::class.java))
|
2019-10-23 20:21:18 +02:00
|
|
|
startActivity(this)
|
|
|
|
finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-19 16:50:33 +02:00
|
|
|
private fun launchFragment(fragment: Fragment) {
|
|
|
|
supportFragmentManager.fragments.lastOrNull()?.also { oldFragment ->
|
|
|
|
oldFragment.enterTransition = null
|
|
|
|
oldFragment.exitTransition = null
|
|
|
|
|
|
|
|
supportFragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
|
|
|
}
|
|
|
|
|
|
|
|
supportFragmentManager
|
|
|
|
.beginTransaction()
|
|
|
|
.setCustomAnimations(0, 0, 0, 0)
|
|
|
|
.replace(R.id.container, fragment)
|
|
|
|
.commit()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun launchDialog(fragment: DialogFragment) {
|
|
|
|
supportFragmentManager.beginTransaction().let {
|
|
|
|
fragment.show(it, "")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressLint("NewApi")
|
|
|
|
private fun watchEventBus() {
|
2020-06-25 01:26:15 +02:00
|
|
|
lifecycleScope.launch(Main) {
|
2019-10-31 16:17:37 +01:00
|
|
|
EventBus.get().collect { message ->
|
2019-08-19 16:50:33 +02:00
|
|
|
when (message) {
|
|
|
|
is Event.LogOut -> {
|
2021-07-21 09:11:07 +02:00
|
|
|
FFA.get().deleteAllData()
|
2020-08-08 14:51:39 +02:00
|
|
|
|
2019-08-19 16:50:33 +02:00
|
|
|
startActivity(Intent(this@MainActivity, LoginActivity::class.java).apply {
|
|
|
|
flags = Intent.FLAG_ACTIVITY_NO_HISTORY
|
|
|
|
})
|
|
|
|
|
|
|
|
finish()
|
|
|
|
}
|
|
|
|
|
|
|
|
is Event.PlaybackError -> toast(message.message)
|
|
|
|
|
|
|
|
is Event.Buffering -> {
|
|
|
|
when (message.value) {
|
2021-07-16 10:03:52 +02:00
|
|
|
true -> binding.nowPlayingContainer?.nowPlayingBuffering?.visibility = View.VISIBLE
|
|
|
|
false -> binding.nowPlayingContainer?.nowPlayingBuffering?.visibility = View.GONE
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
is Event.PlaybackStopped -> {
|
2021-07-16 10:03:52 +02:00
|
|
|
if (binding.nowPlaying.visibility == View.VISIBLE) {
|
|
|
|
(binding.container.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
2019-08-19 16:50:33 +02:00
|
|
|
it.bottomMargin = it.bottomMargin / 2
|
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.landscapeQueue?.let { landscape_queue ->
|
2019-11-05 21:23:29 +01:00
|
|
|
(landscape_queue.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
|
|
|
it.bottomMargin = it.bottomMargin / 2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlaying.animate()
|
2019-08-19 16:50:33 +02:00
|
|
|
.alpha(0.0f)
|
|
|
|
.setDuration(400)
|
|
|
|
.setListener(object : AnimatorListenerAdapter() {
|
|
|
|
override fun onAnimationEnd(animator: Animator?) {
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlaying.visibility = View.GONE
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.start()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-01 16:31:58 +02:00
|
|
|
is Event.TrackFinished -> incrementListenCount(message.track)
|
2019-08-19 16:50:33 +02:00
|
|
|
|
|
|
|
is Event.StateChanged -> {
|
|
|
|
when (message.playing) {
|
|
|
|
true -> {
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.pause)
|
|
|
|
binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.pause)
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
false -> {
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.play)
|
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsToggle?.icon =
|
|
|
|
getDrawable(R.drawable.play)
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-24 12:35:34 +02:00
|
|
|
|
|
|
|
is Event.QueueChanged -> {
|
|
|
|
findViewById<View>(R.id.nav_queue)?.let { view ->
|
|
|
|
ObjectAnimator.ofFloat(view, View.ROTATION, 0f, 360f).let {
|
|
|
|
it.duration = 500
|
|
|
|
it.interpolator = AccelerateDecelerateInterpolator()
|
|
|
|
it.start()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-25 01:26:15 +02:00
|
|
|
lifecycleScope.launch(Main) {
|
2020-06-24 14:54:13 +02:00
|
|
|
CommandBus.get().collect { command ->
|
|
|
|
when (command) {
|
2020-07-09 23:01:35 +02:00
|
|
|
is Command.StartService -> {
|
2020-07-10 17:18:29 +02:00
|
|
|
Build.VERSION_CODES.O.onApi(
|
|
|
|
{
|
2021-07-16 10:03:52 +02:00
|
|
|
startForegroundService(
|
|
|
|
Intent(
|
|
|
|
this@MainActivity,
|
|
|
|
PlayerService::class.java
|
|
|
|
).apply {
|
|
|
|
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
|
|
|
|
})
|
2020-07-10 17:18:29 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
startService(Intent(this@MainActivity, PlayerService::class.java).apply {
|
|
|
|
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
2020-07-09 23:01:35 +02:00
|
|
|
}
|
|
|
|
|
2020-06-24 14:54:13 +02:00
|
|
|
is Command.RefreshTrack -> refreshCurrentTrack(command.track)
|
2020-09-04 13:26:08 +02:00
|
|
|
|
2020-09-04 16:56:31 +02:00
|
|
|
is Command.AddToPlaylist -> if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
2021-07-16 10:03:52 +02:00
|
|
|
AddToPlaylistDialog.show(
|
|
|
|
layoutInflater,
|
|
|
|
this@MainActivity,
|
|
|
|
lifecycleScope,
|
|
|
|
command.tracks
|
|
|
|
)
|
2021-07-01 13:25:09 +02:00
|
|
|
}
|
2020-06-24 14:54:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-25 01:26:15 +02:00
|
|
|
lifecycleScope.launch(Main) {
|
2019-10-31 16:17:37 +01:00
|
|
|
ProgressBus.get().collect { (current, duration, percent) ->
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingProgress?.progress = percent
|
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsProgress?.progress = percent
|
2019-08-19 16:50:33 +02:00
|
|
|
|
|
|
|
val currentMins = (current / 1000) / 60
|
|
|
|
val currentSecs = (current / 1000) % 60
|
|
|
|
|
|
|
|
val durationMins = duration / 60
|
|
|
|
val durationSecs = duration % 60
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsProgressCurrent?.text =
|
|
|
|
"%02d:%02d".format(currentMins, currentSecs)
|
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsProgressDuration?.text =
|
|
|
|
"%02d:%02d".format(durationMins, durationSecs)
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-29 23:42:03 +02:00
|
|
|
|
2020-06-01 16:31:58 +02:00
|
|
|
private fun refreshCurrentTrack(track: Track?) {
|
2020-06-01 21:25:16 +02:00
|
|
|
track?.let {
|
2021-07-16 10:03:52 +02:00
|
|
|
if (binding.nowPlaying.visibility == View.GONE) {
|
|
|
|
binding.nowPlaying.visibility = View.VISIBLE
|
|
|
|
binding.nowPlaying.alpha = 0f
|
2020-06-01 16:31:58 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlaying.animate()
|
2020-06-01 16:31:58 +02:00
|
|
|
.alpha(1.0f)
|
|
|
|
.setDuration(400)
|
|
|
|
.setListener(null)
|
|
|
|
.start()
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
(binding.container.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
2020-06-01 16:31:58 +02:00
|
|
|
it.bottomMargin = it.bottomMargin * 2
|
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.landscapeQueue?.let { landscape_queue ->
|
2020-06-01 16:31:58 +02:00
|
|
|
(landscape_queue.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
|
|
|
it.bottomMargin = it.bottomMargin * 2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingTitle?.text = track.title
|
|
|
|
binding.nowPlayingContainer?.nowPlayingAlbum?.text = track.artist.name
|
|
|
|
binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.pause)
|
2020-06-01 16:31:58 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsTitle?.text = track.title
|
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsArtist?.text = track.artist.name
|
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsToggle?.icon = getDrawable(R.drawable.pause)
|
2020-06-01 16:31:58 +02:00
|
|
|
|
|
|
|
Picasso.get()
|
2020-08-08 14:51:39 +02:00
|
|
|
.maybeLoad(maybeNormalizeUrl(track.album?.cover?.urls?.original))
|
2020-06-01 16:31:58 +02:00
|
|
|
.fit()
|
|
|
|
.centerCrop()
|
2021-07-16 10:03:52 +02:00
|
|
|
.into(binding.nowPlayingContainer?.nowPlayingCover)
|
2020-06-01 16:31:58 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsCover?.let { nowPlayingDetailsCover ->
|
2020-06-01 16:31:58 +02:00
|
|
|
Picasso.get()
|
2020-08-08 14:51:39 +02:00
|
|
|
.maybeLoad(maybeNormalizeUrl(track.album?.cover()))
|
2020-06-01 16:31:58 +02:00
|
|
|
.fit()
|
|
|
|
.centerCrop()
|
2020-06-14 00:42:45 +02:00
|
|
|
.transform(RoundedCornersTransformation(16, 0))
|
2021-07-16 10:03:52 +02:00
|
|
|
.into(nowPlayingDetailsCover)
|
2020-06-01 16:31:58 +02:00
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
if (binding.nowPlayingContainer?.nowPlayingCover == null) {
|
2020-06-25 01:26:15 +02:00
|
|
|
lifecycleScope.launch(Default) {
|
2020-06-01 16:31:58 +02:00
|
|
|
val width = DisplayMetrics().apply {
|
|
|
|
windowManager.defaultDisplay.getMetrics(this)
|
|
|
|
}.widthPixels
|
|
|
|
|
|
|
|
val backgroundCover = Picasso.get()
|
2020-08-08 14:51:39 +02:00
|
|
|
.maybeLoad(maybeNormalizeUrl(track.album?.cover()))
|
2020-06-01 16:31:58 +02:00
|
|
|
.get()
|
|
|
|
.run { Bitmap.createScaledBitmap(this, width, width, false).toDrawable(resources) }
|
|
|
|
.apply {
|
|
|
|
alpha = 20
|
|
|
|
gravity = Gravity.CENTER
|
|
|
|
}
|
|
|
|
|
|
|
|
withContext(Main) {
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetails?.background = backgroundCover
|
2020-06-01 16:31:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.let { now_playing_details_repeat ->
|
2020-06-01 16:31:58 +02:00
|
|
|
changeRepeatMode(Cache.get(this@MainActivity, "repeat")?.readLine()?.toInt() ?: 0)
|
|
|
|
|
|
|
|
now_playing_details_repeat.setOnClickListener {
|
|
|
|
val current = Cache.get(this@MainActivity, "repeat")?.readLine()?.toInt() ?: 0
|
|
|
|
|
|
|
|
changeRepeatMode((current + 1) % 3)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsInfo?.let { nowPlayingDetailsInfo ->
|
|
|
|
nowPlayingDetailsInfo.setOnClickListener {
|
2021-07-01 13:25:09 +02:00
|
|
|
PopupMenu(
|
|
|
|
this@MainActivity,
|
2021-07-16 10:03:52 +02:00
|
|
|
nowPlayingDetailsInfo,
|
2021-07-01 13:25:09 +02:00
|
|
|
Gravity.START,
|
|
|
|
R.attr.actionOverflowMenuStyle,
|
|
|
|
0
|
|
|
|
).apply {
|
2020-06-01 16:31:58 +02:00
|
|
|
inflate(R.menu.track_info)
|
|
|
|
|
|
|
|
setOnMenuItemClickListener {
|
|
|
|
when (it.itemId) {
|
2021-07-01 13:25:09 +02:00
|
|
|
R.id.track_info_artist -> ArtistsFragment.openAlbums(
|
|
|
|
this@MainActivity,
|
|
|
|
track.artist,
|
|
|
|
art = track.album?.cover()
|
|
|
|
)
|
2020-06-01 16:31:58 +02:00
|
|
|
R.id.track_info_album -> AlbumsFragment.openTracks(this@MainActivity, track.album)
|
2021-07-01 13:25:09 +02:00
|
|
|
R.id.track_info_details -> TrackInfoDetailsFragment.new(track)
|
|
|
|
.show(supportFragmentManager, "dialog")
|
2020-06-01 16:31:58 +02:00
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlaying.close()
|
2020-06-01 16:31:58 +02:00
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsFavorite?.let { now_playing_details_favorite ->
|
2020-07-11 16:56:09 +02:00
|
|
|
favoritedRepository.fetch().untilNetwork(lifecycleScope, IO) { favorites, _, _, _ ->
|
2020-06-25 01:26:15 +02:00
|
|
|
lifecycleScope.launch(Main) {
|
2020-06-01 16:31:58 +02:00
|
|
|
track.favorite = favorites.contains(track.id)
|
|
|
|
|
|
|
|
when (track.favorite) {
|
|
|
|
true -> now_playing_details_favorite.setColorFilter(getColor(R.color.colorFavorite))
|
|
|
|
false -> now_playing_details_favorite.setColorFilter(getColor(R.color.controlForeground))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
now_playing_details_favorite.setOnClickListener {
|
|
|
|
when (track.favorite) {
|
|
|
|
true -> {
|
|
|
|
favoriteRepository.deleteFavorite(track.id)
|
|
|
|
now_playing_details_favorite.setColorFilter(getColor(R.color.controlForeground))
|
|
|
|
}
|
|
|
|
|
|
|
|
false -> {
|
|
|
|
favoriteRepository.addFavorite(track.id)
|
|
|
|
now_playing_details_favorite.setColorFilter(getColor(R.color.colorFavorite))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
track.favorite = !track.favorite
|
|
|
|
|
|
|
|
favoriteRepository.fetch(Repository.Origin.Network.origin)
|
|
|
|
}
|
2020-09-26 18:34:13 +02:00
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsAddToPlaylist?.setOnClickListener {
|
2020-09-26 18:34:13 +02:00
|
|
|
CommandBus.send(Command.AddToPlaylist(listOf(track)))
|
|
|
|
}
|
2020-06-01 16:31:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-29 23:42:03 +02:00
|
|
|
private fun changeRepeatMode(index: Int) {
|
|
|
|
when (index) {
|
|
|
|
// From no repeat to repeat all
|
|
|
|
0 -> {
|
|
|
|
Cache.set(this@MainActivity, "repeat", "0".toByteArray())
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setImageResource(R.drawable.repeat)
|
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setColorFilter(
|
2021-07-01 13:25:09 +02:00
|
|
|
ContextCompat.getColor(
|
|
|
|
this,
|
|
|
|
R.color.controlForeground
|
|
|
|
)
|
|
|
|
)
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.alpha = 0.2f
|
2020-05-29 23:42:03 +02:00
|
|
|
|
|
|
|
CommandBus.send(Command.SetRepeatMode(Player.REPEAT_MODE_OFF))
|
|
|
|
}
|
|
|
|
|
|
|
|
// From repeat all to repeat one
|
|
|
|
1 -> {
|
|
|
|
Cache.set(this@MainActivity, "repeat", "1".toByteArray())
|
|
|
|
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setImageResource(R.drawable.repeat)
|
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setColorFilter(
|
2021-07-01 13:25:09 +02:00
|
|
|
ContextCompat.getColor(
|
|
|
|
this,
|
|
|
|
R.color.controlForeground
|
|
|
|
)
|
|
|
|
)
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.alpha = 1.0f
|
2020-05-29 23:42:03 +02:00
|
|
|
|
|
|
|
CommandBus.send(Command.SetRepeatMode(Player.REPEAT_MODE_ALL))
|
|
|
|
}
|
|
|
|
|
|
|
|
// From repeat one to no repeat
|
|
|
|
2 -> {
|
|
|
|
Cache.set(this@MainActivity, "repeat", "2".toByteArray())
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setImageResource(R.drawable.repeat_one)
|
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setColorFilter(
|
2021-07-01 13:25:09 +02:00
|
|
|
ContextCompat.getColor(
|
|
|
|
this,
|
|
|
|
R.color.controlForeground
|
|
|
|
)
|
|
|
|
)
|
2021-07-16 10:03:52 +02:00
|
|
|
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.alpha = 1.0f
|
2020-05-29 23:42:03 +02:00
|
|
|
|
|
|
|
CommandBus.send(Command.SetRepeatMode(Player.REPEAT_MODE_ONE))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-01 16:31:58 +02:00
|
|
|
|
|
|
|
private fun incrementListenCount(track: Track?) {
|
2020-06-01 21:25:16 +02:00
|
|
|
track?.let {
|
2020-06-25 01:26:15 +02:00
|
|
|
lifecycleScope.launch(IO) {
|
2020-06-20 22:10:13 +02:00
|
|
|
try {
|
|
|
|
Fuel
|
|
|
|
.post(mustNormalizeUrl("/api/v1/history/listenings/"))
|
|
|
|
.authorize()
|
|
|
|
.header("Content-Type", "application/json")
|
|
|
|
.body(Gson().toJson(mapOf("track" to track.id)))
|
|
|
|
.awaitStringResponse()
|
|
|
|
} catch (_: Exception) {
|
|
|
|
}
|
2020-06-01 16:31:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|