Refactor packages
This commit is contained in:
parent
c386e1fe93
commit
39b0b4c931
188 changed files with 440 additions and 835 deletions
|
@ -0,0 +1,19 @@
|
|||
package code.name.monkey.retromusic.fragments
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import code.name.monkey.retromusic.R
|
||||
|
||||
|
||||
enum class AlbumCoverStyle(@param:StringRes @field:StringRes
|
||||
val titleRes: Int,
|
||||
@param:DrawableRes @field:DrawableRes
|
||||
val drawableResId: Int, val id: Int) {
|
||||
NORMAL(R.string.normal, R.drawable.np_normal, 0),
|
||||
FLAT(R.string.flat, R.drawable.np_flat, 1),
|
||||
CIRCLE(R.string.circular, R.drawable.np_circle, 2),
|
||||
MATERIAL(R.string.material, R.drawable.np_material, 3),
|
||||
CARD(R.string.card, R.drawable.np_blur_card, 4),
|
||||
FULL(R.string.full, R.drawable.np_full, 5),
|
||||
FULL_CARD(R.string.full_card, R.drawable.np_adaptive, 6)
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
package code.name.monkey.retromusic.fragments
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableString
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.view.*
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_mini_player.*
|
||||
|
||||
open class MiniPlayerFragment : AbsMusicServiceFragment(), MusicProgressViewUpdateHelper.Callback, View.OnClickListener {
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_mini_player, container, false)
|
||||
}
|
||||
|
||||
override fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.actionPlayingQueue -> NavigationUtil.goToPlayingQueue(activity!!)
|
||||
R.id.actionNext -> MusicPlayerRemote.playNextSong()
|
||||
R.id.actionPrevious -> MusicPlayerRemote.back()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
view.setBackgroundColor(ThemeStore.primaryColor(context!!))
|
||||
view.setOnTouchListener(FlingPlayBackController(context!!))
|
||||
//view.setOnClickListener(v -> NavigationUtil.gotoNowPlayingActivity(getContext()));
|
||||
setUpMiniPlayer()
|
||||
|
||||
if (RetroUtil.isTablet()) {
|
||||
actionNext.visibility = View.VISIBLE
|
||||
actionPrevious.visibility = View.VISIBLE
|
||||
actionPlayingQueue.visibility = View.VISIBLE
|
||||
} else {
|
||||
actionNext.visibility = if (PreferenceUtil.getInstance().isExtraMiniExtraControls) View.VISIBLE else View.GONE
|
||||
actionPlayingQueue.visibility = if (PreferenceUtil.getInstance().isExtraMiniExtraControls) View.GONE else View.VISIBLE
|
||||
actionPrevious.visibility = if (PreferenceUtil.getInstance().isExtraMiniExtraControls) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
actionPlayingQueue.setOnClickListener(this)
|
||||
actionNext.setOnClickListener(this)
|
||||
actionPrevious.setOnClickListener(this)
|
||||
}
|
||||
|
||||
private fun setUpMiniPlayer() {
|
||||
setUpPlayPauseButton()
|
||||
ViewUtil.setProgressDrawable(progressBar, ThemeStore.accentColor(context!!))
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseButton() {
|
||||
miniPlayerPlayPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updateSongTitle() {
|
||||
val builder = SpannableStringBuilder()
|
||||
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
val title = SpannableString(song.title)
|
||||
title.setSpan(ForegroundColorSpan(ThemeStore.textColorPrimary(context!!)), 0, title.length, 0)
|
||||
|
||||
val text = SpannableString(song.artistName)
|
||||
text.setSpan(ForegroundColorSpan(ThemeStore.textColorSecondary(context!!)), 0, text.length, 0)
|
||||
|
||||
builder.append(title).append(" • ").append(text)
|
||||
|
||||
miniPlayerTitle.isSelected = true
|
||||
miniPlayerTitle.text = builder
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updateSongTitle()
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateSongTitle()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressBar.max = total
|
||||
val animator = ObjectAnimator.ofInt(progressBar, "progress", progress)
|
||||
animator.duration = 1000
|
||||
animator.interpolator = DecelerateInterpolator()
|
||||
animator.start()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper!!.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper!!.stop()
|
||||
}
|
||||
|
||||
protected fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
miniPlayerPlayPauseButton!!.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
miniPlayerPlayPauseButton!!.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
fun setColor(playerFragmentColor: Int) {
|
||||
view!!.setBackgroundColor(playerFragmentColor)
|
||||
}
|
||||
|
||||
|
||||
class FlingPlayBackController(context: Context) : View.OnTouchListener {
|
||||
|
||||
private var flingPlayBackController: GestureDetector
|
||||
|
||||
init {
|
||||
flingPlayBackController = GestureDetector(context,
|
||||
object : GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float,
|
||||
velocityY: Float): Boolean {
|
||||
if (Math.abs(velocityX) > Math.abs(velocityY)) {
|
||||
if (velocityX < 0) {
|
||||
MusicPlayerRemote.playNextSong()
|
||||
return true
|
||||
} else if (velocityX > 0) {
|
||||
MusicPlayerRemote.playPreviousSong()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||
return flingPlayBackController.onTouchEvent(event)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package code.name.monkey.retromusic.fragments
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import code.name.monkey.retromusic.R
|
||||
|
||||
|
||||
enum class NowPlayingScreen constructor(@param:StringRes @field:StringRes
|
||||
val titleRes: Int,
|
||||
@param:DrawableRes @field:DrawableRes val drawableResId: Int,
|
||||
val id: Int) {
|
||||
ADAPTIVE(R.string.adaptive, R.drawable.np_adaptive, 10),
|
||||
BLUR(R.string.blur, R.drawable.np_blur, 4),
|
||||
BLUR_CARD(R.string.blur_card, R.drawable.np_blur_card, 9),
|
||||
CARD(R.string.card, R.drawable.np_card, 6),
|
||||
COLOR(R.string.color, R.drawable.np_color, 5),
|
||||
FIT(R.string.fit, R.drawable.np_fit, 12),
|
||||
FLAT(R.string.flat, R.drawable.np_flat, 1),
|
||||
FULL(R.string.full, R.drawable.np_full, 2),
|
||||
MATERIAL(R.string.material, R.drawable.np_material, 11),
|
||||
NORMAL(R.string.normal, R.drawable.np_normal, 0),
|
||||
PLAIN(R.string.plain, R.drawable.np_plain, 3),
|
||||
TINY(R.string.tiny, R.drawable.np_tiny, 7),
|
||||
SIMPLE(R.string.simple, R.drawable.np_simple, 8),
|
||||
//SLIDE(R.string.slide, R.drawable.np_slide, 13)
|
||||
|
||||
}
|
142
app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt
Executable file
142
app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt
Executable file
|
@ -0,0 +1,142 @@
|
|||
package code.name.monkey.retromusic.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.media.AudioManager
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.SeekBar
|
||||
import androidx.fragment.app.Fragment
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import code.name.monkey.retromusic.volume.AudioVolumeObserver
|
||||
import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener
|
||||
import kotlinx.android.synthetic.main.fragment_volume.*
|
||||
|
||||
class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolumeChangedListener, View.OnClickListener {
|
||||
|
||||
private var audioVolumeObserver: AudioVolumeObserver? = null
|
||||
|
||||
private val audioManager: AudioManager?
|
||||
get() = context!!.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_volume, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setTintable(ThemeStore.accentColor(context!!))
|
||||
volumeDown.setOnClickListener(this)
|
||||
volumeUp.setOnClickListener(this)
|
||||
|
||||
val iconColor = ATHUtil.resolveColor(context!!, R.attr.iconColor)
|
||||
volumeDown.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN)
|
||||
volumeUp.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (audioVolumeObserver == null) {
|
||||
audioVolumeObserver = AudioVolumeObserver(activity!!)
|
||||
}
|
||||
audioVolumeObserver!!.register(AudioManager.STREAM_MUSIC, this)
|
||||
|
||||
val audioManager = audioManager
|
||||
if (audioManager != null) {
|
||||
volumeSeekBar.max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
|
||||
volumeSeekBar.progress = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
|
||||
}
|
||||
volumeSeekBar.setOnSeekBarChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onAudioVolumeChanged(currentVolume: Int, maxVolume: Int) {
|
||||
if (volumeSeekBar == null) {
|
||||
return
|
||||
}
|
||||
|
||||
volumeSeekBar.max = maxVolume
|
||||
volumeSeekBar.progress = currentVolume
|
||||
volumeDown.setImageResource(if (currentVolume == 0) R.drawable.ic_volume_off_white_24dp else R.drawable.ic_volume_down_white_24dp)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
if (audioVolumeObserver != null) {
|
||||
audioVolumeObserver!!.unregister()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
|
||||
val audioManager = audioManager
|
||||
audioManager?.setStreamVolume(AudioManager.STREAM_MUSIC, i, 0)
|
||||
setPauseWhenZeroVolume(i < 1)
|
||||
volumeDown!!.setImageResource(if (i == 0) R.drawable.ic_volume_off_white_24dp else R.drawable.ic_volume_down_white_24dp)
|
||||
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
||||
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||
|
||||
}
|
||||
|
||||
override fun onClick(view: View) {
|
||||
val audioManager = audioManager
|
||||
when (view.id) {
|
||||
R.id.volumeDown -> audioManager?.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, 0)
|
||||
R.id.volumeUp -> audioManager?.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0)
|
||||
}
|
||||
}
|
||||
|
||||
fun tintWhiteColor() {
|
||||
val iconColor = Color.WHITE
|
||||
volumeDown.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN)
|
||||
volumeUp.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN)
|
||||
|
||||
ViewUtil.setProgressDrawable(volumeSeekBar, iconColor, true)
|
||||
|
||||
}
|
||||
|
||||
fun setTintable(color: Int) {
|
||||
|
||||
ViewUtil.setProgressDrawable(volumeSeekBar, color, true)
|
||||
}
|
||||
|
||||
fun removeThumb() {
|
||||
volumeSeekBar.thumb = null
|
||||
}
|
||||
|
||||
private fun setPauseWhenZeroVolume(pauseWhenZeroVolume: Boolean) {
|
||||
if (PreferenceUtil.getInstance().pauseOnZeroVolume() && pauseWhenZeroVolume)
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
}
|
||||
|
||||
fun setTintableColor(color: Int) {
|
||||
volumeDown.setColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
volumeUp.setColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
//TintHelper.setTintAuto(volumeSeekBar, color, false)
|
||||
ViewUtil.setProgressDrawable(volumeSeekBar, color, true)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): VolumeFragment {
|
||||
return VolumeFragment()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package code.name.monkey.retromusic.fragments.base
|
||||
|
||||
import android.os.Bundle
|
||||
import code.name.monkey.retromusic.fragments.mainactivity.LibraryFragment
|
||||
|
||||
open class AbsLibraryPagerFragment : AbsMusicServiceFragment() {
|
||||
|
||||
|
||||
val libraryFragment: LibraryFragment
|
||||
get() = parentFragment as LibraryFragment
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
package code.name.monkey.retromusic.fragments.base
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
|
||||
|
||||
abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A : RecyclerView.Adapter<*>, LM : RecyclerView.LayoutManager> : AbsLibraryPagerRecyclerViewFragment<A, LM>() {
|
||||
|
||||
private var gridSize: Int = 0
|
||||
private var sortOrder: String? = null
|
||||
|
||||
private var usePaletteInitialized: Boolean = false
|
||||
private var usePalette: Boolean = false
|
||||
private var currentLayoutRes: Int = 0
|
||||
|
||||
val maxGridSize: Int
|
||||
get() = if (isLandscape) {
|
||||
resources.getInteger(R.integer.max_columns_land)
|
||||
} else {
|
||||
resources.getInteger(R.integer.max_columns)
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to customize which item layout currentLayoutRes should be used. You might also want to
|
||||
* override [.canUsePalette] then.
|
||||
*
|
||||
* @see .getGridSize
|
||||
*/
|
||||
protected val itemLayoutRes: Int
|
||||
@LayoutRes
|
||||
get() = if (getGridSize() > maxGridSizeForList) {
|
||||
R.layout.item_grid
|
||||
} else R.layout.item_list
|
||||
|
||||
protected val maxGridSizeForList: Int
|
||||
get() = if (isLandscape) {
|
||||
activity!!.resources.getInteger(R.integer.default_list_columns_land)
|
||||
} else activity!!.resources.getInteger(R.integer.default_list_columns)
|
||||
|
||||
private val isLandscape: Boolean
|
||||
get() = RetroUtil.isLandscape()
|
||||
|
||||
fun getGridSize(): Int {
|
||||
if (gridSize == 0) {
|
||||
gridSize = if (isLandscape) {
|
||||
loadGridSizeLand()
|
||||
} else {
|
||||
loadGridSize()
|
||||
}
|
||||
}
|
||||
return gridSize
|
||||
}
|
||||
|
||||
protected abstract fun setGridSize(gridSize: Int)
|
||||
|
||||
fun getSortOrder(): String? {
|
||||
if (sortOrder == null) {
|
||||
sortOrder = loadSortOrder()
|
||||
}
|
||||
return sortOrder
|
||||
}
|
||||
|
||||
protected abstract fun setSortOrder(sortOrder: String)
|
||||
|
||||
fun setAndSaveSortOrder(sortOrder: String) {
|
||||
this.sortOrder = sortOrder
|
||||
saveSortOrder(sortOrder)
|
||||
setSortOrder(sortOrder)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the palette should be used at all or not
|
||||
*/
|
||||
fun usePalette(): Boolean {
|
||||
if (!usePaletteInitialized) {
|
||||
usePalette = loadUsePalette()
|
||||
usePaletteInitialized = true
|
||||
}
|
||||
return usePalette
|
||||
}
|
||||
|
||||
fun setAndSaveGridSize(gridSize: Int) {
|
||||
val oldLayoutRes = itemLayoutRes
|
||||
this.gridSize = gridSize
|
||||
if (isLandscape) {
|
||||
saveGridSizeLand(gridSize)
|
||||
} else {
|
||||
saveGridSize(gridSize)
|
||||
}
|
||||
// only recreate the adapter and layout manager if the layout currentLayoutRes has changed
|
||||
if (oldLayoutRes != itemLayoutRes) {
|
||||
invalidateLayoutManager()
|
||||
invalidateAdapter()
|
||||
} else {
|
||||
setGridSize(gridSize)
|
||||
}
|
||||
}
|
||||
|
||||
fun setAndSaveUsePalette(usePalette: Boolean) {
|
||||
this.usePalette = usePalette
|
||||
saveUsePalette(usePalette)
|
||||
setUsePalette(usePalette)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the palette option should be available for the current item layout or not
|
||||
*/
|
||||
fun canUsePalette(): Boolean {
|
||||
return itemLayoutRes == R.layout.item_color
|
||||
}
|
||||
|
||||
protected fun notifyLayoutResChanged(@LayoutRes res: Int) {
|
||||
this.currentLayoutRes = res
|
||||
val recyclerView = recyclerView()
|
||||
applyRecyclerViewPaddingForLayoutRes(recyclerView, currentLayoutRes)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
applyRecyclerViewPaddingForLayoutRes(recyclerView(), currentLayoutRes)
|
||||
}
|
||||
|
||||
private fun applyRecyclerViewPaddingForLayoutRes(recyclerView: RecyclerView,
|
||||
@LayoutRes res: Int) {
|
||||
val padding: Int
|
||||
if (res == R.layout.item_grid) {
|
||||
padding = (resources.displayMetrics.density * 2).toInt()
|
||||
} else {
|
||||
padding = 0
|
||||
}
|
||||
recyclerView.setPadding(padding, padding, padding, padding)
|
||||
}
|
||||
|
||||
protected abstract fun loadSortOrder(): String
|
||||
|
||||
protected abstract fun saveSortOrder(sortOrder: String)
|
||||
|
||||
protected abstract fun loadGridSize(): Int
|
||||
|
||||
protected abstract fun saveGridSize(gridColumns: Int)
|
||||
|
||||
protected abstract fun loadGridSizeLand(): Int
|
||||
|
||||
protected abstract fun saveGridSizeLand(gridColumns: Int)
|
||||
|
||||
protected abstract fun saveUsePalette(usePalette: Boolean)
|
||||
|
||||
protected abstract fun loadUsePalette(): Boolean
|
||||
|
||||
protected abstract fun setUsePalette(usePalette: Boolean)
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package code.name.monkey.retromusic.fragments.base
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.NonNull
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.util.DensityUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
|
||||
import kotlinx.android.synthetic.main.fragment_main_activity_recycler_view.*
|
||||
|
||||
abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : RecyclerView.LayoutManager> : AbsLibraryPagerFragment(), AppBarLayout.OnOffsetChangedListener {
|
||||
|
||||
protected var adapter: A? = null
|
||||
protected var layoutManager: LM? = null
|
||||
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_main_activity_recycler_view, container, false);
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
libraryFragment.addOnAppBarOffsetChangedListener(this)
|
||||
initLayoutManager()
|
||||
initAdapter()
|
||||
setUpRecyclerView()
|
||||
}
|
||||
|
||||
private fun setUpRecyclerView() {
|
||||
if (recyclerView is FastScrollRecyclerView) {
|
||||
ViewUtil.setUpFastScrollRecyclerViewColor(activity!!, recyclerView as FastScrollRecyclerView, ThemeStore.accentColor(activity!!))
|
||||
}
|
||||
recyclerView.layoutManager = layoutManager
|
||||
recyclerView.adapter = adapter
|
||||
}
|
||||
|
||||
private fun initAdapter() {
|
||||
adapter = createAdapter()
|
||||
adapter!!.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||
override fun onChanged() {
|
||||
super.onChanged()
|
||||
checkIsEmpty()
|
||||
checkForPadding()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
protected open val emptyMessage: Int
|
||||
@StringRes
|
||||
get() = R.string.empty
|
||||
|
||||
private fun checkIsEmpty() {
|
||||
emptyText.setText(emptyMessage)
|
||||
empty.visibility = if (adapter!!.itemCount == 0) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun checkForPadding() {
|
||||
val height = if (MusicPlayerRemote.playingQueue.isEmpty())
|
||||
DensityUtil.dip2px(context!!, 52f)
|
||||
else
|
||||
0
|
||||
recyclerView.setPadding(0, 0, 0, (height * 2.3).toInt())
|
||||
}
|
||||
|
||||
private fun initLayoutManager() {
|
||||
layoutManager = createLayoutManager()
|
||||
}
|
||||
|
||||
protected abstract fun createLayoutManager(): LM
|
||||
|
||||
@NonNull
|
||||
protected abstract fun createAdapter(): A
|
||||
|
||||
override fun onOffsetChanged(p0: AppBarLayout?, i: Int) {
|
||||
container.setPadding(container.paddingLeft, container.paddingTop,
|
||||
container.paddingRight, libraryFragment.totalAppBarScrollingRange + i)
|
||||
}
|
||||
|
||||
override fun onQueueChanged() {
|
||||
super.onQueueChanged()
|
||||
checkForPadding()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
super.onServiceConnected()
|
||||
checkForPadding()
|
||||
}
|
||||
|
||||
protected fun invalidateLayoutManager() {
|
||||
initLayoutManager()
|
||||
recyclerView.layoutManager = layoutManager
|
||||
}
|
||||
|
||||
protected fun invalidateAdapter() {
|
||||
initAdapter()
|
||||
checkIsEmpty()
|
||||
recyclerView.adapter = adapter
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
libraryFragment.removeOnAppBarOffsetChangedListener(this)
|
||||
}
|
||||
|
||||
fun recyclerView(): RecyclerView {
|
||||
return recyclerView
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package code.name.monkey.retromusic.fragments.base
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.dialogs.OptionsSheetDialogFragment
|
||||
import code.name.monkey.retromusic.activities.MainActivity
|
||||
|
||||
abstract class AbsMainActivityFragment : AbsMusicServiceFragment() {
|
||||
|
||||
val mainActivity: MainActivity
|
||||
get() = activity as MainActivity
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
mainActivity.setNavigationbarColorAuto()
|
||||
mainActivity.setLightNavigationBar(true)
|
||||
mainActivity.setTaskDescriptionColorAuto()
|
||||
mainActivity.hideStatusBar()
|
||||
mainActivity.setBottomBarVisibility(View.VISIBLE)
|
||||
}
|
||||
|
||||
private fun setStatusbarColor(view: View, color: Int) {
|
||||
val statusBar = view.findViewById<View>(R.id.status_bar)
|
||||
if (statusBar != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
statusBar.setBackgroundColor(color)
|
||||
mainActivity.setLightStatusbarAuto(color)
|
||||
} else {
|
||||
statusBar.setBackgroundColor(color)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setStatusbarColorAuto(view: View) {
|
||||
// we don't want to use statusbar color because we are doing the color darkening on our own to support KitKat
|
||||
|
||||
if (VersionUtils.hasMarshmallow()) {
|
||||
setStatusbarColor(view, ThemeStore.primaryColor(context!!))
|
||||
} else {
|
||||
setStatusbarColor(view, ColorUtil.darkenColor(ThemeStore.primaryColor(context!!)))
|
||||
}
|
||||
}
|
||||
|
||||
protected fun showMainMenu() {
|
||||
OptionsSheetDialogFragment.newInstance().show(childFragmentManager, "Main Menu")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package code.name.monkey.retromusic.fragments.base
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
||||
|
||||
/**
|
||||
* Created by hemanths on 18/08/17.
|
||||
*/
|
||||
|
||||
open class AbsMusicServiceFragment : Fragment(), MusicServiceEventListener {
|
||||
|
||||
var playerActivity: AbsMusicServiceActivity? = null
|
||||
private set
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
try {
|
||||
playerActivity = context as AbsMusicServiceActivity?
|
||||
} catch (e: ClassCastException) {
|
||||
throw RuntimeException(context.javaClass.simpleName + " must be an instance of " + AbsMusicServiceActivity::class.java.simpleName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetach() {
|
||||
super.onDetach()
|
||||
playerActivity = null
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
playerActivity!!.addMusicServiceEventListener(this)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
playerActivity!!.removeMusicServiceEventListener(this)
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected() {
|
||||
|
||||
}
|
||||
|
||||
override fun onQueueChanged() {
|
||||
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
|
||||
}
|
||||
|
||||
override fun onMediaStoreChanged() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package code.name.monkey.retromusic.fragments.base
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.fragments.VolumeFragment
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
|
||||
|
||||
/**
|
||||
* Created by hemanths on 24/09/17.
|
||||
*/
|
||||
|
||||
abstract class AbsPlayerControlsFragment : AbsMusicServiceFragment(), MusicProgressViewUpdateHelper.Callback {
|
||||
|
||||
protected abstract fun show()
|
||||
|
||||
protected abstract fun hide()
|
||||
|
||||
protected abstract fun updateShuffleState()
|
||||
|
||||
protected abstract fun updateRepeatState()
|
||||
|
||||
protected abstract fun setUpProgressSlider()
|
||||
|
||||
abstract fun setDark(color: Int)
|
||||
|
||||
fun showBonceAnimation(view: View) {
|
||||
view.apply {
|
||||
clearAnimation()
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
visibility = View.VISIBLE
|
||||
pivotX = (view.width / 2).toFloat()
|
||||
pivotY = (view.height / 2).toFloat()
|
||||
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.scaleX(1.1f)
|
||||
.scaleY(1.1f)
|
||||
.withEndAction {
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(AccelerateInterpolator())
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.alpha(1f)
|
||||
.start()
|
||||
}
|
||||
.start()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
hideVolumeIfAvailable()
|
||||
}
|
||||
|
||||
protected var volumeFragment: VolumeFragment? = null
|
||||
|
||||
private fun hideVolumeIfAvailable() {
|
||||
if (PreferenceUtil.getInstance().volumeToggle) {
|
||||
childFragmentManager.beginTransaction().replace(R.id.volumeFragmentContainer, VolumeFragment()).commit()
|
||||
childFragmentManager.executePendingTransactions()
|
||||
|
||||
volumeFragment = childFragmentManager.findFragmentById(R.id.volumeFragmentContainer) as VolumeFragment?
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SLIDER_ANIMATION_TIME: Long = 400
|
||||
const val VOLUME_FRAGMENT: String = "volume_fragment"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
package code.name.monkey.retromusic.fragments.base
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.os.AsyncTask
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.text.TextUtils
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.dialogs.*
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.interfaces.PaletteColorHolder
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.model.lyrics.Lyrics
|
||||
import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
|
||||
import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.util.*
|
||||
import code.name.monkey.retromusic.views.FitSystemWindowsLayout
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
abstract class AbsPlayerFragment : AbsMusicServiceFragment(), Toolbar.OnMenuItemClickListener, PaletteColorHolder, PlayerAlbumCoverFragment.Callbacks {
|
||||
var callbacks: Callbacks? = null
|
||||
private set
|
||||
private var updateIsFavoriteTask: AsyncTask<*, *, *>? = null
|
||||
private var updateLyricsAsyncTask: AsyncTask<*, *, *>? = null
|
||||
private var playerAlbumCoverFragment: PlayerAlbumCoverFragment? = null
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
try {
|
||||
callbacks = context as Callbacks?
|
||||
} catch (e: ClassCastException) {
|
||||
throw RuntimeException(context.javaClass.simpleName + " must implement " + Callbacks::class.java.simpleName)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onDetach() {
|
||||
super.onDetach()
|
||||
callbacks = null
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
when (item.itemId) {
|
||||
R.id.action_toggle_favorite -> {
|
||||
toggleFavorite(song)
|
||||
return true
|
||||
}
|
||||
R.id.action_share -> {
|
||||
if (fragmentManager != null) {
|
||||
SongShareDialog.create(song).show(fragmentManager!!, "SHARE_SONG")
|
||||
}
|
||||
return true
|
||||
}
|
||||
R.id.action_delete_from_device -> {
|
||||
DeleteSongsDialog.create(song)
|
||||
.show(activity!!.supportFragmentManager, "DELETE_SONGS")
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
if (fragmentManager != null) {
|
||||
AddToPlaylistDialog.create(song).show(fragmentManager!!, "ADD_PLAYLIST")
|
||||
}
|
||||
return true
|
||||
}
|
||||
R.id.action_clear_playing_queue -> {
|
||||
MusicPlayerRemote.clearQueue()
|
||||
return true
|
||||
}
|
||||
R.id.action_save_playing_queue -> {
|
||||
CreatePlaylistDialog.create(MusicPlayerRemote.playingQueue)
|
||||
.show(activity!!.supportFragmentManager, "ADD_TO_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_tag_editor -> {
|
||||
val intent = Intent(activity, SongTagEditorActivity::class.java)
|
||||
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, song.id)
|
||||
startActivity(intent)
|
||||
return true
|
||||
}
|
||||
R.id.action_details -> {
|
||||
if (fragmentManager != null) {
|
||||
SongDetailDialog.create(song).show(fragmentManager!!, "SONG_DETAIL")
|
||||
}
|
||||
return true
|
||||
}
|
||||
R.id.action_go_to_album -> {
|
||||
NavigationUtil.goToAlbum(activity!!, song.albumId)
|
||||
return true
|
||||
}
|
||||
R.id.action_go_to_artist -> {
|
||||
NavigationUtil.goToArtist(activity!!, song.artistId)
|
||||
return true
|
||||
}
|
||||
R.id.now_playing -> {
|
||||
NavigationUtil.goToPlayingQueue(activity!!)
|
||||
return true
|
||||
}
|
||||
R.id.action_show_lyrics -> {
|
||||
NavigationUtil.goToLyrics(activity!!)
|
||||
return true
|
||||
}
|
||||
R.id.action_equalizer -> {
|
||||
NavigationUtil.openEqualizer(activity!!)
|
||||
return true
|
||||
}
|
||||
R.id.action_sleep_timer -> {
|
||||
SleepTimerDialog().show(fragmentManager!!, TAG)
|
||||
return true
|
||||
}
|
||||
R.id.action_set_as_ringtone -> {
|
||||
if (RingtoneManager.requiresDialog(activity!!)) {
|
||||
RingtoneManager.getDialog(activity!!)
|
||||
}
|
||||
val ringtoneManager = RingtoneManager(activity!!)
|
||||
ringtoneManager.setRingtone(song)
|
||||
return true
|
||||
}
|
||||
R.id.action_settings -> {
|
||||
NavigationUtil.goToSettings(activity!!)
|
||||
return true
|
||||
}
|
||||
R.id.action_go_to_genre -> {
|
||||
val retriever = MediaMetadataRetriever()
|
||||
val trackUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, song.id.toLong())
|
||||
retriever.setDataSource(activity, trackUri)
|
||||
var genre: String? = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE)
|
||||
if (genre == null) {
|
||||
genre = "Not Specified"
|
||||
}
|
||||
Toast.makeText(context, genre, Toast.LENGTH_SHORT).show()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
protected open fun toggleFavorite(song: Song) {
|
||||
MusicUtil.toggleFavorite(activity!!, song)
|
||||
}
|
||||
|
||||
abstract fun playerToolbar(): Toolbar
|
||||
|
||||
abstract fun onShow()
|
||||
|
||||
abstract fun onHide()
|
||||
|
||||
abstract fun onBackPressed(): Boolean
|
||||
|
||||
abstract fun toolbarIconColor(): Int
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updateIsFavorite()
|
||||
updateLyrics()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateIsFavorite()
|
||||
updateLyrics()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
if (updateIsFavoriteTask != null && !updateIsFavoriteTask!!.isCancelled) {
|
||||
updateIsFavoriteTask!!.cancel(true)
|
||||
}
|
||||
if (updateLyricsAsyncTask != null && !updateLyricsAsyncTask!!.isCancelled) {
|
||||
updateLyricsAsyncTask!!.cancel(true)
|
||||
}
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
fun updateIsFavorite() {
|
||||
if (updateIsFavoriteTask != null) {
|
||||
updateIsFavoriteTask!!.cancel(false)
|
||||
}
|
||||
updateIsFavoriteTask = object : AsyncTask<Song, Void, Boolean>() {
|
||||
override fun doInBackground(vararg params: Song): Boolean? {
|
||||
val activity = activity
|
||||
return if (activity != null) {
|
||||
MusicUtil.isFavorite(activity, params[0])
|
||||
} else {
|
||||
cancel(false)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPostExecute(isFavorite: Boolean?) {
|
||||
val activity = activity
|
||||
if (activity != null) {
|
||||
val res = if (isFavorite!!)
|
||||
R.drawable.ic_favorite_white_24dp
|
||||
else
|
||||
R.drawable.ic_favorite_border_white_24dp
|
||||
val drawable = RetroUtil.getTintedVectorDrawable(activity, res, toolbarIconColor())
|
||||
if (playerToolbar().menu.findItem(R.id.action_toggle_favorite) != null)
|
||||
playerToolbar().menu.findItem(R.id.action_toggle_favorite).setIcon(drawable).title = if (isFavorite) getString(R.string.action_remove_from_favorites) else getString(R.string.action_add_to_favorites)
|
||||
}
|
||||
}
|
||||
}.execute(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private fun updateLyrics() {
|
||||
if (updateLyricsAsyncTask != null) updateLyricsAsyncTask!!.cancel(false)
|
||||
|
||||
updateLyricsAsyncTask = object : AsyncTask<Song, Void, Lyrics>() {
|
||||
override fun onPreExecute() {
|
||||
super.onPreExecute()
|
||||
setLyrics(null)
|
||||
}
|
||||
|
||||
override fun doInBackground(vararg params: Song): Lyrics? {
|
||||
try {
|
||||
var data: String? = LyricUtil.getStringFromFile(params[0].title, params[0].artistName)
|
||||
return if (TextUtils.isEmpty(data)) {
|
||||
data = MusicUtil.getLyrics(params[0])
|
||||
return if (TextUtils.isEmpty(data)) {
|
||||
null
|
||||
} else {
|
||||
Lyrics.parse(params[0], data)
|
||||
}
|
||||
} else Lyrics.parse(params[0], data!!)
|
||||
} catch (err: FileNotFoundException) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPostExecute(l: Lyrics?) {
|
||||
setLyrics(l)
|
||||
}
|
||||
|
||||
override fun onCancelled(s: Lyrics?) {
|
||||
onPostExecute(null)
|
||||
}
|
||||
}.execute(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
open fun setLyrics(l: Lyrics?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
view.setBackgroundColor(ThemeStore.primaryColor(activity!!))
|
||||
if (PreferenceUtil.getInstance().fullScreenMode && view.findViewById<View>(R.id.status_bar) != null) {
|
||||
view.findViewById<View>(R.id.status_bar).visibility = View.GONE
|
||||
}
|
||||
playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment?
|
||||
playerAlbumCoverFragment?.setCallbacks(this)
|
||||
}
|
||||
|
||||
fun setSafeArea(safeArea: View) {
|
||||
val layout = safeArea.findViewById<FitSystemWindowsLayout>(R.id.safeArea)
|
||||
if (layout != null) {
|
||||
layout.isFit = !PreferenceUtil.getInstance().fullScreenMode
|
||||
}
|
||||
}
|
||||
|
||||
interface Callbacks {
|
||||
|
||||
fun onPaletteColorChanged()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAG: String = AbsPlayerFragment::class.java.simpleName
|
||||
const val VISIBILITY_ANIM_DURATION: Long = 300
|
||||
}
|
||||
|
||||
protected fun getUpNextAndQueueTime(): String {
|
||||
val duration = MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.position)
|
||||
|
||||
return MusicUtil.buildInfoString(
|
||||
resources.getString(R.string.up_next),
|
||||
MusicUtil.getReadableDurationString(duration)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
package code.name.monkey.retromusic.fragments.mainactivity
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.model.Album
|
||||
import code.name.monkey.retromusic.mvp.contract.AlbumContract
|
||||
import code.name.monkey.retromusic.mvp.presenter.AlbumPresenter
|
||||
import code.name.monkey.retromusic.adapter.album.AlbumAdapter
|
||||
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
|
||||
open class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridLayoutManager>(), AlbumContract.AlbumView {
|
||||
|
||||
private var presenter: AlbumPresenter? = null
|
||||
|
||||
|
||||
override val emptyMessage: Int
|
||||
get() = R.string.no_albums
|
||||
|
||||
override fun createLayoutManager(): GridLayoutManager {
|
||||
return GridLayoutManager(activity, getGridSize())
|
||||
}
|
||||
|
||||
override fun createAdapter(): AlbumAdapter {
|
||||
var itemLayoutRes = itemLayoutRes
|
||||
notifyLayoutResChanged(itemLayoutRes)
|
||||
if (itemLayoutRes != R.layout.item_list) {
|
||||
|
||||
itemLayoutRes = PreferenceUtil.getInstance().getAlbumGridStyle(context!!)
|
||||
}
|
||||
val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet
|
||||
return AlbumAdapter(libraryFragment.mainActivity, dataSet, itemLayoutRes, loadUsePalette(), libraryFragment)
|
||||
}
|
||||
|
||||
public override fun loadUsePalette(): Boolean {
|
||||
|
||||
return PreferenceUtil.getInstance().albumColoredFooters()
|
||||
}
|
||||
|
||||
override fun setUsePalette(usePalette: Boolean) {
|
||||
adapter!!.usePalette(usePalette)
|
||||
}
|
||||
|
||||
override fun setGridSize(gridSize: Int) {
|
||||
layoutManager!!.spanCount = gridSize
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun setSortOrder(sortOrder: String) {
|
||||
presenter!!.loadAlbums()
|
||||
}
|
||||
|
||||
override fun loadSortOrder(): String {
|
||||
|
||||
return PreferenceUtil.getInstance().albumSortOrder
|
||||
}
|
||||
|
||||
override fun saveSortOrder(sortOrder: String) {
|
||||
|
||||
PreferenceUtil.getInstance().albumSortOrder = sortOrder
|
||||
}
|
||||
|
||||
override fun loadGridSize(): Int {
|
||||
|
||||
return PreferenceUtil.getInstance().getAlbumGridSize(activity!!)
|
||||
}
|
||||
|
||||
override fun saveGridSize(gridColumns: Int) {
|
||||
|
||||
PreferenceUtil.getInstance().setAlbumGridSize(gridColumns)
|
||||
}
|
||||
|
||||
override fun loadGridSizeLand(): Int {
|
||||
|
||||
return PreferenceUtil.getInstance().getAlbumGridSizeLand(activity!!)
|
||||
}
|
||||
|
||||
override fun saveGridSizeLand(gridColumns: Int) {
|
||||
|
||||
PreferenceUtil.getInstance().setAlbumGridSizeLand(gridColumns)
|
||||
}
|
||||
|
||||
override fun saveUsePalette(usePalette: Boolean) {
|
||||
|
||||
PreferenceUtil.getInstance().setAlbumColoredFooters(usePalette)
|
||||
}
|
||||
|
||||
override fun onMediaStoreChanged() {
|
||||
presenter!!.loadAlbums()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
presenter = AlbumPresenter(this)
|
||||
}
|
||||
|
||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||
super.setMenuVisibility(menuVisible)
|
||||
if (menuVisible) {
|
||||
|
||||
libraryFragment.setTitle(
|
||||
if (PreferenceUtil.getInstance().tabTitles())
|
||||
R.string.library
|
||||
else
|
||||
R.string.albums)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
libraryFragment.setTitle(
|
||||
if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.albums)
|
||||
if (adapter!!.dataSet.isEmpty()) {
|
||||
presenter!!.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
presenter!!.unsubscribe()
|
||||
}
|
||||
|
||||
override fun loading() {}
|
||||
|
||||
override fun showEmptyView() {
|
||||
adapter!!.swapDataSet(ArrayList())
|
||||
}
|
||||
|
||||
override fun completed() {}
|
||||
|
||||
override fun showData(list: ArrayList<Album>) {
|
||||
adapter!!.swapDataSet(list)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val TAG = AlbumsFragment::class.java.simpleName
|
||||
|
||||
fun newInstance(): AlbumsFragment {
|
||||
val args = Bundle()
|
||||
val fragment = AlbumsFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package code.name.monkey.retromusic.fragments.mainactivity
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.model.Artist
|
||||
import code.name.monkey.retromusic.mvp.contract.ArtistContract
|
||||
import code.name.monkey.retromusic.mvp.presenter.ArtistPresenter
|
||||
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
|
||||
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import java.util.*
|
||||
|
||||
class ArtistsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<ArtistAdapter, GridLayoutManager>(), ArtistContract.ArtistView {
|
||||
private var presenter: ArtistPresenter? = null
|
||||
|
||||
override val emptyMessage: Int
|
||||
get() = R.string.no_artists
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
presenter = ArtistPresenter(this)
|
||||
}
|
||||
|
||||
override fun createLayoutManager(): GridLayoutManager {
|
||||
return GridLayoutManager(activity, getGridSize())
|
||||
}
|
||||
|
||||
override fun createAdapter(): ArtistAdapter {
|
||||
var itemLayoutRes = itemLayoutRes
|
||||
notifyLayoutResChanged(itemLayoutRes)
|
||||
if (itemLayoutRes != R.layout.item_list) {
|
||||
itemLayoutRes = PreferenceUtil.getInstance().getArtistGridStyle(context!!)
|
||||
}
|
||||
val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet
|
||||
return ArtistAdapter(libraryFragment.mainActivity, dataSet, itemLayoutRes, loadUsePalette(), libraryFragment)
|
||||
}
|
||||
|
||||
override fun onMediaStoreChanged() {
|
||||
presenter!!.loadArtists()
|
||||
}
|
||||
|
||||
override fun loadGridSize(): Int {
|
||||
return PreferenceUtil.getInstance().getArtistGridSize(activity!!)
|
||||
}
|
||||
|
||||
override fun saveGridSize(gridColumns: Int) {
|
||||
PreferenceUtil.getInstance().setArtistGridSize(gridColumns)
|
||||
}
|
||||
|
||||
override fun loadGridSizeLand(): Int {
|
||||
return PreferenceUtil.getInstance().getArtistGridSizeLand(activity!!)
|
||||
}
|
||||
|
||||
override fun saveGridSizeLand(gridColumns: Int) {
|
||||
PreferenceUtil.getInstance().setArtistGridSizeLand(gridColumns)
|
||||
}
|
||||
|
||||
override fun saveUsePalette(usePalette: Boolean) {
|
||||
PreferenceUtil.getInstance().setArtistColoredFooters(usePalette)
|
||||
}
|
||||
|
||||
public override fun loadUsePalette(): Boolean {
|
||||
return PreferenceUtil.getInstance().artistColoredFooters()
|
||||
}
|
||||
|
||||
override fun setUsePalette(usePalette: Boolean) {
|
||||
adapter!!.usePalette(usePalette)
|
||||
}
|
||||
|
||||
override fun setGridSize(gridSize: Int) {
|
||||
layoutManager!!.spanCount = gridSize
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
|
||||
override fun loadSortOrder(): String {
|
||||
return PreferenceUtil.getInstance().artistSortOrder
|
||||
}
|
||||
|
||||
override fun saveSortOrder(sortOrder: String) {
|
||||
PreferenceUtil.getInstance().artistSortOrder = sortOrder
|
||||
}
|
||||
|
||||
override fun setSortOrder(sortOrder: String) {
|
||||
presenter!!.loadArtists()
|
||||
}
|
||||
|
||||
|
||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||
super.setMenuVisibility(menuVisible)
|
||||
if (menuVisible) {
|
||||
libraryFragment.setTitle(
|
||||
if (PreferenceUtil.getInstance().tabTitles())
|
||||
R.string.library
|
||||
else
|
||||
R.string.artists)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
libraryFragment.setTitle(
|
||||
if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.artists)
|
||||
if (adapter!!.dataSet.isEmpty()) {
|
||||
presenter!!.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
presenter!!.unsubscribe()
|
||||
}
|
||||
|
||||
override fun loading() {}
|
||||
|
||||
override fun showEmptyView() {
|
||||
adapter!!.swapDataSet(ArrayList())
|
||||
}
|
||||
|
||||
override fun completed() {
|
||||
|
||||
}
|
||||
|
||||
override fun showData(list: ArrayList<Artist>) {
|
||||
adapter!!.swapDataSet(list)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val TAG = ArtistsFragment::class.java.simpleName
|
||||
|
||||
fun newInstance(): ArtistsFragment {
|
||||
|
||||
val args = Bundle()
|
||||
|
||||
val fragment = ArtistsFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package code.name.monkey.retromusic.fragments.mainactivity
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.model.Genre
|
||||
import code.name.monkey.retromusic.mvp.contract.GenreContract
|
||||
import code.name.monkey.retromusic.mvp.presenter.GenrePresenter
|
||||
import code.name.monkey.retromusic.adapter.GenreAdapter
|
||||
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewFragment
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import java.util.*
|
||||
|
||||
class GenreFragment : AbsLibraryPagerRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(), GenreContract.GenreView {
|
||||
|
||||
private var mPresenter: GenrePresenter? = null
|
||||
|
||||
override val emptyMessage: Int
|
||||
get() = R.string.no_genres
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
mPresenter = GenrePresenter(this)
|
||||
}
|
||||
|
||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||
super.setMenuVisibility(menuVisible)
|
||||
if (menuVisible) {
|
||||
libraryFragment.setTitle(if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.genres)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
libraryFragment.setTitle(if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.genres)
|
||||
if (adapter!!.dataSet.isEmpty()) {
|
||||
mPresenter!!.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mPresenter!!.unsubscribe()
|
||||
}
|
||||
|
||||
override fun createLayoutManager(): LinearLayoutManager {
|
||||
return LinearLayoutManager(activity)
|
||||
}
|
||||
|
||||
override fun createAdapter(): GenreAdapter {
|
||||
val dataSet = adapter!!.dataSet
|
||||
return GenreAdapter(libraryFragment.mainActivity, dataSet, R.layout.item_list)
|
||||
}
|
||||
|
||||
override fun loading() {
|
||||
|
||||
}
|
||||
|
||||
override fun showData(list: ArrayList<Genre>) {
|
||||
adapter!!.swapDataSet(list)
|
||||
}
|
||||
|
||||
override fun showEmptyView() {
|
||||
adapter!!.swapDataSet(ArrayList())
|
||||
}
|
||||
|
||||
override fun completed() {
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
menu.removeItem(R.id.action_sort_order)
|
||||
menu.removeItem(R.id.action_grid_size)
|
||||
menu.removeItem(R.id.action_new_playlist)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): GenreFragment {
|
||||
val args = Bundle()
|
||||
val fragment = GenreFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,485 @@
|
|||
package code.name.monkey.retromusic.fragments.mainactivity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.SubMenu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.afollestad.materialcab.MaterialCab;
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
||||
|
||||
import code.name.monkey.appthemehelper.ThemeStore;
|
||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity;
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil;
|
||||
import code.name.monkey.appthemehelper.util.TintHelper;
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog;
|
||||
import code.name.monkey.retromusic.helper.SortOrder;
|
||||
import code.name.monkey.retromusic.interfaces.CabHolder;
|
||||
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks;
|
||||
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment;
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment;
|
||||
import code.name.monkey.retromusic.util.Compressor;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import code.name.monkey.retromusic.util.RetroColorUtil;
|
||||
import code.name.monkey.retromusic.util.RetroUtil;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import static code.name.monkey.retromusic.Constants.USER_PROFILE;
|
||||
|
||||
public class LibraryFragment extends AbsMainActivityFragment implements CabHolder, MainActivityFragmentCallbacks {
|
||||
|
||||
public static final String TAG = "LibraryFragment";
|
||||
private static final String CURRENT_TAB_ID = "current_tab_id";
|
||||
|
||||
private Toolbar toolbar;
|
||||
private AppBarLayout appBarLayout;
|
||||
private TextView bannerTitle;
|
||||
private View contentContainer;
|
||||
|
||||
private MaterialCab cab;
|
||||
private FragmentManager fragmentManager;
|
||||
private ImageView userImage;
|
||||
private CompositeDisposable disposable;
|
||||
|
||||
@NonNull
|
||||
public static Fragment newInstance(int tab) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(CURRENT_TAB_ID, tab);
|
||||
LibraryFragment fragment = new LibraryFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Fragment newInstance() {
|
||||
return new LibraryFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
disposable.dispose();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_library, container, false);
|
||||
disposable = new CompositeDisposable();
|
||||
contentContainer = view.findViewById(R.id.fragmentContainer);
|
||||
bannerTitle = view.findViewById(R.id.bannerTitle);
|
||||
appBarLayout = view.findViewById(R.id.appBarLayout);
|
||||
toolbar = view.findViewById(R.id.toolbar);
|
||||
userImage = view.findViewById(R.id.userImage);
|
||||
userImage.setOnClickListener(v -> showMainMenu());
|
||||
|
||||
loadImageFromStorage();
|
||||
return view;
|
||||
}
|
||||
|
||||
private void loadImageFromStorage() {
|
||||
disposable.add(new Compressor(Objects.requireNonNull(getContext()))
|
||||
.setMaxHeight(300)
|
||||
.setMaxWidth(300)
|
||||
.setQuality(75)
|
||||
.setCompressFormat(Bitmap.CompressFormat.WEBP)
|
||||
.compressToBitmapAsFlowable(new File(PreferenceUtil.getInstance().getProfileImage(), USER_PROFILE))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(bitmap -> userImage.setImageBitmap(bitmap),
|
||||
throwable -> userImage.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.ic_person_flat))));
|
||||
}
|
||||
|
||||
public void setTitle(@StringRes int name) {
|
||||
bannerTitle.setText(getString(name));
|
||||
}
|
||||
|
||||
public void addOnAppBarOffsetChangedListener(AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
|
||||
appBarLayout.addOnOffsetChangedListener(onOffsetChangedListener);
|
||||
}
|
||||
|
||||
public void removeOnAppBarOffsetChangedListener(AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
|
||||
appBarLayout.removeOnOffsetChangedListener(onOffsetChangedListener);
|
||||
}
|
||||
|
||||
public int getTotalAppBarScrollingRange() {
|
||||
return appBarLayout.getTotalScrollRange();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
setStatusbarColorAuto(view);
|
||||
setupToolbar();
|
||||
inflateFragment();
|
||||
}
|
||||
|
||||
private void inflateFragment() {
|
||||
if (getArguments() == null) {
|
||||
selectedFragment(SongsFragment.Companion.newInstance());
|
||||
return;
|
||||
}
|
||||
switch (getArguments().getInt(CURRENT_TAB_ID)) {
|
||||
default:
|
||||
case R.id.action_song:
|
||||
selectedFragment(SongsFragment.Companion.newInstance());
|
||||
break;
|
||||
case R.id.action_album:
|
||||
selectedFragment(AlbumsFragment.Companion.newInstance());
|
||||
break;
|
||||
case R.id.action_artist:
|
||||
selectedFragment(ArtistsFragment.Companion.newInstance());
|
||||
break;
|
||||
case R.id.action_playlist:
|
||||
selectedFragment(PlaylistsFragment.Companion.newInstance());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private void setupToolbar() {
|
||||
bannerTitle.setTextColor(ThemeStore.Companion.textColorPrimary(getContext()));
|
||||
|
||||
int primaryColor = ThemeStore.Companion.primaryColor(getContext());
|
||||
TintHelper.setTintAuto(contentContainer, primaryColor, true);
|
||||
|
||||
toolbar.setBackgroundColor(primaryColor);
|
||||
toolbar.setNavigationIcon(R.drawable.ic_search_white_24dp);
|
||||
appBarLayout.setBackgroundColor(primaryColor);
|
||||
appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) ->
|
||||
getMainActivity().setLightStatusbar(!ATHUtil.INSTANCE.isWindowBackgroundDark(getContext())));
|
||||
getMainActivity().setTitle(null);
|
||||
getMainActivity().setSupportActionBar(toolbar);
|
||||
}
|
||||
|
||||
private Fragment getCurrentFragment() {
|
||||
if (fragmentManager == null) {
|
||||
return SongsFragment.Companion.newInstance();
|
||||
}
|
||||
return fragmentManager.findFragmentByTag(LibraryFragment.TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleBackPress() {
|
||||
if (cab != null && cab.isActive()) {
|
||||
cab.finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void selectedFragment(Fragment fragment) {
|
||||
fragmentManager = getChildFragmentManager();
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
|
||||
fragmentTransaction
|
||||
.replace(R.id.fragmentContainer, fragment, TAG)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MaterialCab openCab(int menuRes, @NonNull MaterialCab.Callback callback) {
|
||||
if (cab != null && cab.isActive()) {
|
||||
cab.finish();
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
cab = new MaterialCab(getMainActivity(), R.id.cab_stub)
|
||||
.setMenu(menuRes)
|
||||
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
||||
.setBackgroundColor(
|
||||
RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.Companion.primaryColor(getActivity())))
|
||||
.start(callback);
|
||||
return cab;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(@NotNull Menu menu, @NonNull MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
inflater.inflate(R.menu.menu_main, menu);
|
||||
|
||||
Fragment currentFragment = getCurrentFragment();
|
||||
if (currentFragment instanceof AbsLibraryPagerRecyclerViewCustomGridSizeFragment
|
||||
&& currentFragment.isAdded()) {
|
||||
AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment = (AbsLibraryPagerRecyclerViewCustomGridSizeFragment) currentFragment;
|
||||
|
||||
MenuItem gridSizeItem = menu.findItem(R.id.action_grid_size);
|
||||
if (RetroUtil.isLandscape()) {
|
||||
gridSizeItem.setTitle(R.string.action_grid_size_land);
|
||||
}
|
||||
setUpGridSizeMenu(fragment, gridSizeItem.getSubMenu());
|
||||
|
||||
setUpSortOrderMenu(fragment, menu.findItem(R.id.action_sort_order).getSubMenu());
|
||||
|
||||
} else {
|
||||
menu.add(0, R.id.action_new_playlist, 0, R.string.new_playlist_title).setIcon(R.drawable.ic_playlist_add_white_24dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
menu.removeItem(R.id.action_grid_size);
|
||||
}
|
||||
Activity activity = getActivity();
|
||||
if (activity == null) {
|
||||
return;
|
||||
}
|
||||
ToolbarContentTintHelper.handleOnCreateOptionsMenu(getActivity(), toolbar, menu, ATHToolbarActivity.getToolbarBackgroundColor(toolbar));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
Activity activity = getActivity();
|
||||
if (activity == null) {
|
||||
return;
|
||||
}
|
||||
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(activity, toolbar);
|
||||
}
|
||||
|
||||
|
||||
private void setUpSortOrderMenu(
|
||||
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment,
|
||||
@NonNull SubMenu sortOrderMenu) {
|
||||
String currentSortOrder = fragment.getSortOrder();
|
||||
sortOrderMenu.clear();
|
||||
|
||||
if (fragment instanceof AlbumsFragment) {
|
||||
sortOrderMenu.add(0, R.id.action_album_sort_order_asc, 0, R.string.sort_order_a_z)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_A_Z));
|
||||
sortOrderMenu.add(0, R.id.action_album_sort_order_desc, 1, R.string.sort_order_z_a)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_Z_A));
|
||||
sortOrderMenu.add(0, R.id.action_album_sort_order_artist, 2, R.string.sort_order_artist)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_ARTIST));
|
||||
sortOrderMenu.add(0, R.id.action_album_sort_order_year, 3, R.string.sort_order_year)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_YEAR));
|
||||
} else if (fragment instanceof ArtistsFragment) {
|
||||
sortOrderMenu.add(0, R.id.action_artist_sort_order_asc, 0, R.string.sort_order_a_z)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.ArtistSortOrder.ARTIST_A_Z));
|
||||
sortOrderMenu.add(0, R.id.action_artist_sort_order_desc, 1, R.string.sort_order_z_a)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.ArtistSortOrder.ARTIST_Z_A));
|
||||
} else if (fragment instanceof SongsFragment) {
|
||||
sortOrderMenu.add(0, R.id.action_song_sort_order_asc, 0, R.string.sort_order_a_z)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_A_Z));
|
||||
sortOrderMenu.add(0, R.id.action_song_sort_order_desc, 1, R.string.sort_order_z_a)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_Z_A));
|
||||
sortOrderMenu.add(0, R.id.action_song_sort_order_artist, 2, R.string.sort_order_artist)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_ARTIST));
|
||||
sortOrderMenu.add(0, R.id.action_song_sort_order_album, 3, R.string.sort_order_album)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_ALBUM));
|
||||
sortOrderMenu.add(0, R.id.action_song_sort_order_year, 4, R.string.sort_order_year)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_YEAR));
|
||||
sortOrderMenu.add(0, R.id.action_song_sort_order_date, 5, R.string.sort_order_date)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_DATE));
|
||||
sortOrderMenu.add(0, R.id.action_song_sort_order_composer, 6, R.string.sort_order_composer)
|
||||
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.COMPOSER));
|
||||
}
|
||||
|
||||
sortOrderMenu.setGroupCheckable(0, true, true);
|
||||
}
|
||||
|
||||
private boolean handleSortOrderMenuItem(
|
||||
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment
|
||||
fragment, @NonNull MenuItem item) {
|
||||
String sortOrder = null;
|
||||
if (fragment instanceof AlbumsFragment) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_album_sort_order_asc:
|
||||
sortOrder = SortOrder.AlbumSortOrder.ALBUM_A_Z;
|
||||
break;
|
||||
case R.id.action_album_sort_order_desc:
|
||||
sortOrder = SortOrder.AlbumSortOrder.ALBUM_Z_A;
|
||||
break;
|
||||
case R.id.action_album_sort_order_artist:
|
||||
sortOrder = SortOrder.AlbumSortOrder.ALBUM_ARTIST;
|
||||
break;
|
||||
case R.id.action_album_sort_order_year:
|
||||
sortOrder = SortOrder.AlbumSortOrder.ALBUM_YEAR;
|
||||
break;
|
||||
}
|
||||
} else if (fragment instanceof ArtistsFragment) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_artist_sort_order_asc:
|
||||
sortOrder = SortOrder.ArtistSortOrder.ARTIST_A_Z;
|
||||
break;
|
||||
case R.id.action_artist_sort_order_desc:
|
||||
sortOrder = SortOrder.ArtistSortOrder.ARTIST_Z_A;
|
||||
break;
|
||||
}
|
||||
} else if (fragment instanceof SongsFragment) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_song_sort_order_asc:
|
||||
sortOrder = SortOrder.SongSortOrder.SONG_A_Z;
|
||||
break;
|
||||
case R.id.action_song_sort_order_desc:
|
||||
sortOrder = SortOrder.SongSortOrder.SONG_Z_A;
|
||||
break;
|
||||
case R.id.action_song_sort_order_artist:
|
||||
sortOrder = SortOrder.SongSortOrder.SONG_ARTIST;
|
||||
break;
|
||||
case R.id.action_song_sort_order_album:
|
||||
sortOrder = SortOrder.SongSortOrder.SONG_ALBUM;
|
||||
break;
|
||||
case R.id.action_song_sort_order_year:
|
||||
sortOrder = SortOrder.SongSortOrder.SONG_YEAR;
|
||||
break;
|
||||
case R.id.action_song_sort_order_date:
|
||||
sortOrder = SortOrder.SongSortOrder.SONG_DATE;
|
||||
break;
|
||||
case R.id.action_song_sort_order_composer:
|
||||
sortOrder = SortOrder.SongSortOrder.COMPOSER;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (sortOrder != null) {
|
||||
item.setChecked(true);
|
||||
fragment.setAndSaveSortOrder(sortOrder);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
//if (pager == null) return false;
|
||||
Fragment currentFragment = getCurrentFragment();
|
||||
if (currentFragment instanceof AbsLibraryPagerRecyclerViewCustomGridSizeFragment) {
|
||||
AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment = (AbsLibraryPagerRecyclerViewCustomGridSizeFragment) currentFragment;
|
||||
if (handleGridSizeMenuItem(fragment, item)) {
|
||||
return true;
|
||||
}
|
||||
if (handleSortOrderMenuItem(fragment, item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
int id = item.getItemId();
|
||||
switch (id) {
|
||||
case R.id.action_new_playlist:
|
||||
CreatePlaylistDialog.Companion.create().show(getChildFragmentManager(), "CREATE_PLAYLIST");
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
private void setUpGridSizeMenu(
|
||||
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment,
|
||||
@NonNull SubMenu gridSizeMenu) {
|
||||
switch (fragment.getGridSize()) {
|
||||
case 1:
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_1).setChecked(true);
|
||||
break;
|
||||
case 2:
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_2).setChecked(true);
|
||||
break;
|
||||
case 3:
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_3).setChecked(true);
|
||||
break;
|
||||
case 4:
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_4).setChecked(true);
|
||||
break;
|
||||
case 5:
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_5).setChecked(true);
|
||||
break;
|
||||
case 6:
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_6).setChecked(true);
|
||||
break;
|
||||
case 7:
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_7).setChecked(true);
|
||||
break;
|
||||
case 8:
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_8).setChecked(true);
|
||||
break;
|
||||
}
|
||||
int maxGridSize = fragment.getMaxGridSize();
|
||||
if (maxGridSize < 8) {
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_8).setVisible(false);
|
||||
}
|
||||
if (maxGridSize < 7) {
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_7).setVisible(false);
|
||||
}
|
||||
if (maxGridSize < 6) {
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_6).setVisible(false);
|
||||
}
|
||||
if (maxGridSize < 5) {
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_5).setVisible(false);
|
||||
}
|
||||
if (maxGridSize < 4) {
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_4).setVisible(false);
|
||||
}
|
||||
if (maxGridSize < 3) {
|
||||
gridSizeMenu.findItem(R.id.action_grid_size_3).setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean handleGridSizeMenuItem(
|
||||
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment
|
||||
fragment, @NonNull MenuItem item) {
|
||||
int gridSize = 0;
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_grid_size_1:
|
||||
gridSize = 1;
|
||||
break;
|
||||
case R.id.action_grid_size_2:
|
||||
gridSize = 2;
|
||||
break;
|
||||
case R.id.action_grid_size_3:
|
||||
gridSize = 3;
|
||||
break;
|
||||
case R.id.action_grid_size_4:
|
||||
gridSize = 4;
|
||||
break;
|
||||
case R.id.action_grid_size_5:
|
||||
gridSize = 5;
|
||||
break;
|
||||
case R.id.action_grid_size_6:
|
||||
gridSize = 6;
|
||||
break;
|
||||
case R.id.action_grid_size_7:
|
||||
gridSize = 7;
|
||||
break;
|
||||
case R.id.action_grid_size_8:
|
||||
gridSize = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gridSize > 0) {
|
||||
item.setChecked(true);
|
||||
fragment.setAndSaveGridSize(gridSize);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package code.name.monkey.retromusic.fragments.mainactivity
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.model.Playlist
|
||||
import code.name.monkey.retromusic.mvp.contract.PlaylistContract
|
||||
import code.name.monkey.retromusic.mvp.presenter.PlaylistPresenter
|
||||
import code.name.monkey.retromusic.adapter.playlist.PlaylistAdapter
|
||||
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewFragment
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import java.util.*
|
||||
|
||||
|
||||
class PlaylistsFragment : AbsLibraryPagerRecyclerViewFragment<PlaylistAdapter, LinearLayoutManager>(), PlaylistContract.PlaylistView {
|
||||
|
||||
private var presenter: PlaylistPresenter? = null
|
||||
|
||||
override val emptyMessage: Int
|
||||
get() = R.string.no_playlists
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
presenter = PlaylistPresenter(this)
|
||||
}
|
||||
|
||||
override fun createLayoutManager(): LinearLayoutManager {
|
||||
return LinearLayoutManager(activity)
|
||||
}
|
||||
|
||||
override fun createAdapter(): PlaylistAdapter {
|
||||
return PlaylistAdapter(libraryFragment.mainActivity, ArrayList(),
|
||||
R.layout.item_list, libraryFragment)
|
||||
}
|
||||
|
||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||
super.setMenuVisibility(menuVisible)
|
||||
if (menuVisible) {
|
||||
libraryFragment.setTitle(if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.playlists)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
libraryFragment.setTitle(if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.playlists)
|
||||
if (adapter!!.dataSet.isEmpty()) {
|
||||
presenter!!.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
presenter!!.unsubscribe()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onMediaStoreChanged() {
|
||||
super.onMediaStoreChanged()
|
||||
presenter!!.loadPlaylists()
|
||||
}
|
||||
|
||||
override fun loading() {
|
||||
|
||||
}
|
||||
|
||||
override fun showEmptyView() {
|
||||
adapter!!.swapDataSet(ArrayList())
|
||||
}
|
||||
|
||||
override fun completed() {
|
||||
|
||||
}
|
||||
|
||||
override fun showData(list: ArrayList<Playlist>) {
|
||||
adapter!!.swapDataSet(list)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
menu.apply {
|
||||
removeItem(R.id.action_sort_order)
|
||||
removeItem(R.id.action_grid_size)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): PlaylistsFragment {
|
||||
val args = Bundle()
|
||||
val fragment = PlaylistsFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package code.name.monkey.retromusic.fragments.mainactivity
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.mvp.contract.SongContract
|
||||
import code.name.monkey.retromusic.mvp.presenter.SongPresenter
|
||||
import code.name.monkey.retromusic.adapter.song.ShuffleButtonSongAdapter
|
||||
import code.name.monkey.retromusic.adapter.song.SongAdapter
|
||||
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import java.util.*
|
||||
|
||||
class SongsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<SongAdapter, GridLayoutManager>(), SongContract.SongView {
|
||||
|
||||
|
||||
private lateinit var presenter: SongPresenter
|
||||
|
||||
override val emptyMessage: Int
|
||||
get() = R.string.no_songs
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
presenter = SongPresenter(this)
|
||||
}
|
||||
|
||||
override fun createLayoutManager(): GridLayoutManager {
|
||||
return GridLayoutManager(activity, getGridSize())
|
||||
}
|
||||
|
||||
override fun createAdapter(): SongAdapter {
|
||||
val itemLayoutRes = itemLayoutRes
|
||||
notifyLayoutResChanged(itemLayoutRes)
|
||||
val usePalette = loadUsePalette()
|
||||
|
||||
val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet
|
||||
|
||||
return if (getGridSize() <= maxGridSizeForList) {
|
||||
ShuffleButtonSongAdapter(libraryFragment.mainActivity, dataSet, itemLayoutRes, usePalette, libraryFragment)
|
||||
} else SongAdapter(libraryFragment.mainActivity, dataSet, itemLayoutRes, usePalette, libraryFragment)
|
||||
}
|
||||
|
||||
override fun onMediaStoreChanged() {
|
||||
presenter.loadSongs()
|
||||
}
|
||||
|
||||
override fun loadGridSize(): Int {
|
||||
return PreferenceUtil.getInstance().getSongGridSize(activity!!)
|
||||
}
|
||||
|
||||
override fun saveGridSize(gridColumns: Int) {
|
||||
PreferenceUtil.getInstance().setSongGridSize(gridColumns)
|
||||
}
|
||||
|
||||
override fun loadGridSizeLand(): Int {
|
||||
return PreferenceUtil.getInstance().getSongGridSizeLand(activity!!)
|
||||
}
|
||||
|
||||
override fun saveGridSizeLand(gridColumns: Int) {
|
||||
PreferenceUtil.getInstance().setSongGridSizeLand(gridColumns)
|
||||
}
|
||||
|
||||
public override fun saveUsePalette(usePalette: Boolean) {
|
||||
PreferenceUtil.getInstance().setSongColoredFooters(usePalette)
|
||||
}
|
||||
|
||||
public override fun loadUsePalette(): Boolean {
|
||||
return PreferenceUtil.getInstance().songColoredFooters()
|
||||
}
|
||||
|
||||
public override fun setUsePalette(usePalette: Boolean) {
|
||||
adapter!!.usePalette(usePalette)
|
||||
}
|
||||
|
||||
override fun setGridSize(gridSize: Int) {
|
||||
layoutManager!!.spanCount = gridSize
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
libraryFragment.setTitle(if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.songs)
|
||||
if (adapter!!.dataSet.isEmpty()) {
|
||||
presenter!!.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||
super.setMenuVisibility(menuVisible)
|
||||
if (menuVisible) {
|
||||
libraryFragment.setTitle(
|
||||
if (PreferenceUtil.getInstance().tabTitles())
|
||||
R.string.library
|
||||
else
|
||||
R.string.songs)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
presenter.unsubscribe()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun loading() {
|
||||
|
||||
}
|
||||
|
||||
override fun showData(list: ArrayList<Song>) {
|
||||
adapter!!.swapDataSet(list)
|
||||
}
|
||||
|
||||
override fun showEmptyView() {
|
||||
adapter!!.swapDataSet(ArrayList())
|
||||
}
|
||||
|
||||
override fun completed() {
|
||||
|
||||
}
|
||||
|
||||
override fun loadSortOrder(): String {
|
||||
return PreferenceUtil.getInstance().songSortOrder
|
||||
}
|
||||
|
||||
override fun saveSortOrder(sortOrder: String) {
|
||||
PreferenceUtil.getInstance().songSortOrder = sortOrder
|
||||
}
|
||||
|
||||
override fun setSortOrder(sortOrder: String) {
|
||||
presenter!!.loadSongs()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): SongsFragment {
|
||||
val args = Bundle()
|
||||
val fragment = SongsFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}// Required empty public constructor
|
|
@ -0,0 +1,753 @@
|
|||
package code.name.monkey.retromusic.fragments.mainactivity.folders;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialcab.MaterialCab;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.Loader;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import code.name.monkey.appthemehelper.ThemeStore;
|
||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity;
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil;
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil;
|
||||
import code.name.monkey.appthemehelper.util.TintHelper;
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
|
||||
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.interfaces.LoaderIds;
|
||||
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks;
|
||||
import code.name.monkey.retromusic.misc.DialogAsyncTask;
|
||||
import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener;
|
||||
import code.name.monkey.retromusic.misc.WrappedAsyncTaskLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.adapter.SongFileAdapter;
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment;
|
||||
import code.name.monkey.retromusic.util.FileUtil;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import code.name.monkey.retromusic.util.RetroColorUtil;
|
||||
import code.name.monkey.retromusic.util.ViewUtil;
|
||||
import code.name.monkey.retromusic.views.BreadCrumbLayout;
|
||||
|
||||
public class FoldersFragment extends AbsMainActivityFragment implements
|
||||
MainActivityFragmentCallbacks,
|
||||
CabHolder, BreadCrumbLayout.SelectionCallback, SongFileAdapter.Callbacks,
|
||||
AppBarLayout.OnOffsetChangedListener, LoaderManager.LoaderCallbacks<List<File>> {
|
||||
|
||||
public static final String TAG = FoldersFragment.class.getSimpleName();
|
||||
public static final FileFilter AUDIO_FILE_FILTER = file -> !file.isHidden() && (file.isDirectory() ||
|
||||
FileUtil.fileIsMimeType(file, "audio/*", MimeTypeMap.getSingleton()) ||
|
||||
FileUtil.fileIsMimeType(file, "application/opus", MimeTypeMap.getSingleton()) ||
|
||||
FileUtil.fileIsMimeType(file, "application/ogg", MimeTypeMap.getSingleton()));
|
||||
|
||||
private static final String PATH = "path";
|
||||
private static final String CRUMBS = "crumbs";
|
||||
private static final int LOADER_ID = LoaderIds.Companion.getFOLDERS_FRAGMENT();
|
||||
|
||||
private View coordinatorLayout, container, empty;
|
||||
|
||||
private TextView title;
|
||||
|
||||
private Toolbar toolbar;
|
||||
|
||||
private BreadCrumbLayout breadCrumbs;
|
||||
|
||||
private AppBarLayout appBarLayout;
|
||||
|
||||
private FastScrollRecyclerView recyclerView;
|
||||
|
||||
private Comparator<File> fileComparator = (lhs, rhs) -> {
|
||||
if (lhs.isDirectory() && !rhs.isDirectory()) {
|
||||
return -1;
|
||||
} else if (!lhs.isDirectory() && rhs.isDirectory()) {
|
||||
return 1;
|
||||
} else {
|
||||
return lhs.getName().compareToIgnoreCase
|
||||
(rhs.getName());
|
||||
}
|
||||
};
|
||||
private SongFileAdapter adapter;
|
||||
private MaterialCab cab;
|
||||
|
||||
public FoldersFragment() {
|
||||
}
|
||||
|
||||
public static FoldersFragment newInstance(Context context) {
|
||||
return newInstance(PreferenceUtil.getInstance().getStartDirectory());
|
||||
}
|
||||
|
||||
public static FoldersFragment newInstance(File directory) {
|
||||
FoldersFragment frag = new FoldersFragment();
|
||||
Bundle b = new Bundle();
|
||||
b.putSerializable(PATH, directory);
|
||||
frag.setArguments(b);
|
||||
return frag;
|
||||
}
|
||||
|
||||
public static File getDefaultStartDirectory() {
|
||||
File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
|
||||
File startFolder;
|
||||
if (musicDir.exists() && musicDir.isDirectory()) {
|
||||
startFolder = musicDir;
|
||||
} else {
|
||||
File externalStorage = Environment.getExternalStorageDirectory();
|
||||
if (externalStorage.exists() && externalStorage.isDirectory()) {
|
||||
startFolder = externalStorage;
|
||||
} else {
|
||||
startFolder = new File("/"); // root
|
||||
}
|
||||
}
|
||||
return startFolder;
|
||||
}
|
||||
|
||||
private static File tryGetCanonicalFile(File file) {
|
||||
try {
|
||||
return file.getCanonicalFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
private void initViews(View view) {
|
||||
coordinatorLayout = view.findViewById(R.id.coordinatorLayout);
|
||||
recyclerView = view.findViewById(R.id.recyclerView);
|
||||
appBarLayout = view.findViewById(R.id.appBarLayout);
|
||||
breadCrumbs = view.findViewById(R.id.breadCrumbs);
|
||||
toolbar = view.findViewById(R.id.toolbar);
|
||||
empty = view.findViewById(android.R.id.empty);
|
||||
title = view.findViewById(R.id.bannerTitle);
|
||||
container = view.findViewById(R.id.container);
|
||||
}
|
||||
|
||||
private void setCrumb(BreadCrumbLayout.Crumb crumb, boolean addToHistory) {
|
||||
if (crumb == null) {
|
||||
return;
|
||||
}
|
||||
saveScrollPosition();
|
||||
breadCrumbs.setActiveOrAdd(crumb, false);
|
||||
if (addToHistory) {
|
||||
breadCrumbs.addHistory(crumb);
|
||||
}
|
||||
getLoaderManager().restartLoader(LOADER_ID, null, this);
|
||||
}
|
||||
|
||||
private void saveScrollPosition() {
|
||||
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
|
||||
if (crumb != null) {
|
||||
crumb.setScrollPosition(((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private BreadCrumbLayout.Crumb getActiveCrumb() {
|
||||
return breadCrumbs != null && breadCrumbs.size() > 0 ? breadCrumbs
|
||||
.getCrumb(breadCrumbs.getActiveIndex()) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (breadCrumbs != null) {
|
||||
outState.putParcelable(CRUMBS, breadCrumbs.getStateWrapper());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
getMainActivity().setBottomBarVisibility(View.GONE);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
//noinspection ConstantConditions
|
||||
setCrumb(new BreadCrumbLayout.Crumb(
|
||||
FileUtil.safeGetCanonicalFile((File) getArguments().getSerializable(PATH))), true);
|
||||
} else {
|
||||
breadCrumbs.restoreFromStateWrapper(savedInstanceState.getParcelable(CRUMBS));
|
||||
getLoaderManager().initLoader(LOADER_ID, null, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_folder, container, false);
|
||||
initViews(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
setStatusbarColorAuto(view);
|
||||
setUpAppbarColor();
|
||||
setUpBreadCrumbs();
|
||||
setUpRecyclerView();
|
||||
setUpAdapter();
|
||||
|
||||
}
|
||||
|
||||
private void setUpAppbarColor() {
|
||||
title.setTextColor(ThemeStore.Companion.textColorPrimary(getContext()));
|
||||
|
||||
//noinspection ConstantConditions
|
||||
int primaryColor = ThemeStore.Companion.primaryColor(getContext());
|
||||
|
||||
toolbar.setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp);
|
||||
//noinspection ConstantConditions
|
||||
|
||||
getActivity().setTitle(null);
|
||||
getMainActivity().setSupportActionBar(toolbar);
|
||||
TintHelper.setTintAuto(container, primaryColor, true);
|
||||
appBarLayout.setBackgroundColor(primaryColor);
|
||||
toolbar.setBackgroundColor(primaryColor);
|
||||
toolbar.setNavigationOnClickListener(v -> {
|
||||
getActivity().onBackPressed();
|
||||
});
|
||||
|
||||
breadCrumbs.setActivatedContentColor(ToolbarContentTintHelper.toolbarTitleColor(getActivity(), ColorUtil.INSTANCE.darkenColor(primaryColor)));
|
||||
breadCrumbs.setDeactivatedContentColor(ToolbarContentTintHelper.toolbarSubtitleColor(getActivity(), ColorUtil.INSTANCE.darkenColor(primaryColor)));
|
||||
appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> getMainActivity().setLightStatusbar(!ATHUtil.INSTANCE.isWindowBackgroundDark(getContext())));
|
||||
}
|
||||
|
||||
private void setUpBreadCrumbs() {
|
||||
breadCrumbs.setCallback(this);
|
||||
}
|
||||
|
||||
private void setUpRecyclerView() {
|
||||
//noinspection ConstantConditions
|
||||
ViewUtil.INSTANCE.setUpFastScrollRecyclerViewColor(getActivity(), recyclerView,
|
||||
ThemeStore.Companion.accentColor(getActivity()));
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
appBarLayout.addOnOffsetChangedListener(this);
|
||||
}
|
||||
|
||||
private void setUpAdapter() {
|
||||
adapter = new SongFileAdapter(getMainActivity(), new LinkedList<File>(), R.layout.item_list,
|
||||
this, this);
|
||||
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
super.onChanged();
|
||||
checkIsEmpty();
|
||||
}
|
||||
});
|
||||
recyclerView.setAdapter(adapter);
|
||||
checkIsEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
saveScrollPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
appBarLayout.removeOnOffsetChangedListener(this);
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleBackPress() {
|
||||
if (cab != null && cab.isActive()) {
|
||||
cab.finish();
|
||||
return true;
|
||||
}
|
||||
if (breadCrumbs != null && breadCrumbs.popHistory()) {
|
||||
setCrumb(breadCrumbs.lastHistory(), false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MaterialCab openCab(int menuRes, MaterialCab.Callback callback) {
|
||||
if (cab != null && cab.isActive()) {
|
||||
cab.finish();
|
||||
}
|
||||
cab = new MaterialCab(getMainActivity(), R.id.cab_stub)
|
||||
.setMenu(menuRes)
|
||||
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
||||
.setBackgroundColor(RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.Companion.primaryColor(getActivity())))
|
||||
.start(callback);
|
||||
return cab;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
inflater.inflate(R.menu.menu_folders, menu);
|
||||
ToolbarContentTintHelper.handleOnCreateOptionsMenu(getActivity(), toolbar, menu,
|
||||
ATHToolbarActivity.getToolbarBackgroundColor(toolbar));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(getActivity(), toolbar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrumbSelection(BreadCrumbLayout.Crumb crumb, int index) {
|
||||
setCrumb(crumb, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
//noinspection ConstantConditions
|
||||
getActivity().onBackPressed();
|
||||
break;
|
||||
case R.id.action_go_to_start_directory:
|
||||
setCrumb(new BreadCrumbLayout.Crumb(tryGetCanonicalFile(PreferenceUtil.getInstance().getStartDirectory())), true);
|
||||
return true;
|
||||
case R.id.action_scan:
|
||||
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
|
||||
if (crumb != null) {
|
||||
//noinspection Convert2MethodRef
|
||||
new ListPathsAsyncTask(getActivity(), paths -> scanPaths(paths)).execute(new ListPathsAsyncTask.LoadingInfo(crumb.getFile(), AUDIO_FILE_FILTER));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileSelected(File file) {
|
||||
file = tryGetCanonicalFile(file); // important as we compare the path value later
|
||||
if (file.isDirectory()) {
|
||||
setCrumb(new BreadCrumbLayout.Crumb(file), true);
|
||||
} else {
|
||||
FileFilter fileFilter = pathname -> !pathname.isDirectory() && AUDIO_FILE_FILTER
|
||||
.accept(pathname);
|
||||
new ListSongsAsyncTask(getActivity(), file, (songs, extra) -> {
|
||||
File file1 = (File) extra;
|
||||
int startIndex = -1;
|
||||
for (int i = 0; i < songs.size(); i++) {
|
||||
if (file1.getPath().equals(songs.get(i).getData())) { // path is already canonical here
|
||||
startIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (startIndex > -1) {
|
||||
MusicPlayerRemote.INSTANCE.openQueue(songs, startIndex, true);
|
||||
} else {
|
||||
final File finalFile = file1;
|
||||
Snackbar.make(coordinatorLayout, Html.fromHtml(
|
||||
String.format(getString(R.string.not_listed_in_media_store), file1.getName())),
|
||||
Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.action_scan,
|
||||
v -> new ListPathsAsyncTask(getActivity(), this::scanPaths)
|
||||
.execute(new ListPathsAsyncTask.LoadingInfo(finalFile, AUDIO_FILE_FILTER)))
|
||||
.setActionTextColor(ThemeStore.Companion.accentColor(getActivity()))
|
||||
.show();
|
||||
}
|
||||
}).execute(new ListSongsAsyncTask.LoadingInfo(toList(file.getParentFile()), fileFilter,
|
||||
getFileComparator()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMultipleItemAction(MenuItem item, ArrayList<File> files) {
|
||||
final int itemId = item.getItemId();
|
||||
new ListSongsAsyncTask(getActivity(), null,
|
||||
(songs, extra) -> SongsMenuHelper.INSTANCE.handleMenuClick(getActivity(), songs, itemId))
|
||||
.execute(new ListSongsAsyncTask.LoadingInfo(files, AUDIO_FILE_FILTER, getFileComparator()));
|
||||
}
|
||||
|
||||
private ArrayList<File> toList(File file) {
|
||||
ArrayList<File> files = new ArrayList<>(1);
|
||||
files.add(file);
|
||||
return files;
|
||||
}
|
||||
|
||||
private Comparator<File> getFileComparator() {
|
||||
return fileComparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileMenuClicked(final File file, View view) {
|
||||
PopupMenu popupMenu = new PopupMenu(getActivity(), view);
|
||||
if (file.isDirectory()) {
|
||||
popupMenu.inflate(R.menu.menu_item_directory);
|
||||
popupMenu.setOnMenuItemClickListener(item -> {
|
||||
final int itemId = item.getItemId();
|
||||
switch (itemId) {
|
||||
case R.id.action_play_next:
|
||||
case R.id.action_add_to_current_playing:
|
||||
case R.id.action_add_to_playlist:
|
||||
case R.id.action_delete_from_device:
|
||||
new ListSongsAsyncTask(getActivity(), null, (songs, extra) -> {
|
||||
if (!songs.isEmpty()) {
|
||||
SongsMenuHelper.INSTANCE.handleMenuClick(getActivity(), songs, itemId);
|
||||
}
|
||||
}).execute(new ListSongsAsyncTask.LoadingInfo(toList(file), AUDIO_FILE_FILTER,
|
||||
getFileComparator()));
|
||||
return true;
|
||||
case R.id.action_set_as_start_directory:
|
||||
PreferenceUtil.getInstance().setStartDirectory(file);
|
||||
Toast.makeText(getActivity(),
|
||||
String.format(getString(R.string.new_start_directory), file.getPath()),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
case R.id.action_scan:
|
||||
new ListPathsAsyncTask(getActivity(), this::scanPaths)
|
||||
.execute(new ListPathsAsyncTask.LoadingInfo(file, AUDIO_FILE_FILTER));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
popupMenu.inflate(R.menu.menu_item_file);
|
||||
popupMenu.setOnMenuItemClickListener(item -> {
|
||||
final int itemId = item.getItemId();
|
||||
switch (itemId) {
|
||||
case R.id.action_play_next:
|
||||
case R.id.action_add_to_current_playing:
|
||||
case R.id.action_add_to_playlist:
|
||||
case R.id.action_go_to_album:
|
||||
case R.id.action_go_to_artist:
|
||||
case R.id.action_share:
|
||||
case R.id.action_tag_editor:
|
||||
case R.id.action_details:
|
||||
case R.id.action_set_as_ringtone:
|
||||
case R.id.action_delete_from_device:
|
||||
new ListSongsAsyncTask(getActivity(), null, (songs, extra) -> SongMenuHelper.INSTANCE.handleMenuClick(getActivity(), songs.get(0), itemId)).execute(new ListSongsAsyncTask.LoadingInfo(toList(file), AUDIO_FILE_FILTER, getFileComparator()));
|
||||
return true;
|
||||
case R.id.action_scan:
|
||||
new ListPathsAsyncTask(getActivity(), this::scanPaths).execute(new ListPathsAsyncTask.LoadingInfo(file, AUDIO_FILE_FILTER));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
popupMenu.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
|
||||
container.setPadding(container.getPaddingLeft(), container.getPaddingTop(),
|
||||
container.getPaddingRight(), this.appBarLayout.getTotalScrollRange() + verticalOffset);
|
||||
}
|
||||
|
||||
private void checkIsEmpty() {
|
||||
if (empty != null) {
|
||||
empty
|
||||
.setVisibility(adapter == null || adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void scanPaths(@Nullable String[] toBeScanned) {
|
||||
if (getActivity() == null) {
|
||||
return;
|
||||
}
|
||||
if (toBeScanned == null || toBeScanned.length < 1) {
|
||||
Toast.makeText(getActivity(), R.string.nothing_to_scan, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
MediaScannerConnection.scanFile(getActivity().getApplicationContext(), toBeScanned, null,
|
||||
new UpdateToastMediaScannerCompletionListener(getActivity(), toBeScanned));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAdapter(@NonNull List<File> files) {
|
||||
adapter.swapDataSet(files);
|
||||
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
|
||||
if (crumb != null && recyclerView != null) {
|
||||
((LinearLayoutManager) recyclerView.getLayoutManager())
|
||||
.scrollToPositionWithOffset(crumb.getScrollPosition(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Loader<List<File>> onCreateLoader(int id, Bundle args) {
|
||||
return new AsyncFileLoader(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(@NonNull Loader<List<File>> loader, List<File> data) {
|
||||
updateAdapter(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(@NonNull Loader<List<File>> loader) {
|
||||
updateAdapter(new LinkedList<File>());
|
||||
}
|
||||
|
||||
private static class AsyncFileLoader extends WrappedAsyncTaskLoader<List<File>> {
|
||||
|
||||
private WeakReference<FoldersFragment> fragmentWeakReference;
|
||||
|
||||
AsyncFileLoader(FoldersFragment foldersFragment) {
|
||||
super(Objects.requireNonNull(foldersFragment.getActivity()));
|
||||
fragmentWeakReference = new WeakReference<>(foldersFragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<File> loadInBackground() {
|
||||
FoldersFragment foldersFragment = fragmentWeakReference.get();
|
||||
File directory = null;
|
||||
if (foldersFragment != null) {
|
||||
BreadCrumbLayout.Crumb crumb = foldersFragment.getActiveCrumb();
|
||||
if (crumb != null) {
|
||||
directory = crumb.getFile();
|
||||
}
|
||||
}
|
||||
if (directory != null) {
|
||||
List<File> files = FileUtil.listFiles(directory, AUDIO_FILE_FILTER);
|
||||
Collections.sort(files, foldersFragment.getFileComparator());
|
||||
return files;
|
||||
} else {
|
||||
return new LinkedList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ListSongsAsyncTask extends ListingFilesDialogAsyncTask<ListSongsAsyncTask.LoadingInfo, Void, ArrayList<Song>> {
|
||||
|
||||
private final Object extra;
|
||||
private WeakReference<Context> contextWeakReference;
|
||||
private WeakReference<OnSongsListedCallback> callbackWeakReference;
|
||||
|
||||
ListSongsAsyncTask(Context context, Object extra, OnSongsListedCallback callback) {
|
||||
super(context);
|
||||
this.extra = extra;
|
||||
contextWeakReference = new WeakReference<>(context);
|
||||
callbackWeakReference = new WeakReference<>(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
checkCallbackReference();
|
||||
checkContextReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArrayList<Song> doInBackground(LoadingInfo... params) {
|
||||
try {
|
||||
LoadingInfo info = params[0];
|
||||
List<File> files = FileUtil.listFilesDeep(info.files, info.fileFilter);
|
||||
|
||||
if (isCancelled() || checkContextReference() == null
|
||||
|| checkCallbackReference() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Collections.sort(files, info.fileComparator);
|
||||
|
||||
Context context = checkContextReference();
|
||||
if (isCancelled() || context == null || checkCallbackReference() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return FileUtil.matchFilesWithMediaStore(context, files).blockingFirst();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
cancel(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(ArrayList<Song> songs) {
|
||||
super.onPostExecute(songs);
|
||||
OnSongsListedCallback callback = checkCallbackReference();
|
||||
if (songs != null && callback != null) {
|
||||
callback.onSongsListed(songs, extra);
|
||||
}
|
||||
}
|
||||
|
||||
private Context checkContextReference() {
|
||||
Context context = contextWeakReference.get();
|
||||
if (context == null) {
|
||||
cancel(false);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
private OnSongsListedCallback checkCallbackReference() {
|
||||
OnSongsListedCallback callback = callbackWeakReference.get();
|
||||
if (callback == null) {
|
||||
cancel(false);
|
||||
}
|
||||
return callback;
|
||||
}
|
||||
|
||||
public interface OnSongsListedCallback {
|
||||
|
||||
void onSongsListed(@NonNull ArrayList<Song> songs, Object extra);
|
||||
}
|
||||
|
||||
static class LoadingInfo {
|
||||
|
||||
final Comparator<File> fileComparator;
|
||||
final FileFilter fileFilter;
|
||||
final List<File> files;
|
||||
|
||||
LoadingInfo(@NonNull List<File> files, @NonNull FileFilter fileFilter,
|
||||
@NonNull Comparator<File> fileComparator) {
|
||||
this.fileComparator = fileComparator;
|
||||
this.fileFilter = fileFilter;
|
||||
this.files = files;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ListPathsAsyncTask extends
|
||||
ListingFilesDialogAsyncTask<ListPathsAsyncTask.LoadingInfo, String, String[]> {
|
||||
|
||||
private WeakReference<OnPathsListedCallback> onPathsListedCallbackWeakReference;
|
||||
|
||||
public ListPathsAsyncTask(Context context, OnPathsListedCallback callback) {
|
||||
super(context);
|
||||
onPathsListedCallbackWeakReference = new WeakReference<>(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
checkCallbackReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(LoadingInfo... params) {
|
||||
try {
|
||||
if (isCancelled() || checkCallbackReference() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
LoadingInfo info = params[0];
|
||||
|
||||
final String[] paths;
|
||||
|
||||
if (info.file.isDirectory()) {
|
||||
List<File> files = FileUtil.listFilesDeep(info.file, info.fileFilter);
|
||||
|
||||
if (isCancelled() || checkCallbackReference() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
paths = new String[files.size()];
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
File f = files.get(i);
|
||||
paths[i] = FileUtil.safeGetCanonicalPath(f);
|
||||
|
||||
if (isCancelled() || checkCallbackReference() == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
paths = new String[1];
|
||||
paths[0] = info.file.getPath();
|
||||
}
|
||||
|
||||
return paths;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
cancel(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String[] paths) {
|
||||
super.onPostExecute(paths);
|
||||
OnPathsListedCallback callback = checkCallbackReference();
|
||||
if (callback != null && paths != null) {
|
||||
callback.onPathsListed(paths);
|
||||
}
|
||||
}
|
||||
|
||||
private OnPathsListedCallback checkCallbackReference() {
|
||||
OnPathsListedCallback callback = onPathsListedCallbackWeakReference.get();
|
||||
if (callback == null) {
|
||||
cancel(false);
|
||||
}
|
||||
return callback;
|
||||
}
|
||||
|
||||
public interface OnPathsListedCallback {
|
||||
|
||||
void onPathsListed(@NonNull String[] paths);
|
||||
}
|
||||
|
||||
public static class LoadingInfo {
|
||||
|
||||
public final File file;
|
||||
final FileFilter fileFilter;
|
||||
|
||||
public LoadingInfo(File file, FileFilter fileFilter) {
|
||||
this.file = file;
|
||||
this.fileFilter = fileFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class ListingFilesDialogAsyncTask<Params, Progress, Result> extends
|
||||
DialogAsyncTask<Params, Progress, Result> {
|
||||
|
||||
ListingFilesDialogAsyncTask(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ListingFilesDialogAsyncTask(Context context, int showDelay) {
|
||||
super(context, showDelay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog createDialog(@NonNull Context context) {
|
||||
View view= LayoutInflater.from(context).inflate(R.layout.progress_bar,null);
|
||||
ProgressBar progressBar= view.findViewById(R.id.progressBar);
|
||||
ViewUtil.INSTANCE.setProgressDrawable(progressBar,ThemeStore.Companion.accentColor(context));
|
||||
|
||||
MaterialDialog materialDialog= new MaterialDialog(context);
|
||||
materialDialog.setContentView(R.layout.progress_bar);
|
||||
materialDialog.title(R.string.listing_files,"");
|
||||
return materialDialog;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
package code.name.monkey.retromusic.fragments.mainactivity.home
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.TintHelper
|
||||
import code.name.monkey.retromusic.Constants.USER_BANNER
|
||||
import code.name.monkey.retromusic.Constants.USER_PROFILE
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.glide.GlideApp
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
|
||||
import code.name.monkey.retromusic.loaders.SongLoader
|
||||
import code.name.monkey.retromusic.model.Home
|
||||
import code.name.monkey.retromusic.model.smartplaylist.HistoryPlaylist
|
||||
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist
|
||||
import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist
|
||||
import code.name.monkey.retromusic.mvp.contract.HomeContract
|
||||
import code.name.monkey.retromusic.mvp.presenter.HomePresenter
|
||||
import code.name.monkey.retromusic.adapter.HomeAdapter
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||
import code.name.monkey.retromusic.util.Compressor
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.synthetic.main.fragment_banner_home.*
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallbacks, HomeContract.HomeView {
|
||||
override fun showEmpty() {
|
||||
|
||||
}
|
||||
|
||||
private lateinit var disposable: CompositeDisposable
|
||||
private lateinit var homePresenter: HomePresenter
|
||||
private lateinit var contentContainerView: View
|
||||
private lateinit var lastAdded: View
|
||||
private lateinit var topPlayed: View
|
||||
private lateinit var actionShuffle: View
|
||||
private lateinit var history: View
|
||||
private lateinit var userImage: ImageView
|
||||
private lateinit var toolbar: Toolbar
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, viewGroup: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(if (PreferenceUtil.getInstance().isHomeBanner) R.layout.fragment_banner_home else R.layout.fragment_home, viewGroup, false)
|
||||
}
|
||||
|
||||
private val displayMetrics: DisplayMetrics
|
||||
get() {
|
||||
val display = mainActivity.windowManager.defaultDisplay
|
||||
val metrics = DisplayMetrics()
|
||||
display.getMetrics(metrics)
|
||||
return metrics
|
||||
}
|
||||
|
||||
private fun getTimeOfTheDay() {
|
||||
val c = Calendar.getInstance()
|
||||
val timeOfDay = c.get(Calendar.HOUR_OF_DAY)
|
||||
|
||||
var images = arrayOf<String>()
|
||||
when (timeOfDay) {
|
||||
in 0..5 -> images = resources.getStringArray(R.array.night)
|
||||
in 6..11 -> images = resources.getStringArray(R.array.morning)
|
||||
in 12..15 -> images = resources.getStringArray(R.array.after_noon)
|
||||
in 16..19 -> images = resources.getStringArray(R.array.evening)
|
||||
in 20..23 -> images = resources.getStringArray(R.array.night)
|
||||
}
|
||||
|
||||
val day = images[Random().nextInt(images.size)]
|
||||
loadTimeImage(day)
|
||||
}
|
||||
|
||||
|
||||
private fun loadTimeImage(day: String) {
|
||||
if (bannerImage != null) {
|
||||
if (PreferenceUtil.getInstance().bannerImage.isEmpty()) {
|
||||
GlideApp.with(activity!!)
|
||||
.load(day)
|
||||
.placeholder(R.drawable.material_design_default)
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.into(bannerImage!!)
|
||||
} else {
|
||||
disposable.add(Compressor(context!!)
|
||||
.setQuality(100)
|
||||
.setCompressFormat(Bitmap.CompressFormat.WEBP)
|
||||
.compressToBitmapAsFlowable(File(PreferenceUtil.getInstance().bannerImage, USER_BANNER))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { bannerImage!!.setImageBitmap(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadImageFromStorage(imageView: ImageView) {
|
||||
disposable.add(Compressor(context!!)
|
||||
.setMaxHeight(300)
|
||||
.setMaxWidth(300)
|
||||
.setQuality(75)
|
||||
.setCompressFormat(Bitmap.CompressFormat.WEBP)
|
||||
.compressToBitmapAsFlowable(File(PreferenceUtil.getInstance().profileImage, USER_PROFILE))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
if (it != null) {
|
||||
imageView.setImageBitmap(it)
|
||||
} else {
|
||||
imageView.setImageDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_person_flat))
|
||||
}
|
||||
}) {
|
||||
imageView.setImageDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_person_flat))
|
||||
})
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
homePresenter = HomePresenter(this)
|
||||
}
|
||||
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
toolbar = view.findViewById(R.id.toolbar)
|
||||
|
||||
if (!PreferenceUtil.getInstance().isHomeBanner)
|
||||
setStatusbarColorAuto(view)
|
||||
|
||||
lastAdded = view.findViewById(R.id.lastAdded)
|
||||
lastAdded.setOnClickListener {
|
||||
NavigationUtil.goToPlaylistNew(mainActivity, LastAddedPlaylist(mainActivity))
|
||||
}
|
||||
|
||||
topPlayed = view.findViewById(R.id.topPlayed)
|
||||
topPlayed.setOnClickListener {
|
||||
NavigationUtil.goToPlaylistNew(mainActivity, MyTopTracksPlaylist(mainActivity))
|
||||
}
|
||||
|
||||
actionShuffle = view.findViewById(R.id.actionShuffle)
|
||||
actionShuffle.setOnClickListener {
|
||||
MusicPlayerRemote.openAndShuffleQueue(SongLoader.getAllSongs(mainActivity).blockingFirst(), true)
|
||||
}
|
||||
|
||||
history = view.findViewById(R.id.history)
|
||||
history.setOnClickListener {
|
||||
NavigationUtil.goToPlaylistNew(mainActivity, HistoryPlaylist(mainActivity))
|
||||
}
|
||||
|
||||
userImage = view.findViewById(R.id.userImage)
|
||||
userImage.setOnClickListener { showMainMenu() }
|
||||
|
||||
homePresenter = HomePresenter(this)
|
||||
|
||||
contentContainerView = view.findViewById(R.id.contentContainer)
|
||||
contentContainerView.setBackgroundColor(ThemeStore.primaryColor(context!!))
|
||||
|
||||
setupToolbar()
|
||||
homeAdapter = HomeAdapter(mainActivity, ArrayList(), displayMetrics)
|
||||
|
||||
homePresenter.subscribe()
|
||||
|
||||
checkPadding()
|
||||
}
|
||||
|
||||
private fun checkPadding() {
|
||||
val marginSpan = when {
|
||||
MusicPlayerRemote.playingQueue.isEmpty() -> RetroUtil.convertDpToPixel(52f, context).toInt()
|
||||
else -> RetroUtil.convertDpToPixel(0f, context).toInt()
|
||||
}
|
||||
|
||||
(recyclerView.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin = (marginSpan * 2.3f).toInt()
|
||||
}
|
||||
|
||||
private fun setupToolbar() {
|
||||
mainActivity.title = null
|
||||
toolbar.apply {
|
||||
navigationIcon = TintHelper.createTintedDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_search_white_24dp), ThemeStore.textColorSecondary(context!!))
|
||||
setBackgroundColor(Color.TRANSPARENT)
|
||||
setNavigationOnClickListener {
|
||||
NavigationUtil.goToSearch(activity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleBackPress(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
disposable = CompositeDisposable()
|
||||
loadImageFromStorage(userImage)
|
||||
getTimeOfTheDay()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
disposable.dispose()
|
||||
homePresenter.unsubscribe()
|
||||
}
|
||||
|
||||
override fun loading() {
|
||||
|
||||
}
|
||||
|
||||
override fun showEmptyView() {
|
||||
|
||||
}
|
||||
|
||||
override fun completed() {
|
||||
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
super.onServiceConnected()
|
||||
checkPadding()
|
||||
}
|
||||
|
||||
override fun onQueueChanged() {
|
||||
super.onQueueChanged()
|
||||
checkPadding()
|
||||
}
|
||||
|
||||
private lateinit var homeAdapter: HomeAdapter
|
||||
|
||||
override fun showData(list: ArrayList<Home>) {
|
||||
val finalList = list.sortedWith(compareBy { it.priority })
|
||||
homeAdapter.swapData(finalList)
|
||||
recyclerView.apply {
|
||||
layoutManager = LinearLayoutManager(mainActivity)
|
||||
adapter = homeAdapter
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val TAG: String = "BannerHomeFragment"
|
||||
|
||||
fun newInstance(): BannerHomeFragment {
|
||||
val args = Bundle()
|
||||
val fragment = BannerHomeFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package code.name.monkey.retromusic.fragments.player
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.transform.CarousalPagerTransformer
|
||||
import code.name.monkey.retromusic.transform.ParallaxPagerTransformer
|
||||
import code.name.monkey.retromusic.adapter.album.AlbumCoverPagerAdapter
|
||||
import code.name.monkey.retromusic.fragments.NowPlayingScreen
|
||||
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import kotlinx.android.synthetic.main.fragment_player_album_cover.*
|
||||
|
||||
|
||||
class PlayerAlbumCoverFragment : AbsMusicServiceFragment(), ViewPager.OnPageChangeListener {
|
||||
|
||||
|
||||
|
||||
|
||||
private var callbacks: Callbacks? = null
|
||||
private var currentPosition: Int = 0
|
||||
private val colorReceiver = object : AlbumCoverPagerAdapter.AlbumCoverFragment.ColorReceiver {
|
||||
override fun onColorReady(color: Int, request: Int) {
|
||||
if (currentPosition == request) {
|
||||
notifyColorChange(color)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeSlideEffect() {
|
||||
val transformer = ParallaxPagerTransformer(code.name.monkey.retromusic.R.id.player_image)
|
||||
transformer.setSpeed(0.3f)
|
||||
viewPager.setPageTransformer(true, transformer)
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(code.name.monkey.retromusic.R.layout.fragment_player_album_cover, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
|
||||
viewPager.addOnPageChangeListener(this)
|
||||
//noinspection ConstantConditions
|
||||
if (PreferenceUtil.getInstance().carouselEffect() &&
|
||||
!((PreferenceUtil.getInstance().nowPlayingScreen == NowPlayingScreen.FULL) ||
|
||||
(PreferenceUtil.getInstance().nowPlayingScreen == NowPlayingScreen.ADAPTIVE)
|
||||
|| (PreferenceUtil.getInstance().nowPlayingScreen == NowPlayingScreen.FIT))) {
|
||||
viewPager.clipToPadding = false
|
||||
viewPager.setPadding(96, 0, 96, 0)
|
||||
viewPager.pageMargin = 18
|
||||
viewPager.setPageTransformer(false, CarousalPagerTransformer(context!!))
|
||||
} else {
|
||||
viewPager.offscreenPageLimit = 2
|
||||
viewPager.setPageTransformer(true, PreferenceUtil.getInstance().albumCoverTransform)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
|
||||
viewPager.removeOnPageChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayingQueue()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
viewPager.currentItem = MusicPlayerRemote.position
|
||||
}
|
||||
|
||||
override fun onQueueChanged() {
|
||||
updatePlayingQueue()
|
||||
}
|
||||
|
||||
private fun updatePlayingQueue() {
|
||||
viewPager.apply {
|
||||
adapter = AlbumCoverPagerAdapter(fragmentManager!!, MusicPlayerRemote.playingQueue)
|
||||
viewPager.adapter!!.notifyDataSetChanged()
|
||||
viewPager.currentItem = MusicPlayerRemote.position
|
||||
onPageSelected(MusicPlayerRemote.position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
currentPosition = position
|
||||
if (viewPager.adapter != null) {
|
||||
(viewPager.adapter as AlbumCoverPagerAdapter).receiveColor(colorReceiver, position)
|
||||
}
|
||||
if (position != MusicPlayerRemote.position) {
|
||||
MusicPlayerRemote.playSongAt(position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun notifyColorChange(color: Int) {
|
||||
if (callbacks != null) {
|
||||
callbacks!!.onColorChanged(color)
|
||||
}
|
||||
}
|
||||
|
||||
fun setCallbacks(listener: Callbacks) {
|
||||
callbacks = listener
|
||||
}
|
||||
|
||||
fun removeEffect() {
|
||||
viewPager.setPageTransformer(false, null)
|
||||
}
|
||||
|
||||
|
||||
interface Callbacks {
|
||||
|
||||
fun onColorChanged(color: Int)
|
||||
|
||||
fun onFavoriteToggled()
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
companion object {
|
||||
val TAG: String = PlayerAlbumCoverFragment::class.java.simpleName
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package code.name.monkey.retromusic.fragments.player.adaptive
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import kotlinx.android.synthetic.main.fragment_adaptive_player.*
|
||||
|
||||
class AdaptiveFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private var lastColor: Int = 0
|
||||
private lateinit var playbackControlsFragment: AdaptivePlaybackControlsFragment
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_adaptive_player, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as AdaptivePlaybackControlsFragment
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.apply {
|
||||
removeSlideEffect()
|
||||
setCallbacks(this@AdaptiveFragment)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
ATHUtil.resolveColor(context, R.attr.iconColor)
|
||||
val primaryColor = ThemeStore.primaryColor(context!!)
|
||||
playerToolbar.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
ToolbarContentTintHelper.colorizeToolbar(this, primaryColor, activity)
|
||||
setTitleTextColor(primaryColor)
|
||||
setSubtitleTextColor(ThemeStore.textColorSecondary(context!!))
|
||||
setOnMenuItemClickListener(this@AdaptiveFragment)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
super.onServiceConnected()
|
||||
updateIsFavorite()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateIsFavorite()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
playerToolbar.apply {
|
||||
title = song.title
|
||||
subtitle = song.artistName
|
||||
}
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
playbackControlsFragment.setDark(color)
|
||||
lastColor = color
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
playbackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
playbackControlsFragment.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return ATHUtil.resolveColor(context, R.attr.iconColor)
|
||||
}
|
||||
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
package code.name.monkey.retromusic.fragments.player.adaptive
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_adaptive_player_playback_controls.*
|
||||
|
||||
class AdaptivePlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_adaptive_player_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
|
||||
playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBonceAnimation(playPauseButton)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper!!.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper!!.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
if (ColorUtil.isColorLight(ATHUtil.resolveColor(context, android.R.attr.windowBackground))) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
|
||||
}
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
updatePlayPauseColor()
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(colorFinal)), false)
|
||||
TintHelper.setTintAuto(playPauseButton, colorFinal, true)
|
||||
ViewUtil.setProgressDrawable(progressSlider, colorFinal, true)
|
||||
volumeFragment?.setTintable(colorFinal)
|
||||
}
|
||||
|
||||
private fun updatePlayPauseColor() {
|
||||
//playPauseButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
//Ignore
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
//Ignore
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
package code.name.monkey.retromusic.fragments.player.blur
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import androidx.core.content.ContextCompat
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_player_playback_controls.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
|
||||
|
||||
class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_player_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
|
||||
playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBonceAnimation()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
title.text = song.title
|
||||
text.text = song.artistName
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper!!.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper!!.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
lastPlaybackControlsColor = Color.WHITE
|
||||
lastDisabledPlaybackControlsColor = ContextCompat.getColor(context!!, R.color.md_grey_500)
|
||||
|
||||
title.setTextColor(lastPlaybackControlsColor)
|
||||
text.setTextColor(lastDisabledPlaybackControlsColor)
|
||||
|
||||
setFabColor(lastPlaybackControlsColor)
|
||||
songCurrentProgress.setTextColor(lastPlaybackControlsColor)
|
||||
songTotalTime.setTextColor(lastPlaybackControlsColor)
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
volumeFragment?.tintWhiteColor()
|
||||
}
|
||||
|
||||
private fun setFabColor(i: Int) {
|
||||
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(i)), false)
|
||||
TintHelper.setTintAuto(playPauseButton, i, true)
|
||||
setProgressBarColor(i)
|
||||
}
|
||||
|
||||
private fun setProgressBarColor(newColor: Int) {
|
||||
ViewUtil.setProgressDrawable(progressSlider, newColor)
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.rotation(360f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
if (playPauseButton != null) {
|
||||
playPauseButton!!.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun showBonceAnimation() {
|
||||
playPauseButton.apply {
|
||||
clearAnimation()
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
visibility = View.VISIBLE
|
||||
pivotX = (width / 2).toFloat()
|
||||
pivotY = (height / 2).toFloat()
|
||||
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.scaleX(1.1f)
|
||||
.scaleY(1.1f)
|
||||
.withEndAction {
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(AccelerateInterpolator())
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.alpha(1f).start()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
package code.name.monkey.retromusic.fragments.player.blur
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.glide.BlurTransformation
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import kotlinx.android.synthetic.main.fragment_blur.*
|
||||
|
||||
class BlurPlayerFragment : AbsPlayerFragment() {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private lateinit var playbackControlsFragment: BlurPlaybackControlsFragment
|
||||
|
||||
private var lastColor: Int = 0
|
||||
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_blur, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as BlurPlaybackControlsFragment
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar!!.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
ToolbarContentTintHelper.colorizeToolbar(this, Color.WHITE, activity)
|
||||
}.setOnMenuItemClickListener(this)
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
playbackControlsFragment.setDark(color)
|
||||
lastColor = color
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar!!, Color.WHITE, activity)
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return Color.WHITE
|
||||
}
|
||||
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
|
||||
private fun updateBlur() {
|
||||
val activity = activity ?: return
|
||||
val blurAmount = PreferenceManager.getDefaultSharedPreferences(context).getInt("new_blur_amount", 25)
|
||||
colorBackground!!.clearColorFilter()
|
||||
GlideApp.with(activity)
|
||||
.asBitmapPalette()
|
||||
.load(RetroGlideExtension.getSongModel(MusicPlayerRemote.currentSong))
|
||||
.transition(RetroGlideExtension.getDefaultTransition())
|
||||
.transform(BlurTransformation.Builder(activity).blurRadius(blurAmount.toFloat()).build())
|
||||
.songOptions(MusicPlayerRemote.currentSong)
|
||||
.override(320, 480)
|
||||
.into(object : RetroMusicColoredTarget(colorBackground) {
|
||||
override fun onColorReady(color: Int) {
|
||||
if (color == defaultFooterColor) {
|
||||
colorBackground!!.setColorFilter(color)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||
super.onLoadFailed(errorDrawable)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updateIsFavorite()
|
||||
updateBlur()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateIsFavorite()
|
||||
updateBlur()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package code.name.monkey.retromusic.fragments.player.card
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment
|
||||
import kotlinx.android.synthetic.main.fragment_card_player.*
|
||||
|
||||
class CardFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
private lateinit var playbackControlsFragment: CardPlaybackControlsFragment
|
||||
|
||||
override fun onShow() {
|
||||
playbackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
playbackControlsFragment.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return Color.WHITE
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
playbackControlsFragment.setDark(color)
|
||||
lastColor = color
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, Color.WHITE, activity)
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_card_player, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as CardPlaybackControlsFragment
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
playerAlbumCoverFragment.removeSlideEffect()
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.inflateMenu(R.menu.menu_player)
|
||||
playerToolbar.setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
playerToolbar.setOnMenuItemClickListener(this)
|
||||
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, Color.WHITE, activity)
|
||||
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updateIsFavorite()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateIsFavorite()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): PlayerFragment {
|
||||
val args = Bundle()
|
||||
val fragment = PlayerFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
package code.name.monkey.retromusic.fragments.player.card
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import kotlinx.android.synthetic.main.fragment_card_player_playback_controls.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
|
||||
class CardPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_card_player_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
|
||||
setupControls()
|
||||
|
||||
playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBonceAnimation(playPauseButton)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupControls() {
|
||||
image.apply {
|
||||
setImageResource(R.drawable.ic_play_circle_filled_white_24dp)
|
||||
val iconPadding = activity!!.resources.getDimensionPixelSize(R.dimen.list_item_image_icon_padding)
|
||||
setPadding(iconPadding, iconPadding, iconPadding, iconPadding)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
songTitle.text = song.title
|
||||
songText.text = song.artistName
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper!!.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper!!.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
|
||||
if (ColorUtil.isColorLight(ATHUtil.resolveColor(context, android.R.attr.windowBackground))) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
|
||||
}
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
updatePlayPauseColor()
|
||||
updateProgressTextColor()
|
||||
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
image.setColorFilter(colorFinal, PorterDuff.Mode.SRC_IN)
|
||||
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(colorFinal)), false)
|
||||
TintHelper.setTintAuto(playPauseButton, colorFinal, true)
|
||||
|
||||
volumeFragment?.setTintable(colorFinal)
|
||||
|
||||
}
|
||||
|
||||
private fun updatePlayPauseColor() {
|
||||
//playPauseButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
private fun updateProgressTextColor() {
|
||||
val color = MaterialValueHelper.getPrimaryTextColor(context, false)
|
||||
songTotalTime!!.setTextColor(color)
|
||||
songCurrentProgress!!.setTextColor(color)
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
//Ignore
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
//Ignore
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package code.name.monkey.retromusic.fragments.player.cardblur
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.glide.BlurTransformation
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment
|
||||
import kotlinx.android.synthetic.main.fragment_card_blur_player.*
|
||||
|
||||
class CardBlurFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
private lateinit var playbackControlsFragment: CardBlurPlaybackControlsFragment
|
||||
|
||||
|
||||
override fun onShow() {
|
||||
playbackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
playbackControlsFragment.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return Color.WHITE
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
playbackControlsFragment.setDark(color)
|
||||
lastColor = color
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, Color.WHITE, activity)
|
||||
|
||||
playerToolbar.setTitleTextColor(Color.WHITE)
|
||||
playerToolbar.setSubtitleTextColor(Color.WHITE)
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_card_blur_player, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as CardBlurPlaybackControlsFragment
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment?
|
||||
if (playerAlbumCoverFragment != null) {
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
playerAlbumCoverFragment.removeEffect()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
setTitleTextColor(Color.WHITE)
|
||||
setSubtitleTextColor(Color.WHITE)
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, Color.WHITE, activity)
|
||||
}.setOnMenuItemClickListener(this)
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updateIsFavorite()
|
||||
updateBlur()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateIsFavorite()
|
||||
updateBlur()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
playerToolbar.apply {
|
||||
title = song.title
|
||||
subtitle = song.artistName
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateBlur() {
|
||||
val activity = activity ?: return
|
||||
val blurAmount = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getInt("new_blur_amount", 25)
|
||||
|
||||
colorBackground!!.clearColorFilter()
|
||||
|
||||
GlideApp.with(activity)
|
||||
.asBitmapPalette()
|
||||
.load(RetroGlideExtension.getSongModel(MusicPlayerRemote.currentSong))
|
||||
.transition(RetroGlideExtension.getDefaultTransition())
|
||||
.transform(BlurTransformation.Builder(activity).blurRadius(blurAmount.toFloat()).build())
|
||||
.songOptions(MusicPlayerRemote.currentSong)
|
||||
.override(320, 480)
|
||||
.into(object : RetroMusicColoredTarget(colorBackground) {
|
||||
override fun onColorReady(color: Int) {
|
||||
if (color == defaultFooterColor) {
|
||||
colorBackground!!.setColorFilter(color)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||
super.onLoadFailed(errorDrawable)
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): PlayerFragment {
|
||||
return PlayerFragment()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
package code.name.monkey.retromusic.fragments.player.cardblur
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_card_blur_player_playback_controls.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
import kotlinx.android.synthetic.main.player_time.*
|
||||
|
||||
class CardBlurPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_card_blur_player_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
lastPlaybackControlsColor = Color.WHITE
|
||||
lastDisabledPlaybackControlsColor = ColorUtil.withAlpha(Color.WHITE, 0.3f)
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
updateProgressTextColor()
|
||||
|
||||
ViewUtil.setProgressDrawable(progressSlider, Color.WHITE, true)
|
||||
volumeFragment?.tintWhiteColor()
|
||||
}
|
||||
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.apply {
|
||||
TintHelper.setTintAuto(this, Color.WHITE, true)
|
||||
TintHelper.setTintAuto(this, Color.BLACK, false)
|
||||
setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
when {
|
||||
MusicPlayerRemote.isPlaying -> playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
else -> playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun updateProgressTextColor() {
|
||||
val color = MaterialValueHelper.getPrimaryTextColor(context, false)
|
||||
songTotalTime.setTextColor(color)
|
||||
songCurrentProgress.setTextColor(color)
|
||||
}
|
||||
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.rotation(360f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
if (playPauseButton != null) {
|
||||
playPauseButton!!.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,415 @@
|
|||
package code.name.monkey.retromusic.fragments.player.classic
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorSet
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.dialogs.SongShareDialog
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.menu.SongMenuHelper
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.model.lyrics.Lyrics
|
||||
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
|
||||
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
|
||||
import code.name.monkey.retromusic.adapter.song.PlayingQueueAdapter
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import code.name.monkey.retromusic.views.WidthFitSquareLayout
|
||||
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator
|
||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
|
||||
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
|
||||
import com.sothree.slidinguppanel.SlidingUpPanelLayout
|
||||
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState.ANCHORED
|
||||
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState.COLLAPSED
|
||||
import kotlinx.android.synthetic.main.fragment_classic_player.*
|
||||
import kotlinx.android.synthetic.main.fragment_classic_player_playback_controls.*
|
||||
|
||||
|
||||
class ClassicPlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks, SlidingUpPanelLayout.PanelSlideListener {
|
||||
override fun onPanelSlide(p0: View?, p1: Float) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPanelStateChanged(p0: View?, p1: SlidingUpPanelLayout.PanelState?, p2: SlidingUpPanelLayout.PanelState?) {
|
||||
when (p2) {
|
||||
COLLAPSED -> onPanelCollapsed(p0!!)
|
||||
ANCHORED -> playerSlidingLayout.panelState = COLLAPSED // this fixes a bug where the panel would get stuck for some reason
|
||||
else -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
classicPlaybackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
classicPlaybackControlsFragment.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
var wasExpanded = false
|
||||
if (playerSlidingLayout != null) {
|
||||
wasExpanded = playerSlidingLayout.panelState === SlidingUpPanelLayout.PanelState.EXPANDED
|
||||
playerSlidingLayout.panelState = COLLAPSED
|
||||
}
|
||||
|
||||
return wasExpanded
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return Color.WHITE
|
||||
}
|
||||
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
animateColorChange(color)
|
||||
classicPlaybackControlsFragment.setDark(ColorUtil.isColorLight(color))
|
||||
callbacks?.onPaletteColorChanged()
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
|
||||
var lastColor: Int = 0
|
||||
|
||||
lateinit var classicPlaybackControlsFragment: ClassicPlayerPlaybackControlsFragment
|
||||
private var playerAlbumCoverFragment: PlayerAlbumCoverFragment? = null
|
||||
|
||||
private lateinit var layoutManager: LinearLayoutManager
|
||||
private lateinit var playingQueueAdapter: PlayingQueueAdapter
|
||||
private lateinit var wrappedAdapter: RecyclerView.Adapter<*>
|
||||
private lateinit var recyclerViewDragDropManager: RecyclerViewDragDropManager
|
||||
|
||||
private var lyricsClassic: Lyrics? = null
|
||||
|
||||
private lateinit var impl: Impl
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
if (RetroUtil.isLandscape()) {
|
||||
impl = LandscapeImpl(this)
|
||||
} else {
|
||||
impl = PortraitImpl(this)
|
||||
}
|
||||
|
||||
return inflater.inflate(R.layout.fragment_classic_player, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
impl.init()
|
||||
|
||||
setUpPlayerToolbar()
|
||||
setUpSubFragments()
|
||||
setUpRecyclerView()
|
||||
|
||||
playerSlidingLayout.addPanelSlideListener(this)
|
||||
playerSlidingLayout.setAntiDragView(view.findViewById<View>(code.name.monkey.retromusic.R.id.draggableArea))
|
||||
|
||||
view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
view.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
impl.setUpPanelAndAlbumCoverHeight()
|
||||
}
|
||||
})
|
||||
|
||||
// for some reason the xml attribute doesn't get applied here.
|
||||
playingQueueCard.setCardBackgroundColor(ATHUtil.resolveColor(activity, code.name.monkey.retromusic.R.attr.cardBackgroundColor))
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.apply {
|
||||
inflateMenu(code.name.monkey.retromusic.R.menu.menu_player)
|
||||
setNavigationIcon(code.name.monkey.retromusic.R.drawable.ic_close_white_24dp)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
setOnMenuItemClickListener(this@ClassicPlayerFragment)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
classicPlaybackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as ClassicPlayerPlaybackControlsFragment
|
||||
playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment?.setCallbacks(this)
|
||||
|
||||
}
|
||||
|
||||
private fun setUpRecyclerView() {
|
||||
recyclerViewDragDropManager = RecyclerViewDragDropManager()
|
||||
val animator = RefactoredDefaultItemAnimator()
|
||||
|
||||
playingQueueAdapter = PlayingQueueAdapter(
|
||||
activity as AppCompatActivity,
|
||||
MusicPlayerRemote.playingQueue,
|
||||
MusicPlayerRemote.position,
|
||||
R.layout.item_queue)
|
||||
wrappedAdapter = recyclerViewDragDropManager.createWrappedAdapter(playingQueueAdapter)
|
||||
|
||||
layoutManager = LinearLayoutManager(activity)
|
||||
|
||||
playerRecyclerView.layoutManager = layoutManager
|
||||
playerRecyclerView.adapter = wrappedAdapter
|
||||
playerRecyclerView.itemAnimator = animator
|
||||
|
||||
recyclerViewDragDropManager.attachRecyclerView(playerRecyclerView)
|
||||
|
||||
layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
if (playerSlidingLayout != null) {
|
||||
playerSlidingLayout.removePanelSlideListener(this)
|
||||
}
|
||||
recyclerViewDragDropManager.release()
|
||||
|
||||
if (playerRecyclerView != null) {
|
||||
playerRecyclerView.itemAnimator = null
|
||||
playerRecyclerView.adapter = null
|
||||
}
|
||||
WrapperAdapterUtils.releaseAll(wrappedAdapter)
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
recyclerViewDragDropManager.cancelDrag()
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updateQueue()
|
||||
updateCurrentSong()
|
||||
updateIsFavorite()
|
||||
//updateLyrics()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateCurrentSong()
|
||||
updateIsFavorite()
|
||||
updateQueuePosition()
|
||||
//updateLyrics()
|
||||
}
|
||||
|
||||
override fun onQueueChanged() {
|
||||
updateQueue()
|
||||
}
|
||||
|
||||
override fun onMediaStoreChanged() {
|
||||
updateQueue()
|
||||
}
|
||||
|
||||
private fun updateQueue() {
|
||||
playingQueueAdapter.swapDataSet(MusicPlayerRemote.playingQueue, MusicPlayerRemote.position)
|
||||
playerQueueSubHeader.text = getUpNextAndQueueTime()
|
||||
if (playerSlidingLayout.panelState === COLLAPSED) {
|
||||
resetToCurrentPosition()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateQueuePosition() {
|
||||
playingQueueAdapter.setCurrent(MusicPlayerRemote.position)
|
||||
playerQueueSubHeader.text = getUpNextAndQueueTime()
|
||||
if (playerSlidingLayout.panelState === COLLAPSED) {
|
||||
resetToCurrentPosition()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCurrentSong() {
|
||||
impl.updateCurrentSong(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
private fun animateColorChange(newColor: Int) {
|
||||
impl.animateColorChange(newColor)
|
||||
lastColor = newColor
|
||||
}
|
||||
|
||||
private fun onPanelCollapsed(panel: View) {
|
||||
resetToCurrentPosition()
|
||||
}
|
||||
|
||||
private fun resetToCurrentPosition() {
|
||||
playerRecyclerView.stopScroll()
|
||||
layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BaseImpl(private val fragment: ClassicPlayerFragment) : Impl {
|
||||
fun createDefaultColorChangeAnimatorSet(color: Int): AnimatorSet {
|
||||
val backgroundAnimator: Animator
|
||||
backgroundAnimator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
val x = (fragment.classicPlaybackControlsFragment.playerPlayPauseFab.x + (fragment.classicPlaybackControlsFragment.playerPlayPauseFab.width / 2).toFloat() + fragment.classicPlaybackControlsFragment.view!!.x).toInt()
|
||||
val y = (fragment.classicPlaybackControlsFragment.playerPlayPauseFab.y + (fragment.classicPlaybackControlsFragment.playerPlayPauseFab.height / 2).toFloat() + fragment.classicPlaybackControlsFragment.view!!.y + fragment.classicPlaybackControlsFragment.playerProgressSlider.height.toFloat()).toInt()
|
||||
val startRadius = Math.max(fragment.classicPlaybackControlsFragment.playerPlayPauseFab.width / 2, fragment.classicPlaybackControlsFragment.playerPlayPauseFab.height / 2).toFloat()
|
||||
val endRadius = Math.max(fragment.colorBackground.width, fragment.colorBackground.height).toFloat()
|
||||
fragment.colorBackground.setBackgroundColor(color)
|
||||
ViewAnimationUtils.createCircularReveal(fragment.colorBackground, x, y, startRadius, endRadius)
|
||||
} else {
|
||||
ViewUtil.createBackgroundColorTransition(fragment.colorBackground, fragment.lastColor, color)
|
||||
}
|
||||
|
||||
val animatorSet = AnimatorSet()
|
||||
|
||||
animatorSet.play(backgroundAnimator)
|
||||
|
||||
if (!ATHUtil.isWindowBackgroundDark(fragment.activity!!)) {
|
||||
val adjustedLastColor = if (ColorUtil.isColorLight(fragment.lastColor)) ColorUtil.darkenColor(fragment.lastColor) else fragment.lastColor
|
||||
val adjustedNewColor = if (ColorUtil.isColorLight(color)) ColorUtil.darkenColor(color) else color
|
||||
val subHeaderAnimator = ViewUtil.createTextColorTransition(fragment.playerQueueSubHeader, adjustedLastColor, adjustedNewColor)
|
||||
animatorSet.play(subHeaderAnimator)
|
||||
}
|
||||
animatorSet.duration = ViewUtil.RETRO_MUSIC_ANIM_TIME.toLong()
|
||||
return animatorSet
|
||||
}
|
||||
|
||||
override fun animateColorChange(newColor: Int) {
|
||||
if (ATHUtil.isWindowBackgroundDark(fragment.activity!!)) {
|
||||
fragment.playerQueueSubHeader.setTextColor(ThemeStore.textColorSecondary(fragment.activity!!))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PortraitImpl(private val fragment: ClassicPlayerFragment) : BaseImpl(fragment) {
|
||||
override fun init() {
|
||||
currentSongViewHolder = MediaEntryViewHolder(fragment.view?.findViewById(R.id.currentSong)!!)
|
||||
|
||||
currentSongViewHolder?.apply {
|
||||
separator?.visibility = View.VISIBLE
|
||||
shortSeparator?.visibility = View.GONE
|
||||
image?.apply {
|
||||
scaleType = ImageView.ScaleType.CENTER
|
||||
setColorFilter(ATHUtil.resolveColor(fragment.activity!!, code.name.monkey.retromusic.R.attr.iconColor, ThemeStore.textColorSecondary(fragment.activity!!)), PorterDuff.Mode.SRC_IN)
|
||||
setImageResource(code.name.monkey.retromusic.R.drawable.ic_equalizer_white_24dp)
|
||||
|
||||
}
|
||||
imageTextContainer?.cardElevation = 0f
|
||||
itemView.setOnClickListener {
|
||||
// toggle the panel
|
||||
if (fragment.playerSlidingLayout.panelState == COLLAPSED) {
|
||||
fragment.playerSlidingLayout.panelState = SlidingUpPanelLayout.PanelState.EXPANDED
|
||||
} else if (fragment.playerSlidingLayout.panelState == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
||||
fragment.playerSlidingLayout.panelState = COLLAPSED
|
||||
}
|
||||
}
|
||||
menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu((fragment.activity as AppCompatActivity?)!!) {
|
||||
override val song: Song
|
||||
get() = currentSong
|
||||
|
||||
override val menuRes: Int
|
||||
get() = code.name.monkey.retromusic.R.menu.menu_item_playing_queue_song
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
code.name.monkey.retromusic.R.id.action_remove_from_playing_queue -> {
|
||||
MusicPlayerRemote.removeFromQueue(MusicPlayerRemote.position)
|
||||
return true
|
||||
}
|
||||
code.name.monkey.retromusic.R.id.action_share -> {
|
||||
SongShareDialog.create(song).show(fragment.fragmentManager!!, "SONG_SHARE_DIALOG")
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.onMenuItemClick(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateCurrentSong(song: Song) {
|
||||
currentSong = song
|
||||
currentSongViewHolder?.apply {
|
||||
title?.text = song.title
|
||||
text?.text = MusicUtil.getSongInfoString(song)
|
||||
}
|
||||
}
|
||||
|
||||
override fun animateColorChange(newColor: Int) {
|
||||
fragment.playerSlidingLayout.setBackgroundColor(fragment.lastColor)
|
||||
createDefaultColorChangeAnimatorSet(newColor).start()
|
||||
}
|
||||
|
||||
override fun setUpPanelAndAlbumCoverHeight() {
|
||||
val albumCoverContainer = fragment.view!!.findViewById<WidthFitSquareLayout>(R.id.albumCoverContainer)
|
||||
val availablePanelHeight = fragment.playerSlidingLayout.height - fragment.view!!.findViewById<View>(R.id.playerContent).height + ViewUtil.convertDpToPixel(8f, fragment.resources).toInt()
|
||||
val minPanelHeight = ViewUtil.convertDpToPixel(72f + 24f, fragment.resources).toInt()
|
||||
|
||||
if (availablePanelHeight < minPanelHeight) {
|
||||
albumCoverContainer.layoutParams.height = albumCoverContainer.height - (minPanelHeight - availablePanelHeight)
|
||||
albumCoverContainer.forceSquare(false)
|
||||
}
|
||||
fragment.playerSlidingLayout.panelHeight = Math.max(minPanelHeight, availablePanelHeight)
|
||||
|
||||
(fragment.activity as AbsSlidingMusicPanelActivity).setAntiDragView(fragment.playerSlidingLayout.findViewById<View>(R.id.playerPanel))
|
||||
|
||||
}
|
||||
|
||||
private var currentSongViewHolder: MediaEntryViewHolder? = null
|
||||
var currentSong = Song.emptySong
|
||||
|
||||
}
|
||||
|
||||
class LandscapeImpl(private val fragment: ClassicPlayerFragment) : BaseImpl(fragment) {
|
||||
override fun init() {
|
||||
|
||||
}
|
||||
|
||||
override fun updateCurrentSong(song: Song) {
|
||||
fragment.playerToolbar.title = song.title
|
||||
fragment.playerToolbar.subtitle = MusicUtil.getSongInfoString(song)
|
||||
}
|
||||
|
||||
override fun animateColorChange(newColor: Int) {
|
||||
fragment.playerSlidingLayout.setBackgroundColor(fragment.lastColor)
|
||||
|
||||
val animatorSet = createDefaultColorChangeAnimatorSet(newColor)
|
||||
animatorSet.play(ViewUtil.createBackgroundColorTransition(fragment.playerToolbar, fragment.lastColor, newColor)).with(ViewUtil.createBackgroundColorTransition(fragment.view?.findViewById(R.id.status_bar)!!, ColorUtil.darkenColor(fragment.lastColor), ColorUtil.darkenColor(newColor)))
|
||||
animatorSet.start()
|
||||
}
|
||||
|
||||
override fun setUpPanelAndAlbumCoverHeight() {
|
||||
val panelHeight = fragment.playerSlidingLayout.height - fragment.classicPlaybackControlsFragment.view?.height!!
|
||||
fragment.playerSlidingLayout.panelHeight = panelHeight
|
||||
(fragment.activity as AbsSlidingMusicPanelActivity).setAntiDragView(fragment.playerSlidingLayout.findViewById(R.id.playerPanel))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal interface Impl {
|
||||
fun init()
|
||||
|
||||
fun updateCurrentSong(song: Song)
|
||||
|
||||
fun animateColorChange(newColor: Int)
|
||||
|
||||
fun setUpPanelAndAlbumCoverHeight()
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
package code.name.monkey.retromusic.fragments.player.classic
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import androidx.annotation.NonNull
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.views.PlayPauseDrawable
|
||||
import kotlinx.android.synthetic.main.fragment_classic_player_playback_controls.*
|
||||
|
||||
|
||||
class ClassicPlayerPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
public override fun show() {
|
||||
playerPlayPauseFab.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.rotation(360f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
if (playerPlayPauseFab != null) {
|
||||
playerPlayPauseFab.scaleX = 0f
|
||||
playerPlayPauseFab.scaleY = 0f
|
||||
playerPlayPauseFab.rotation = 0f
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
|
||||
}
|
||||
|
||||
fun setDark(dark: Boolean) {
|
||||
if (dark) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true);
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false);
|
||||
}
|
||||
|
||||
//volumeFragment?.setTintableColor(lastPlaybackControlsColor)
|
||||
|
||||
updateRepeatState();
|
||||
updateShuffleState();
|
||||
updatePrevNextColor();
|
||||
updateProgressTextColor();
|
||||
}
|
||||
|
||||
private var playerFabPlayPauseDrawable: PlayPauseDrawable? = null
|
||||
|
||||
private var lastPlaybackControlsColor = 0
|
||||
private var lastDisabledPlaybackControlsColor = 0
|
||||
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
|
||||
|
||||
override fun onCreateView(@NonNull inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(code.name.monkey.retromusic.R.layout.fragment_classic_player_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setUpMusicControllers()
|
||||
updateProgressTextColor()
|
||||
|
||||
//volumeFragment = childFragmentManager.findFragmentById(R.id.volumeFragment) as VolumeFragment
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun updateProgressTextColor() {
|
||||
val color = MaterialValueHelper.getPrimaryTextColor(context, false)
|
||||
playerSongTotalTime.setTextColor(color)
|
||||
playerSongCurrentProgress.setTextColor(color)
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
val fabColor = Color.WHITE
|
||||
TintHelper.setTintAuto(playerPlayPauseFab, fabColor, true)
|
||||
|
||||
playerFabPlayPauseDrawable = PlayPauseDrawable(activity!!)
|
||||
|
||||
playerPlayPauseFab.setImageDrawable(playerFabPlayPauseDrawable) // Note: set the drawable AFTER TintHelper.setTintAuto() was called
|
||||
playerPlayPauseFab.setColorFilter(MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(fabColor)), PorterDuff.Mode.SRC_IN)
|
||||
playerPlayPauseFab.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
playerPlayPauseFab.post {
|
||||
if (playerPlayPauseFab != null) {
|
||||
playerPlayPauseFab.pivotX = (playerPlayPauseFab.width / 2).toFloat()
|
||||
playerPlayPauseFab.pivotY = (playerPlayPauseFab.height / 2).toFloat()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
playerNextButton.setOnClickListener { _ -> MusicPlayerRemote.playNextSong() }
|
||||
playerPrevButton.setOnClickListener { _ -> MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
playerNextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
playerPrevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
playerShuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> playerShuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> playerShuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
playerRepeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
playerRepeatButton.setImageResource(code.name.monkey.retromusic.R.drawable.ic_repeat_white_24dp)
|
||||
playerRepeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
playerRepeatButton.setImageResource(code.name.monkey.retromusic.R.drawable.ic_repeat_white_24dp)
|
||||
playerRepeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
playerRepeatButton.setImageResource(code.name.monkey.retromusic.R.drawable.ic_repeat_one_white_24dp)
|
||||
playerRepeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
val color = MaterialValueHelper.getPrimaryTextColor(context, false)
|
||||
playerProgressSlider.thumb.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
playerProgressSlider.progressDrawable.mutate().setColorFilter(Color.TRANSPARENT, PorterDuff.Mode.SRC_IN)
|
||||
|
||||
playerProgressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
playerProgressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(playerProgressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
|
||||
playerSongTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
playerSongCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState(false)
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState(true)
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
fun updatePlayPauseDrawableState(animate: Boolean) {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playerFabPlayPauseDrawable?.setPause(animate)
|
||||
} else {
|
||||
playerFabPlayPauseDrawable?.setPlay(animate)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,320 @@
|
|||
package code.name.monkey.retromusic.fragments.player.color
|
||||
|
||||
import android.animation.ArgbEvaluator
|
||||
import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.AsyncTask
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.palette.graphics.Palette
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.glide.palette.BitmapPaletteWrapper
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.model.lyrics.Lyrics
|
||||
import code.name.monkey.retromusic.activities.LyricsActivity
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import kotlinx.android.synthetic.main.fragment_color_player.*
|
||||
|
||||
class ColorFragment : AbsPlayerFragment() {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
override val paletteColor: Int
|
||||
get() = backgroundColor
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private var lastColor: Int = 0
|
||||
private var backgroundColor: Int = 0
|
||||
|
||||
private var playbackControlsFragment: ColorPlaybackControlsFragment? = null
|
||||
|
||||
private var valueAnimator: ValueAnimator? = null
|
||||
private var updateLyricsAsyncTask: AsyncTask<*, *, *>? = null
|
||||
private var lyricsColor: Lyrics? = null
|
||||
|
||||
override fun onShow() {
|
||||
playbackControlsFragment!!.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
playbackControlsFragment!!.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return lastColor
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
if (valueAnimator != null) {
|
||||
valueAnimator!!.cancel()
|
||||
valueAnimator = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_color_player, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
setupViews()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as ColorPlaybackControlsFragment?
|
||||
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
setOnMenuItemClickListener(this@ColorFragment)
|
||||
ToolbarContentTintHelper.colorizeToolbar(this, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
updateLyricsLocal()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
super.onServiceConnected()
|
||||
updateSong()
|
||||
updateLyricsLocal()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
|
||||
GlideApp.with(activity!!).asBitmapPalette()
|
||||
.load(RetroGlideExtension.getSongModel(MusicPlayerRemote.currentSong))
|
||||
.songOptions(MusicPlayerRemote.currentSong)
|
||||
.transition(RetroGlideExtension.getDefaultTransition())
|
||||
.into(object : RetroMusicColoredTarget(playerImage) {
|
||||
override fun onColorReady(color: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onResourceReady(resource: BitmapPaletteWrapper, glideAnimation: Transition<in BitmapPaletteWrapper>?) {
|
||||
super.onResourceReady(resource, glideAnimation)
|
||||
|
||||
val background = resource.palette.getColor()
|
||||
val accentColor = resource.palette.getContrastColor(background)
|
||||
|
||||
val palette = resource.palette
|
||||
val swatch = RetroColorUtil.getSwatch(palette)
|
||||
|
||||
val textColor = RetroColorUtil.getTextColor(palette)
|
||||
val backgroundColor = swatch.rgb
|
||||
|
||||
setColors(backgroundColor, textColor)
|
||||
}
|
||||
|
||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||
super.onLoadFailed(errorDrawable)
|
||||
val backgroundColor = defaultFooterColor
|
||||
val textColor = if (ColorUtil.isColorLight(defaultFooterColor))
|
||||
MaterialValueHelper.getPrimaryTextColor(context, true)
|
||||
else
|
||||
MaterialValueHelper.getPrimaryTextColor(context, false)
|
||||
|
||||
setColors(backgroundColor, textColor)
|
||||
}
|
||||
})
|
||||
|
||||
/*SongGlideRequest.Builder.from(Glide.with(activity), MusicPlayerRemote.currentSong)
|
||||
.checkIgnoreMediaStore(activity!!)
|
||||
.generatePalette(activity).build().dontAnimate()
|
||||
.into(object : RetroMusicColoredTarget(playerImage) {
|
||||
override fun onColorReady(color: Int) {
|
||||
//setColors(color);
|
||||
}
|
||||
|
||||
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
|
||||
super.onLoadFailed(e, errorDrawable)
|
||||
|
||||
val backgroundColor = defaultFooterColor
|
||||
val textColor = if (ColorUtil.isColorLight(defaultFooterColor))
|
||||
MaterialValueHelper.getPrimaryTextColor(context, true)
|
||||
else
|
||||
MaterialValueHelper.getPrimaryTextColor(context, false)
|
||||
|
||||
setColors(backgroundColor, textColor)
|
||||
}
|
||||
|
||||
override fun onResourceReady(resource: BitmapPaletteWrapper,
|
||||
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>?) {
|
||||
super.onResourceReady(resource, glideAnimation)
|
||||
*//* MediaNotificationProcessor processor = new MediaNotificationProcessor(getContext(),
|
||||
getContext());
|
||||
Palette.Builder builder = MediaNotificationProcessor
|
||||
.generatePalette(resource.getBitmap());
|
||||
|
||||
int backgroundColor = processor.getBackgroundColor(builder);
|
||||
int textColor = processor.getTextColor(builder);*//*
|
||||
|
||||
val palette = resource.palette
|
||||
val swatch = RetroColorUtil.getSwatch(palette)
|
||||
|
||||
val textColor = RetroColorUtil.getTextColor(palette)
|
||||
val backgroundColor = swatch.rgb
|
||||
|
||||
setColors(backgroundColor, textColor)
|
||||
}
|
||||
})*/
|
||||
}
|
||||
|
||||
private fun setColors(backgroundColor: Int, textColor: Int) {
|
||||
playbackControlsFragment!!.setDark(textColor, backgroundColor)
|
||||
|
||||
colorGradientBackground?.setBackgroundColor(backgroundColor)
|
||||
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, textColor, activity)
|
||||
|
||||
lastColor = textColor
|
||||
|
||||
this.backgroundColor = backgroundColor
|
||||
|
||||
if (playerActivity != null) {
|
||||
playerActivity!!.setLightNavigationBar(ColorUtil.isColorLight(backgroundColor))
|
||||
}
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
|
||||
}
|
||||
|
||||
private fun colorize(i: Int) {
|
||||
if (valueAnimator != null) {
|
||||
valueAnimator!!.cancel()
|
||||
}
|
||||
|
||||
valueAnimator = ValueAnimator.ofObject(ArgbEvaluator(), paletteColor, i)
|
||||
valueAnimator!!.addUpdateListener { animation ->
|
||||
colorGradientBackground?.setBackgroundColor(animation.animatedValue as Int)
|
||||
}
|
||||
valueAnimator!!.setDuration(ViewUtil.RETRO_MUSIC_ANIM_TIME.toLong()).start()
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private fun updateLyricsLocal() {
|
||||
if (updateLyricsAsyncTask != null) {
|
||||
updateLyricsAsyncTask!!.cancel(false)
|
||||
}
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
updateLyricsAsyncTask = object : AsyncTask<Void?, Void?, Lyrics?>() {
|
||||
override fun onPreExecute() {
|
||||
super.onPreExecute()
|
||||
lyricsColor = null
|
||||
playerToolbar.menu.removeItem(R.id.action_show_lyrics)
|
||||
}
|
||||
|
||||
override fun doInBackground(vararg params: Void?): Lyrics? {
|
||||
val data = MusicUtil.getLyrics(song)
|
||||
return if (TextUtils.isEmpty(data)) {
|
||||
null
|
||||
} else Lyrics.parse(song, data!!)
|
||||
}
|
||||
|
||||
override fun onPostExecute(l: Lyrics?) {
|
||||
lyricsColor = l
|
||||
if (lyricsColor == null) {
|
||||
lyricsView.setText(R.string.no_lyrics_found)
|
||||
} else {
|
||||
lyricsView.text = lyricsColor!!.text
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCancelled(s: Lyrics?) {
|
||||
onPostExecute(null)
|
||||
}
|
||||
}.execute()
|
||||
}
|
||||
|
||||
private fun setupViews() {
|
||||
lyricsView.setOnClickListener {
|
||||
if (lyricsContainer!!.visibility == View.GONE) {
|
||||
lyricsContainer!!.visibility = View.VISIBLE
|
||||
} else {
|
||||
lyricsContainer!!.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
playerImage.setOnClickListener {
|
||||
if (lyricsContainer!!.visibility == View.GONE) {
|
||||
lyricsContainer!!.visibility = View.VISIBLE
|
||||
} else {
|
||||
lyricsContainer!!.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
expand.setOnClickListener { startActivity(Intent(context, LyricsActivity::class.java)) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): ColorFragment {
|
||||
val args = Bundle()
|
||||
val fragment = ColorFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Palette.getContrastColor(background: Int): Int {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
fun Palette.getColor(): Int {
|
||||
return when {
|
||||
darkMutedSwatch != null -> darkMutedSwatch!!.rgb
|
||||
mutedSwatch != null -> mutedSwatch!!.rgb
|
||||
lightMutedSwatch != null -> lightMutedSwatch!!.rgb
|
||||
else -> Palette.Swatch(Color.BLACK, 1).rgb
|
||||
}
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
package code.name.monkey.retromusic.fragments.player.color
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.TintHelper
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import kotlinx.android.synthetic.main.fragment_player_playback_controls.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
|
||||
class ColorPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_color_player_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
title.text = song.title
|
||||
text.text = song.artistName
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
|
||||
fun setDark(textColor: Int, background: Int) {
|
||||
setDark(textColor)
|
||||
TintHelper.setTintAuto(playPauseButton, background, false)
|
||||
TintHelper.setTintAuto(playPauseButton, textColor, true)
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
lastPlaybackControlsColor = color
|
||||
lastDisabledPlaybackControlsColor = ColorUtil.withAlpha(color, 0.5f)
|
||||
|
||||
title!!.setTextColor(lastPlaybackControlsColor)
|
||||
text!!.setTextColor(lastDisabledPlaybackControlsColor)
|
||||
|
||||
setProgressBarColor(lastPlaybackControlsColor, lastDisabledPlaybackControlsColor)
|
||||
|
||||
volumeFragment?.setTintableColor(lastPlaybackControlsColor)
|
||||
|
||||
songCurrentProgress.setTextColor(lastDisabledPlaybackControlsColor)
|
||||
songTotalTime.setTextColor(lastDisabledPlaybackControlsColor)
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
}
|
||||
|
||||
private fun setProgressBarColor(c1: Int, c2: Int) {
|
||||
progressSlider.thumbTintList = ColorStateList.valueOf(c1)
|
||||
val ld = progressSlider.progressDrawable as LayerDrawable
|
||||
|
||||
val clipDrawableProgress = ld.findDrawableByLayerId(android.R.id.progress)
|
||||
clipDrawableProgress.setColorFilter(c1, PorterDuff.Mode.SRC_IN)
|
||||
|
||||
val clipDrawableBackground = ld.findDrawableByLayerId(android.R.id.background)
|
||||
clipDrawableBackground.setColorFilter(c2, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
TintHelper.setTintAuto(playPauseButton, Color.WHITE, true)
|
||||
TintHelper.setTintAuto(playPauseButton, Color.BLACK, false)
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
when {
|
||||
MusicPlayerRemote.isPlaying -> playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
else -> playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.rotation(360f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
playPauseButton.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider!!.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package code.name.monkey.retromusic.fragments.player.fit
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import kotlinx.android.synthetic.main.fragment_fit.*
|
||||
|
||||
|
||||
class FitFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
private lateinit var playbackControlsFragment: FitPlaybackControlsFragment
|
||||
|
||||
override fun onShow() {
|
||||
playbackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
playbackControlsFragment.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return ATHUtil.resolveColor(context, R.attr.iconColor)
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
playbackControlsFragment.setDark(color)
|
||||
lastColor = color
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
|
||||
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_fit, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as FitPlaybackControlsFragment
|
||||
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
playerAlbumCoverFragment.removeEffect()
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar!!.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
setOnMenuItemClickListener(this@FitFragment)
|
||||
ToolbarContentTintHelper.colorizeToolbar(this, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updateIsFavorite()
|
||||
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateIsFavorite()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): FitFragment {
|
||||
return FitFragment()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
package code.name.monkey.retromusic.fragments.player.fit
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import kotlinx.android.synthetic.main.fragment_player_playback_controls.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
|
||||
class FitPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_fit_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
|
||||
playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBonceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
title.text = song.title
|
||||
text.text = song.artistName
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
val colorBg = ATHUtil.resolveColor(activity, android.R.attr.colorBackground)
|
||||
if (ColorUtil.isColorLight(colorBg)) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
|
||||
}
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
|
||||
volumeFragment?.setTintable(colorFinal)
|
||||
|
||||
setFabColor(colorFinal)
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
}
|
||||
|
||||
private fun setFabColor(i: Int) {
|
||||
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(i)), false)
|
||||
TintHelper.setTintAuto(playPauseButton, i, true)
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton!!.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton!!.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.rotation(360f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
if (playPauseButton != null) {
|
||||
playPauseButton!!.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun showBonceAnimation() {
|
||||
playPauseButton.apply {
|
||||
clearAnimation()
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
visibility = View.VISIBLE
|
||||
pivotX = (width / 2).toFloat()
|
||||
pivotY = (height / 2).toFloat()
|
||||
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.scaleX(1.1f)
|
||||
.scaleY(1.1f)
|
||||
.withEndAction {
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(AccelerateInterpolator())
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.alpha(1f).start()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
package code.name.monkey.retromusic.fragments.player.flat
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.*
|
||||
|
||||
class FlatPlaybackControlsFragment : AbsPlayerControlsFragment(), Callback {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_flat_player_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
|
||||
public override fun hide() {
|
||||
playPauseButton!!.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
val colorBg = ATHUtil.resolveColor(activity, android.R.attr.colorBackground)
|
||||
val isDark = ColorUtil.isColorLight(colorBg)
|
||||
if (isDark) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
|
||||
}
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
|
||||
updateTextColors(colorFinal)
|
||||
volumeFragment?.setTintable(colorFinal)
|
||||
|
||||
ViewUtil.setProgressDrawable(progressSlider, colorFinal, true)
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
private fun updateTextColors(color: Int) {
|
||||
val isDark = ColorUtil.isColorLight(color)
|
||||
val darkColor = ColorUtil.darkenColor(color)
|
||||
val colorPrimary = MaterialValueHelper.getPrimaryTextColor(context, isDark)
|
||||
val colorSecondary = MaterialValueHelper.getSecondaryTextColor(context, ColorUtil.isColorLight(darkColor))
|
||||
|
||||
TintHelper.setTintAuto(playPauseButton!!, colorPrimary, false)
|
||||
TintHelper.setTintAuto(playPauseButton!!, color, true)
|
||||
|
||||
title.setBackgroundColor(color)
|
||||
title.setTextColor(colorPrimary)
|
||||
text.setBackgroundColor(darkColor)
|
||||
text.setTextColor(colorSecondary)
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
//TransitionManager.beginDelayedTransition(viewGroup, new ChangeText().setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN));
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
title.text = song.title
|
||||
text.text = song.artistName
|
||||
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider!!.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package code.name.monkey.retromusic.fragments.player.flat
|
||||
|
||||
import android.animation.ArgbEvaluator
|
||||
import android.animation.ValueAnimator
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import code.name.monkey.retromusic.views.DrawableGradient
|
||||
import kotlinx.android.synthetic.main.fragment_flat_player.*
|
||||
|
||||
class FlatPlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private var valueAnimator: ValueAnimator? = null
|
||||
private lateinit var flatPlaybackControlsFragment: FlatPlaybackControlsFragment
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
flatPlaybackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as FlatPlaybackControlsFragment
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.inflateMenu(R.menu.menu_player)
|
||||
playerToolbar.setNavigationOnClickListener { _ -> activity!!.onBackPressed() }
|
||||
playerToolbar.setOnMenuItemClickListener(this)
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context,
|
||||
R.attr.iconColor), activity)
|
||||
}
|
||||
|
||||
private fun colorize(i: Int) {
|
||||
if (valueAnimator != null) {
|
||||
valueAnimator!!.cancel()
|
||||
}
|
||||
|
||||
valueAnimator = ValueAnimator.ofObject(ArgbEvaluator(), android.R.color.transparent, i)
|
||||
valueAnimator!!.addUpdateListener { animation ->
|
||||
val drawable = DrawableGradient(GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
intArrayOf(animation.animatedValue as Int, android.R.color.transparent), 0)
|
||||
colorGradientBackground?.background = drawable
|
||||
|
||||
}
|
||||
valueAnimator!!.setDuration(ViewUtil.RETRO_MUSIC_ANIM_TIME.toLong()).start()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_flat_player, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpPlayerToolbar()
|
||||
setUpSubFragments()
|
||||
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
flatPlaybackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
flatPlaybackControlsFragment.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
val isLight = ColorUtil.isColorLight(paletteColor)
|
||||
return if (PreferenceUtil.getInstance().adaptiveColor)
|
||||
MaterialValueHelper.getPrimaryTextColor(context, isLight)
|
||||
else
|
||||
ATHUtil.resolveColor(context, R.attr.iconColor)
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
lastColor = color
|
||||
flatPlaybackControlsFragment.setDark(color)
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
|
||||
val isLight = ColorUtil.isColorLight(color)
|
||||
|
||||
//TransitionManager.beginDelayedTransition(mToolbar);
|
||||
val iconColor = if (PreferenceUtil.getInstance().adaptiveColor)
|
||||
MaterialValueHelper.getPrimaryTextColor(context!!, isLight)
|
||||
else
|
||||
ATHUtil.resolveColor(context!!, R.attr.iconColor)
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, iconColor, activity)
|
||||
if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
colorize(color)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
package code.name.monkey.retromusic.fragments.player.full
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.AsyncTask
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.SeekBar
|
||||
import androidx.core.content.ContextCompat
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_full_player_controls.*
|
||||
|
||||
/**
|
||||
* Created by hemanths on 20/09/17.
|
||||
*/
|
||||
|
||||
class FullPlaybackControlsFragment : AbsPlayerControlsFragment(), PopupMenu.OnMenuItemClickListener {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_full_player_controls, container, false)
|
||||
}
|
||||
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
|
||||
songTotalTime.setTextColor(Color.WHITE)
|
||||
songCurrentProgress.setTextColor(Color.WHITE)
|
||||
|
||||
title.isSelected = true
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper!!.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper!!.stop()
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
|
||||
public override fun hide() {
|
||||
playPauseButton.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
lastPlaybackControlsColor = Color.WHITE
|
||||
lastDisabledPlaybackControlsColor = ContextCompat.getColor(context!!, R.color.md_grey_500)
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
volumeFragment?.setTintableColor(colorFinal)
|
||||
text.setTextColor(colorFinal)
|
||||
|
||||
ViewUtil.setProgressDrawable(progressSlider, colorFinal, true)
|
||||
|
||||
playPauseButton.backgroundTintList = ColorStateList.valueOf(colorFinal)
|
||||
playPauseButton.imageTintList = ColorStateList.valueOf(MaterialValueHelper.getPrimaryTextColor(context, ColorUtil.isColorLight(colorFinal)))
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
title.text = song.title
|
||||
text.text = song.artistName
|
||||
updateIsFavorite()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
playPauseButton.post {
|
||||
if (playPauseButton != null) {
|
||||
playPauseButton.pivotX = (playPauseButton.width / 2).toFloat()
|
||||
playPauseButton.pivotY = (playPauseButton.height / 2).toFloat()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
setupFavourite()
|
||||
setupMenu()
|
||||
}
|
||||
|
||||
private fun setupMenu() {
|
||||
playerMenu.setOnClickListener {
|
||||
val popupMenu = PopupMenu(context!!, it)
|
||||
popupMenu.setOnMenuItemClickListener(this)
|
||||
popupMenu.inflate(R.menu.menu_player)
|
||||
popupMenu.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||
return (parentFragment as FullPlayerFragment).onMenuItemClick(item!!)
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider!!.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupFavourite() {
|
||||
songFavourite?.setOnClickListener {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleFavorite(song: Song) {
|
||||
MusicUtil.toggleFavorite(activity!!, song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
private var updateIsFavoriteTask: AsyncTask<*, *, *>? = null
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
fun updateIsFavorite() {
|
||||
if (updateIsFavoriteTask != null) {
|
||||
updateIsFavoriteTask!!.cancel(false)
|
||||
}
|
||||
updateIsFavoriteTask = object : AsyncTask<Song, Void, Boolean>() {
|
||||
override fun doInBackground(vararg params: Song): Boolean? {
|
||||
val activity = activity
|
||||
return if (activity != null) {
|
||||
MusicUtil.isFavorite(getActivity()!!, params[0])
|
||||
} else {
|
||||
cancel(false)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPostExecute(isFavorite: Boolean?) {
|
||||
val activity = activity
|
||||
if (activity != null) {
|
||||
val res = if (isFavorite!!)
|
||||
R.drawable.ic_favorite_white_24dp
|
||||
else
|
||||
R.drawable.ic_favorite_border_white_24dp
|
||||
|
||||
val drawable = TintHelper.createTintedDrawable(activity, res, Color.WHITE)
|
||||
songFavourite?.setImageDrawable(drawable)
|
||||
}
|
||||
}
|
||||
}.execute(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
package code.name.monkey.retromusic.fragments.player.full
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.extensions.hide
|
||||
import code.name.monkey.retromusic.extensions.show
|
||||
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.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.loaders.ArtistLoader
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics
|
||||
import code.name.monkey.retromusic.model.lyrics.Lyrics
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.synthetic.main.fragment_full.*
|
||||
|
||||
class FullPlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks, MusicProgressViewUpdateHelper.Callback {
|
||||
private lateinit var lyricsLayout: FrameLayout
|
||||
private lateinit var lyricsLine1: TextView
|
||||
private lateinit var lyricsLine2: TextView
|
||||
|
||||
private var lyrics: Lyrics? = null
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
if (!isLyricsLayoutBound()) return
|
||||
|
||||
if (!isLyricsLayoutVisible()) {
|
||||
hideLyricsLayout()
|
||||
return
|
||||
}
|
||||
|
||||
if (lyrics !is AbsSynchronizedLyrics) return
|
||||
val synchronizedLyrics = lyrics as AbsSynchronizedLyrics
|
||||
|
||||
lyricsLayout.visibility = View.VISIBLE
|
||||
lyricsLayout.alpha = 1f
|
||||
|
||||
val oldLine = lyricsLine2.text.toString()
|
||||
val line = synchronizedLyrics.getLine(progress)
|
||||
|
||||
if (oldLine != line || oldLine.isEmpty()) {
|
||||
lyricsLine1.text = oldLine
|
||||
lyricsLine2.text = line
|
||||
|
||||
lyricsLine1.visibility = View.VISIBLE
|
||||
lyricsLine2.visibility = View.VISIBLE
|
||||
|
||||
lyricsLine2.measure(View.MeasureSpec.makeMeasureSpec(lyricsLine2.measuredWidth, View.MeasureSpec.EXACTLY), View.MeasureSpec.UNSPECIFIED)
|
||||
val h: Float = lyricsLine2.measuredHeight.toFloat()
|
||||
|
||||
lyricsLine1.alpha = 1f
|
||||
lyricsLine1.translationY = 0f
|
||||
lyricsLine1.animate().alpha(0f).translationY(-h).duration = VISIBILITY_ANIM_DURATION
|
||||
|
||||
lyricsLine2.alpha = 0f
|
||||
lyricsLine2.translationY = h
|
||||
lyricsLine2.animate().alpha(1f).translationY(0f).duration = VISIBILITY_ANIM_DURATION
|
||||
}
|
||||
}
|
||||
|
||||
private fun isLyricsLayoutVisible(): Boolean {
|
||||
return lyrics != null && lyrics!!.isSynchronized && lyrics!!.isValid
|
||||
}
|
||||
|
||||
private fun isLyricsLayoutBound(): Boolean {
|
||||
return lyricsLayout != null && lyricsLine1 != null && lyricsLine2 != null
|
||||
}
|
||||
|
||||
private fun hideLyricsLayout() {
|
||||
lyricsLayout.animate().alpha(0f).setDuration( VISIBILITY_ANIM_DURATION).withEndAction(Runnable {
|
||||
if (!isLyricsLayoutBound()) return@Runnable
|
||||
lyricsLayout.visibility = View.GONE
|
||||
lyricsLine1.text = null
|
||||
lyricsLine2.text = null
|
||||
})
|
||||
}
|
||||
|
||||
override fun setLyrics(l: Lyrics?) {
|
||||
lyrics = l
|
||||
|
||||
if (!isLyricsLayoutBound()) return
|
||||
|
||||
if (!isLyricsLayoutVisible()) {
|
||||
hideLyricsLayout()
|
||||
return
|
||||
}
|
||||
|
||||
lyricsLine1.text = null
|
||||
lyricsLine2.text = null
|
||||
|
||||
lyricsLayout.visibility = View.VISIBLE
|
||||
lyricsLayout.animate().alpha(1f).duration = VISIBILITY_ANIM_DURATION
|
||||
}
|
||||
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
private lateinit var fullPlaybackControlsFragment: FullPlaybackControlsFragment
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.apply {
|
||||
setNavigationIcon(R.drawable.ic_close_white_24dp)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_full, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
lyricsLayout = view.findViewById(R.id.player_lyrics)
|
||||
lyricsLine1 = view.findViewById(R.id.player_lyrics_line1)
|
||||
lyricsLine2 = view.findViewById(R.id.player_lyrics_line2)
|
||||
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
setupArtist()
|
||||
nextSong.isSelected = true
|
||||
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
private fun setupArtist() {
|
||||
artistImage.setOnClickListener {
|
||||
NavigationUtil.goToArtist(activity!!, MusicPlayerRemote.currentSong.artistId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
fullPlaybackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as FullPlaybackControlsFragment
|
||||
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
playerAlbumCoverFragment.removeSlideEffect()
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return Color.WHITE
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
lastColor = color
|
||||
fullPlaybackControlsFragment.setDark(color)
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, Color.WHITE, activity)
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
fullPlaybackControlsFragment.onFavoriteToggled()
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
super.onServiceConnected()
|
||||
updateArtistImage()
|
||||
updateLabel()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateArtistImage()
|
||||
updateLabel()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
progressViewUpdateHelper.stop()
|
||||
compositeDisposable.dispose()
|
||||
}
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
|
||||
private fun updateArtistImage() {
|
||||
compositeDisposable.addAll(ArtistLoader.getArtist(context!!, MusicPlayerRemote.currentSong.artistId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
GlideApp.with(activity!!)
|
||||
.asBitmapPalette()
|
||||
.load(RetroGlideExtension.getArtistModel(it))
|
||||
.transition(RetroGlideExtension.getDefaultTransition())
|
||||
.artistOptions(it)
|
||||
.dontAnimate()
|
||||
.into(object : RetroMusicColoredTarget(artistImage) {
|
||||
override fun onColorReady(color: Int) {
|
||||
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
override fun onQueueChanged() {
|
||||
super.onQueueChanged()
|
||||
if (MusicPlayerRemote.playingQueue.isNotEmpty()) updateLabel()
|
||||
}
|
||||
|
||||
private fun updateLabel() {
|
||||
(MusicPlayerRemote.playingQueue.size - 1).apply {
|
||||
println("Log Position $this ${MusicPlayerRemote.position}")
|
||||
if (this == (MusicPlayerRemote.position)) {
|
||||
nextSongLabel.setText(R.string.last_song)
|
||||
nextSong.hide()
|
||||
} else {
|
||||
val title = MusicPlayerRemote.playingQueue[MusicPlayerRemote.position + 1].title
|
||||
nextSongLabel.setText(R.string.next_song)
|
||||
nextSong.apply {
|
||||
text = title
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
package code.name.monkey.retromusic.fragments.player.lockscreen
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
import kotlinx.android.synthetic.main.player_time.*
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
class LockScreenPlayerControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_lock_screen_playback_controls, container, false)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
|
||||
title.text = song.title
|
||||
text.text = String.format("%s - %s", song.artistName, song.albumName)
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper!!.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper!!.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
|
||||
val colorBg = ATHUtil.resolveColor(context!!, android.R.attr.colorBackground)
|
||||
if (ColorUtil.isColorLight(colorBg)) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(context!!, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(context!!, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(context!!, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false)
|
||||
}
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.textColorSecondary(context!!)
|
||||
}
|
||||
volumeFragment?.setTintable(colorFinal)
|
||||
ViewUtil.setProgressDrawable(progressSlider, ColorUtil.stripAlpha(colorFinal), true)
|
||||
|
||||
updatePrevNextColor()
|
||||
|
||||
val isDark = ColorUtil.isColorLight(color)
|
||||
text!!.setTextColor(color)
|
||||
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(context!!, isDark), false)
|
||||
TintHelper.setTintAuto(playPauseButton, color, true)
|
||||
}
|
||||
|
||||
fun setProgressBarColor(progressBar: SeekBar?, newColor: Int) {
|
||||
TintHelper.setTintAuto(progressBar!!, newColor, false)
|
||||
//LayerDrawable ld = (LayerDrawable) progressBar.getProgressDrawable();
|
||||
//ClipDrawable clipDrawable = (ClipDrawable) ld.findDrawableByLayerId(android.R.id.progress);
|
||||
//clipDrawable.setColorFilter(newColor, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpProgressSlider()
|
||||
setUpShuffleButton()
|
||||
setUpRepeatButton()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.rotation(360f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
if (playPauseButton != null) {
|
||||
playPauseButton!!.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
package code.name.monkey.retromusic.fragments.player.material
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_material_playback_controls.*
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
class MaterialControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_material_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
title.text = song.title
|
||||
text.text = song.artistName
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
val colorBg = ATHUtil.resolveColor(context, android.R.attr.colorBackground)
|
||||
if (ColorUtil.isColorLight(colorBg)) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(context, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(context, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(context, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false)
|
||||
}
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
lastPlaybackControlsColor = color
|
||||
color
|
||||
} else {
|
||||
ThemeStore.textColorSecondary(context!!)
|
||||
}
|
||||
text.setTextColor(colorFinal)
|
||||
ViewUtil.setProgressDrawable(progressSlider, ColorUtil.stripAlpha(colorFinal), true)
|
||||
|
||||
volumeFragment?.setTintable(colorFinal)
|
||||
|
||||
updatePlayPauseColor()
|
||||
updatePrevNextColor()
|
||||
}
|
||||
|
||||
private fun updatePlayPauseColor() {
|
||||
playPauseButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_big);
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_big);
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider!!.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package code.name.monkey.retromusic.fragments.player.material
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment
|
||||
import kotlinx.android.synthetic.main.fragment_material.*
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
class MaterialFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
private lateinit var playbackControlsFragment: MaterialControlsFragment
|
||||
|
||||
override fun onShow() {
|
||||
playbackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
playbackControlsFragment.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return ATHUtil.resolveColor(context!!, R.attr.iconColor)
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
playbackControlsFragment.setDark(color)
|
||||
lastColor = color
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context!!, R.attr.iconColor), activity)
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_material, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as MaterialControlsFragment
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
setOnMenuItemClickListener(this@MaterialFragment)
|
||||
ToolbarContentTintHelper.colorizeToolbar(this, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updateIsFavorite()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateIsFavorite()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): PlayerFragment {
|
||||
return PlayerFragment()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package code.name.monkey.retromusic.fragments.player.normal
|
||||
|
||||
import android.animation.ArgbEvaluator
|
||||
import android.animation.ValueAnimator
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import code.name.monkey.retromusic.views.DrawableGradient
|
||||
import kotlinx.android.synthetic.main.fragment_player.*
|
||||
|
||||
|
||||
class PlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
|
||||
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
private lateinit var playbackControlsFragment: PlayerPlaybackControlsFragment
|
||||
private var valueAnimator: ValueAnimator? = null
|
||||
|
||||
|
||||
private fun colorize(i: Int) {
|
||||
if (valueAnimator != null) {
|
||||
valueAnimator!!.cancel()
|
||||
}
|
||||
|
||||
valueAnimator = ValueAnimator.ofObject(ArgbEvaluator(), android.R.color.transparent, i)
|
||||
valueAnimator!!.addUpdateListener { animation ->
|
||||
val drawable = DrawableGradient(GradientDrawable.Orientation.TOP_BOTTOM, intArrayOf(animation.animatedValue as Int, android.R.color.transparent), 0)
|
||||
colorGradientBackground?.background = drawable
|
||||
}
|
||||
valueAnimator!!.setDuration(ViewUtil.RETRO_MUSIC_ANIM_TIME.toLong()).start()
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
playbackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
playbackControlsFragment.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return ATHUtil.resolveColor(context, R.attr.iconColor)
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
playbackControlsFragment.setDark(color)
|
||||
lastColor = color
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
|
||||
|
||||
if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
colorize(color)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun getCutOff(): Int {
|
||||
return if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) 20 else 0
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_player, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
snowfall.visibility = if (PreferenceUtil.getInstance().isSnowFall) View.VISIBLE else View.GONE
|
||||
|
||||
|
||||
//val display = activity?.windowManager?.defaultDisplay
|
||||
//val outMetrics = DisplayMetrics()
|
||||
//display?.getMetrics(outMetrics)
|
||||
|
||||
//val density = resources.displayMetrics.density
|
||||
//val dpWidth = outMetrics.widthPixels / density
|
||||
|
||||
//playerAlbumCoverContainer?.layoutParams?.height = RetroUtil.convertDpToPixel((dpWidth - getCutOff()), context!!).toInt()
|
||||
}
|
||||
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as PlayerPlaybackControlsFragment
|
||||
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.inflateMenu(R.menu.menu_player)
|
||||
playerToolbar.setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
playerToolbar.setOnMenuItemClickListener(this)
|
||||
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updateIsFavorite()
|
||||
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
updateIsFavorite()
|
||||
}
|
||||
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): PlayerFragment {
|
||||
return PlayerFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
package code.name.monkey.retromusic.fragments.player.normal
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_player_playback_controls.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
|
||||
class PlayerPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_player_playback_controls, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
|
||||
playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBonceAnimation(playPauseButton)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
val colorBg = ATHUtil.resolveColor(context!!, android.R.attr.colorBackground)
|
||||
if (ColorUtil.isColorLight(colorBg)) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(context!!, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(context!!, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(context!!, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false)
|
||||
}
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
|
||||
|
||||
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(context!!, ColorUtil.isColorLight(colorFinal)), false)
|
||||
TintHelper.setTintAuto(playPauseButton, colorFinal, true)
|
||||
ViewUtil.setProgressDrawable(progressSlider, colorFinal)
|
||||
|
||||
volumeFragment?.setTintable(colorFinal)
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
title.text = song.title
|
||||
text.text = song.artistName
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.rotation(360f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
if (playPauseButton != null) {
|
||||
playPauseButton!!.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
package code.name.monkey.retromusic.fragments.player.plain
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_plain_controls_fragment.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class PlainPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_plain_controls_fragment, container, false)
|
||||
}
|
||||
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
|
||||
playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBonceAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
val colorBg = ATHUtil.resolveColor(context!!, android.R.attr.colorBackground)
|
||||
if (ColorUtil.isColorLight(colorBg)) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(context!!, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(context!!, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(context!!, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false)
|
||||
}
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
volumeFragment?.setTintable(colorFinal)
|
||||
|
||||
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(context!!, ColorUtil.isColorLight(colorFinal)), false)
|
||||
TintHelper.setTintAuto(playPauseButton, colorFinal, true)
|
||||
setProgressBarColor(colorFinal)
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
}
|
||||
|
||||
private fun setProgressBarColor(newColor: Int) {
|
||||
progressSlider.thumbTintList = ColorStateList.valueOf(newColor)
|
||||
ViewUtil.setProgressDrawable(progressSlider, newColor)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.rotation(360f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
if (playPauseButton != null) {
|
||||
playPauseButton!!.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
|
||||
MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun showBonceAnimation() {
|
||||
playPauseButton.apply {
|
||||
clearAnimation()
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
visibility = View.VISIBLE
|
||||
pivotX = (width / 2).toFloat()
|
||||
pivotY = (height / 2).toFloat()
|
||||
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.scaleX(1.1f)
|
||||
.scaleY(1.1f)
|
||||
.withEndAction {
|
||||
animate().setDuration(200)
|
||||
.setInterpolator(AccelerateInterpolator())
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.alpha(1f).start()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package code.name.monkey.retromusic.fragments.player.plain
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import kotlinx.android.synthetic.main.fragment_plain_player.*
|
||||
|
||||
class PlainPlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private lateinit var plainPlaybackControlsFragment: PlainPlaybackControlsFragment
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
playerTitle.text = song.title
|
||||
playerText.text = song.artistName
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
super.onServiceConnected()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_plain_player, container, false)
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
setOnMenuItemClickListener(this@PlainPlayerFragment)
|
||||
ToolbarContentTintHelper.colorizeToolbar(this, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
plainPlaybackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as PlainPlaybackControlsFragment
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
plainPlaybackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
plainPlaybackControlsFragment.hide()
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return ATHUtil.resolveColor(context!!, R.attr.iconColor)
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
plainPlaybackControlsFragment.setDark(color)
|
||||
lastColor = color
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar!!, ATHUtil.resolveColor(context!!, R.attr.iconColor), activity)
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
package code.name.monkey.retromusic.fragments.player.simple
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import kotlinx.android.synthetic.main.fragment_simple_controls_fragment.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class SimplePlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_simple_controls_fragment, container, false)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
|
||||
playPauseButton.setOnClickListener {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
MusicPlayerRemote.pauseSong()
|
||||
} else {
|
||||
MusicPlayerRemote.resumePlaying()
|
||||
}
|
||||
showBonceAnimation(playPauseButton)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
title.text = song.title
|
||||
text.text = song.artistName
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
|
||||
}
|
||||
|
||||
public override fun show() {
|
||||
playPauseButton!!.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.rotation(360f)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.start()
|
||||
}
|
||||
|
||||
public override fun hide() {
|
||||
if (playPauseButton != null) {
|
||||
playPauseButton!!.apply {
|
||||
scaleX = 0f
|
||||
scaleY = 0f
|
||||
rotation = 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
songCurrentProgress!!.text = String.format("%s / %s", MusicUtil.getReadableDurationString(progress.toLong()),
|
||||
MusicUtil.getReadableDurationString(total.toLong()))
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
val colorBg = ATHUtil.resolveColor(context!!, android.R.attr.colorBackground)
|
||||
if (ColorUtil.isColorLight(colorBg)) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(context!!, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(context!!, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(context!!, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false)
|
||||
}
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
|
||||
volumeFragment?.setTintable(colorFinal)
|
||||
|
||||
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(context!!, ColorUtil.isColorLight(colorFinal)), false)
|
||||
TintHelper.setTintAuto(playPauseButton, colorFinal, true)
|
||||
text.setTextColor(colorFinal)
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package code.name.monkey.retromusic.fragments.player.simple
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import kotlinx.android.synthetic.main.fragment_simple_player.*
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class SimplePlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
private lateinit var simplePlaybackControlsFragment: SimplePlaybackControlsFragment
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
return inflater.inflate(R.layout.fragment_simple_player, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpSubFragments()
|
||||
setUpPlayerToolbar()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
simplePlaybackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as SimplePlaybackControlsFragment
|
||||
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
simplePlaybackControlsFragment.show()
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
simplePlaybackControlsFragment.hide()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return ATHUtil.resolveColor(context!!, R.attr.iconColor)
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
lastColor = color
|
||||
callbacks!!.onPaletteColorChanged()
|
||||
simplePlaybackControlsFragment.setDark(color)
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context!!, R.attr.iconColor), activity)
|
||||
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
setOnMenuItemClickListener(this@SimplePlayerFragment)
|
||||
ToolbarContentTintHelper.colorizeToolbar(this, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* 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.fragments.player.slide
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.*
|
||||
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.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
|
||||
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import kotlinx.android.synthetic.main.fragment_slide_player.*
|
||||
|
||||
/**
|
||||
* Created by hemanths on 3/15/19
|
||||
*/
|
||||
class SlidePlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Callback {
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return Color.WHITE
|
||||
}
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_slide_player, container, false)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
updateIsFavorite()
|
||||
}
|
||||
|
||||
override fun onQueueChanged() {
|
||||
super.onQueueChanged()
|
||||
updateQueue()
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
updatePlayPauseDrawableState()
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updateSong()
|
||||
updateIsFavorite()
|
||||
updateQueue()
|
||||
}
|
||||
|
||||
private fun updateQueue() {
|
||||
songAdapter.swapDataSet(MusicPlayerRemote.playingQueue)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private fun updatePlayPauseDrawableState() {
|
||||
if (MusicPlayerRemote.isPlaying) {
|
||||
albumCoverContainer.cardElevation = 24.0f
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
|
||||
} else {
|
||||
albumCoverContainer.cardElevation = 0.0f
|
||||
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
title.text = song.title
|
||||
text.text = song.artistName
|
||||
|
||||
GlideApp.with(activity!!).asBitmapPalette()
|
||||
.load(RetroGlideExtension.getSongModel(song))
|
||||
.songOptions(song)
|
||||
.transition(RetroGlideExtension.getDefaultTransition())
|
||||
.into(object : RetroMusicColoredTarget(playerImage) {
|
||||
override fun onColorReady(color: Int) {
|
||||
setColor(color)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setColor(color: Int) {
|
||||
lastColor = color
|
||||
val colorBg = ATHUtil.resolveColor(context!!, android.R.attr.colorBackground)
|
||||
if (ColorUtil.isColorLight(colorBg)) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(context!!, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(context!!, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(context!!, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false)
|
||||
}
|
||||
|
||||
val colorFinal = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
|
||||
|
||||
text.setTextColor(colorFinal)
|
||||
playerQueueSubHeader.setTextColor(colorFinal)
|
||||
TintHelper.setTintAuto(playPauseButton, lastPlaybackControlsColor, false)
|
||||
ViewUtil.setProgressDrawable(progressSlider, colorFinal)
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
updatePrevNextColor()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
setUpPlayerToolbar()
|
||||
(activity as AbsSlidingMusicPanelActivity).setAntiDragView(recyclerView)
|
||||
playerQueueSubHeader.setTextColor(ThemeStore.accentColor(context!!))
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpPlayPauseFab()
|
||||
setUpPrevNext()
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
setUpRecyclerView()
|
||||
}
|
||||
|
||||
private lateinit var songAdapter: SimpleSongAdapter
|
||||
|
||||
private fun setUpRecyclerView() {
|
||||
songAdapter = SimpleSongAdapter(context = activity as AppCompatActivity,
|
||||
songs = ArrayList(), i = R.layout.item_song, useNumbers = true)
|
||||
recyclerView.apply {
|
||||
adapter = songAdapter
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpProgressSlider() {
|
||||
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
MusicPlayerRemote.seekTo(progress)
|
||||
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressSlider.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
|
||||
animator.duration = AbsPlayerControlsFragment.SLIDER_ANIMATION_TIME
|
||||
animator.interpolator = LinearInterpolator()
|
||||
animator.start()
|
||||
|
||||
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||
}
|
||||
|
||||
private fun setUpPlayPauseFab() {
|
||||
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
private fun setUpPrevNext() {
|
||||
updatePrevNextColor()
|
||||
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
|
||||
previousButton.setOnClickListener { MusicPlayerRemote.back() }
|
||||
}
|
||||
|
||||
private fun updatePrevNextColor() {
|
||||
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
override fun onPlayStateChanged() {
|
||||
updatePlayPauseDrawableState()
|
||||
}
|
||||
|
||||
override fun onRepeatModeChanged() {
|
||||
updateRepeatState()
|
||||
}
|
||||
|
||||
override fun onShuffleModeChanged() {
|
||||
updateShuffleState()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.inflateMenu(R.menu.menu_player)
|
||||
playerToolbar.setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
playerToolbar.setOnMenuItemClickListener(this)
|
||||
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, Color.WHITE, activity)
|
||||
}
|
||||
|
||||
fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
|
||||
val smoothScroller = object : LinearSmoothScroller(this.context) {
|
||||
override fun getVerticalSnapPreference(): Int {
|
||||
return snapMode
|
||||
}
|
||||
|
||||
override fun getHorizontalSnapPreference(): Int {
|
||||
return snapMode
|
||||
}
|
||||
}
|
||||
smoothScroller.targetPosition = position
|
||||
this.layoutManager?.startSmoothScroll(smoothScroller)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package code.name.monkey.retromusic.fragments.player.tiny
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||
import kotlinx.android.synthetic.main.fragment_tiny_controls_fragment.*
|
||||
|
||||
class TinyPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
||||
override fun show() {
|
||||
|
||||
}
|
||||
|
||||
override fun hide() {
|
||||
|
||||
}
|
||||
|
||||
override fun setUpProgressSlider() {
|
||||
|
||||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
if (ColorUtil.isColorLight(color)) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true);
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false);
|
||||
}
|
||||
|
||||
updateRepeatState();
|
||||
updateShuffleState();
|
||||
}
|
||||
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
|
||||
}
|
||||
|
||||
private var lastPlaybackControlsColor: Int = 0
|
||||
private var lastDisabledPlaybackControlsColor: Int = 0
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_tiny_controls_fragment, container, false);
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpMusicControllers()
|
||||
}
|
||||
|
||||
private fun setUpMusicControllers() {
|
||||
setUpRepeatButton()
|
||||
setUpShuffleButton()
|
||||
setUpProgressSlider()
|
||||
}
|
||||
|
||||
private fun setUpShuffleButton() {
|
||||
playerShuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
|
||||
}
|
||||
|
||||
private fun setUpRepeatButton() {
|
||||
playerRepeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
|
||||
}
|
||||
|
||||
override fun updateShuffleState() {
|
||||
when (MusicPlayerRemote.shuffleMode) {
|
||||
MusicService.SHUFFLE_MODE_SHUFFLE -> playerShuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
else -> playerShuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateRepeatState() {
|
||||
when (MusicPlayerRemote.repeatMode) {
|
||||
MusicService.REPEAT_MODE_NONE -> {
|
||||
playerRepeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
playerRepeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_ALL -> {
|
||||
playerRepeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
|
||||
playerRepeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
MusicService.REPEAT_MODE_THIS -> {
|
||||
playerRepeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
|
||||
playerRepeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
package code.name.monkey.retromusic.fragments.player.tiny
|
||||
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ObjectAnimator
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
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.appthemehelper.util.ToolbarContentTintHelper
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
||||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.fragments.MiniPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import kotlinx.android.synthetic.main.fragment_tiny_player.*
|
||||
|
||||
class TinyPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Callback {
|
||||
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||
progressBar.max = total
|
||||
|
||||
val animator = ObjectAnimator.ofInt(progressBar, "progress", progress)
|
||||
|
||||
val animatorSet = AnimatorSet()
|
||||
animatorSet.playSequentially(animator)
|
||||
|
||||
animatorSet.duration = 1500
|
||||
animatorSet.interpolator = LinearInterpolator()
|
||||
animatorSet.start()
|
||||
|
||||
playerSongTotalTime.text = String.format("%s/%s", MusicUtil.getReadableDurationString(total.toLong()),
|
||||
MusicUtil.getReadableDurationString(progress.toLong()))
|
||||
}
|
||||
|
||||
|
||||
override fun playerToolbar(): Toolbar {
|
||||
return playerToolbar
|
||||
}
|
||||
|
||||
override fun onShow() {
|
||||
|
||||
}
|
||||
|
||||
override fun onHide() {
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toolbarIconColor(): Int {
|
||||
return MaterialValueHelper.getSecondaryTextColor(context, ColorUtil.isColorLight(lastColor))
|
||||
}
|
||||
|
||||
private var lastColor: Int = 0
|
||||
override val paletteColor: Int
|
||||
get() = lastColor
|
||||
|
||||
override fun onColorChanged(color: Int) {
|
||||
val lastColor = if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
color
|
||||
} else {
|
||||
ThemeStore.accentColor(context!!)
|
||||
}
|
||||
callbacks?.onPaletteColorChanged()
|
||||
tinyPlaybackControlsFragment.setDark(lastColor)
|
||||
|
||||
TintHelper.setTintAuto(progressBar, lastColor, false)
|
||||
|
||||
val iconColor = MaterialValueHelper.getSecondaryTextColor(context, ColorUtil.isColorLight(lastColor))
|
||||
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, iconColor, activity)
|
||||
}
|
||||
|
||||
override fun onFavoriteToggled() {
|
||||
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
|
||||
private lateinit var tinyPlaybackControlsFragment: TinyPlaybackControlsFragment
|
||||
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
progressViewUpdateHelper.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
progressViewUpdateHelper.stop()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
songTitle.text = song.title
|
||||
songText.text = String.format("%s \nby -%s", song.albumName, song.artistName)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_tiny_player, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
progressBar.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||
progressBar.setOnTouchListener(MiniPlayerFragment.FlingPlayBackController(activity!!))
|
||||
|
||||
setUpPlayerToolbar()
|
||||
setUpSubFragments()
|
||||
}
|
||||
|
||||
private fun setUpSubFragments() {
|
||||
tinyPlaybackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as TinyPlaybackControlsFragment
|
||||
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||
playerAlbumCoverFragment.setCallbacks(this)
|
||||
|
||||
}
|
||||
|
||||
private fun setUpPlayerToolbar() {
|
||||
playerToolbar.apply {
|
||||
inflateMenu(R.menu.menu_player)
|
||||
setNavigationOnClickListener { activity!!.onBackPressed() }
|
||||
setOnMenuItemClickListener(this@TinyPlayerFragment)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toggleFavorite(song: Song) {
|
||||
super.toggleFavorite(song)
|
||||
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||
updateIsFavorite()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected() {
|
||||
super.onServiceConnected()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
override fun onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged()
|
||||
updateSong()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.retromusic.preferences.*
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
abstract class AbsSettingsFragment : PreferenceFragmentCompat() {
|
||||
internal fun showProToastAndNavigate(message: String) {
|
||||
Toast.makeText(context, "$message is Pro version feature.", Toast.LENGTH_SHORT).show()
|
||||
|
||||
NavigationUtil.goToProVersion(activity!!)
|
||||
}
|
||||
|
||||
protected fun setSummary(preference: Preference) {
|
||||
setSummary(preference, PreferenceManager
|
||||
.getDefaultSharedPreferences(preference.context)
|
||||
.getString(preference.key, "")!!)
|
||||
}
|
||||
|
||||
internal fun setSummary(preference: Preference, value: Any) {
|
||||
val stringValue = value.toString()
|
||||
if (preference is ListPreference) {
|
||||
val index = preference.findIndexOfValue(stringValue)
|
||||
preference.setSummary(if (index >= 0) preference.entries[index] else null)
|
||||
} else {
|
||||
preference.summary = stringValue
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun invalidateSettings()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setDivider(ColorDrawable(Color.TRANSPARENT))
|
||||
listView.setBackgroundColor(ThemeStore.primaryColor(context!!))
|
||||
listView.overScrollMode = View.OVER_SCROLL_NEVER
|
||||
listView.setPadding(0, 0, 0, 0)
|
||||
listView.setPaddingRelative(0, 0, 0, 0)
|
||||
invalidateSettings()
|
||||
}
|
||||
|
||||
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||
var dialogFragment: DialogFragment? = null
|
||||
if (preference is NowPlayingScreenPreference) {
|
||||
dialogFragment = NowPlayingScreenPreferenceDialog.newInstance(preference.key);
|
||||
} else if (preference is AlbumCoverStylePreference) {
|
||||
dialogFragment = AlbumCoverStylePreferenceDialog.newInstance(preference.key);
|
||||
}
|
||||
if (preference is MaterialListPreference) {
|
||||
val entries = preference.entries
|
||||
|
||||
dialogFragment = MaterialListPreferenceDialog.newInstance(preference)
|
||||
}
|
||||
if (preference is BlacklistPreference) {
|
||||
dialogFragment = BlacklistPreferenceDialog.newInstance(preference.key)
|
||||
}
|
||||
if (dialogFragment != null) {
|
||||
// The dialog was created (it was one of our custom Preferences), show the dialog for it
|
||||
dialogFragment.setTargetFragment(this, 0);
|
||||
dialogFragment.show(this.fragmentManager!!, "android.support.v7.preference.PreferenceFragment.DIALOG");
|
||||
} else {
|
||||
// Dialog creation could not be handled here. Try with the super method.
|
||||
super.onDisplayPreferenceDialog(preference);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.content.Intent
|
||||
import android.media.audiofx.AudioEffect
|
||||
import android.os.Bundle
|
||||
import androidx.preference.Preference
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class AudioSettings : AbsSettingsFragment() {
|
||||
override fun invalidateSettings() {
|
||||
val findPreference: Preference = findPreference("equalizer")!!
|
||||
if (!hasEqualizer() && PreferenceUtil.getInstance().selectedEqualizer != "retro") {
|
||||
findPreference.isEnabled = false
|
||||
findPreference.summary = resources.getString(R.string.no_equalizer)
|
||||
} else {
|
||||
findPreference.isEnabled = true
|
||||
}
|
||||
findPreference.setOnPreferenceClickListener {
|
||||
NavigationUtil.openEqualizer(activity!!)
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun hasEqualizer(): Boolean {
|
||||
val effects = Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL)
|
||||
|
||||
val pm = activity!!.packageManager
|
||||
val ri = pm.resolveActivity(effects, 0)
|
||||
return ri != null
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_audio)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.preference.Preference
|
||||
import code.name.monkey.retromusic.R
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class ImageSettingFragment : AbsSettingsFragment() {
|
||||
override fun invalidateSettings() {
|
||||
val autoDownloadImagesPolicy: Preference = findPreference("auto_download_images_policy")!!
|
||||
setSummary(autoDownloadImagesPolicy)
|
||||
autoDownloadImagesPolicy.setOnPreferenceChangeListener { _, o ->
|
||||
setSummary(autoDownloadImagesPolicy, o)
|
||||
true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_images)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val preference: Preference = findPreference("auto_download_images_policy")!!
|
||||
setSummary(preference)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.retromusic.Constants.USER_PROFILE
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.SettingsActivity
|
||||
import code.name.monkey.retromusic.util.Compressor
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.synthetic.main.fragment_main_settings.*
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
|
||||
class MainSettingsFragment : Fragment(), View.OnClickListener {
|
||||
override fun onClick(v: View) {
|
||||
when (v.id) {
|
||||
R.id.generalSettings -> inflateFragment(ThemeSettingsFragment(), R.string.general_settings_title)
|
||||
R.id.audioSettings -> inflateFragment(AudioSettings(), R.string.pref_header_audio)
|
||||
R.id.nowPlayingSettings -> inflateFragment(NowPlayingSettingsFragment(), R.string.now_playing)
|
||||
R.id.personalizeSettings -> inflateFragment(PersonaizeSettingsFragment(), R.string.personalize)
|
||||
R.id.imageSettings -> inflateFragment(ImageSettingFragment(), R.string.pref_header_images)
|
||||
R.id.notificationSettings -> inflateFragment(NotificationSettingsFragment(), R.string.notification)
|
||||
R.id.otherSettings -> inflateFragment(OtherSettingsFragment(), R.string.others)
|
||||
R.id.aboutSettings -> NavigationUtil.goToAbout(activity!!)
|
||||
}
|
||||
}
|
||||
|
||||
private val settingsIcons = arrayOf(R.id.general_settings_icon, R.id.audio_settings_icon, R.id.now_playing_settings_icon, R.id.personalize_settings_icon, R.id.image_settings_icon, R.id.notification_settings_icon, R.id.other_settings_icon)
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_main_settings, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
generalSettings.setOnClickListener(this)
|
||||
audioSettings.setOnClickListener(this)
|
||||
nowPlayingSettings.setOnClickListener(this)
|
||||
personalizeSettings.setOnClickListener(this)
|
||||
imageSettings.setOnClickListener(this)
|
||||
notificationSettings.setOnClickListener(this)
|
||||
otherSettings.setOnClickListener(this)
|
||||
aboutSettings.setOnClickListener(this)
|
||||
|
||||
text.setTextColor(ThemeStore.textColorSecondary(context!!))
|
||||
text.text = PreferenceUtil.getInstance().userBio
|
||||
titleWelcome.setTextColor(ThemeStore.textColorPrimary(context!!))
|
||||
titleWelcome.text = String.format("%s %s!", getTimeOfTheDay(), PreferenceUtil.getInstance().userName)
|
||||
loadImageFromStorage()
|
||||
userInfoContainer.setOnClickListener { NavigationUtil.goToUserInfo(activity!!) }
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
private fun loadImageFromStorage() {
|
||||
|
||||
disposable.add(Compressor(context!!)
|
||||
.setMaxHeight(300)
|
||||
.setMaxWidth(300)
|
||||
.setQuality(75)
|
||||
.setCompressFormat(Bitmap.CompressFormat.WEBP)
|
||||
.compressToBitmapAsFlowable(
|
||||
File(PreferenceUtil.getInstance().profileImage, USER_PROFILE))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ userImage.setImageBitmap(it) }, {
|
||||
userImage.setImageDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_person_flat))
|
||||
}))
|
||||
}
|
||||
|
||||
private fun inflateFragment(fragment: Fragment, @StringRes title: Int) {
|
||||
if (activity != null) {
|
||||
(activity as SettingsActivity).setupFragment(fragment, title)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTimeOfTheDay(): String {
|
||||
var message = getString(R.string.title_good_day)
|
||||
val c = Calendar.getInstance()
|
||||
val timeOfDay = c.get(Calendar.HOUR_OF_DAY)
|
||||
|
||||
when (timeOfDay) {
|
||||
in 0..5 -> message = getString(R.string.title_good_night)
|
||||
in 6..11 -> message = getString(R.string.title_good_morning)
|
||||
in 12..15 -> message = getString(R.string.title_good_afternoon)
|
||||
in 16..19 -> message = getString(R.string.title_good_evening)
|
||||
in 20..23 -> message = getString(R.string.title_good_night)
|
||||
}
|
||||
return message
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.preference.TwoStatePreference
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class NotificationSettingsFragment : AbsSettingsFragment() {
|
||||
override fun invalidateSettings() {
|
||||
val classicNotification: TwoStatePreference = findPreference("classic_notification")!!
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
classicNotification.isVisible = false
|
||||
} else {
|
||||
classicNotification.isChecked = PreferenceUtil.getInstance().classicNotification()
|
||||
classicNotification.setOnPreferenceChangeListener { _, newValue ->
|
||||
// Save preference
|
||||
PreferenceUtil.getInstance().setClassicNotification(newValue as Boolean)
|
||||
|
||||
val service = MusicPlayerRemote.musicService
|
||||
if (service != null) {
|
||||
service.initNotification()
|
||||
service.updateNotification()
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_notification)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.TwoStatePreference
|
||||
import code.name.monkey.retromusic.App
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil.*
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class NowPlayingSettingsFragment : AbsSettingsFragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
override fun invalidateSettings() {
|
||||
updateNowPlayingScreenSummary()
|
||||
updateAlbumCoverStyleSummary()
|
||||
|
||||
val carouselEffect: TwoStatePreference = findPreference("carousel_effect")!!
|
||||
carouselEffect.setOnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue as Boolean && !App.isProVersion) {
|
||||
showProToastAndNavigate(activity!!.getString(R.string.pref_title_toggle_carousel_effect))
|
||||
return@setOnPreferenceChangeListener false
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_now_playing_screen)
|
||||
}
|
||||
|
||||
private fun updateAlbumCoverStyleSummary() {
|
||||
val preference: Preference = findPreference(ALBUM_COVER_STYLE)!!
|
||||
preference.setSummary(getInstance().albumCoverStyle.titleRes)
|
||||
}
|
||||
|
||||
private fun updateNowPlayingScreenSummary() {
|
||||
val preference: Preference = findPreference(NOW_PLAYING_SCREEN_ID)!!
|
||||
preference.setSummary(getInstance().nowPlayingScreen.titleRes)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
getInstance().registerOnSharedPreferenceChangedListener(this)
|
||||
val preference: Preference = findPreference("album_cover_transform")!!
|
||||
setSummary(preference)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
getInstance().unregisterOnSharedPreferenceChangedListener(this)
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
||||
when (key) {
|
||||
NOW_PLAYING_SCREEN_ID -> updateNowPlayingScreenSummary()
|
||||
ALBUM_COVER_STYLE -> updateAlbumCoverStyleSummary()
|
||||
CIRCULAR_ALBUM_ART, CAROUSEL_EFFECT -> invalidateSettings()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.preference.Preference
|
||||
|
||||
import code.name.monkey.retromusic.R
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class OtherSettingsFragment : AbsSettingsFragment() {
|
||||
override fun invalidateSettings() {
|
||||
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_blacklist)
|
||||
addPreferencesFromResource(R.xml.pref_playlists)
|
||||
addPreferencesFromResource(R.xml.pref_advanced)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val preference: Preference = findPreference("last_added_interval")!!
|
||||
setSummary(preference)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.TwoStatePreference
|
||||
import code.name.monkey.retromusic.App
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
|
||||
|
||||
class PersonaizeSettingsFragment : AbsSettingsFragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
override fun invalidateSettings() {
|
||||
val cornerWindow: TwoStatePreference = findPreference("corner_window")!!
|
||||
cornerWindow.setOnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue as Boolean && !App.isProVersion) {
|
||||
showProToastAndNavigate(activity!!.getString(R.string.pref_title_round_corners))
|
||||
return@setOnPreferenceChangeListener false
|
||||
}
|
||||
activity!!.recreate()
|
||||
return@setOnPreferenceChangeListener true
|
||||
}
|
||||
|
||||
|
||||
val toggleFullScreen: TwoStatePreference = findPreference("toggle_full_screen")!!
|
||||
toggleFullScreen.setOnPreferenceChangeListener { _, _ ->
|
||||
activity!!.recreate()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_ui)
|
||||
addPreferencesFromResource(R.xml.pref_window)
|
||||
addPreferencesFromResource(R.xml.pref_lockscreen)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
PreferenceUtil.getInstance().registerOnSharedPreferenceChangedListener(this)
|
||||
|
||||
var preference: Preference? = findPreference("album_grid_style")
|
||||
setSummary(preference!!)
|
||||
preference = findPreference("artist_grid_style")
|
||||
setSummary(preference!!)
|
||||
preference = findPreference("home_artist_grid_style")
|
||||
setSummary(preference!!)
|
||||
preference = findPreference("tab_text_mode")
|
||||
setSummary(preference!!)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
PreferenceUtil.getInstance().unregisterOnSharedPreferenceChangedListener(this)
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
||||
when (key) {
|
||||
PreferenceUtil.CAROUSEL_EFFECT -> invalidateSettings()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package code.name.monkey.retromusic.fragments.settings
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.Color.BLUE
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.TwoStatePreference
|
||||
import code.name.monkey.appthemehelper.*
|
||||
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEColorPreference
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.App
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.color.colorChooser
|
||||
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
class ThemeSettingsFragment : AbsSettingsFragment() {
|
||||
|
||||
override fun invalidateSettings() {
|
||||
val primaryColorPref: ATEColorPreference = findPreference("primary_color")!!
|
||||
primaryColorPref.isVisible = PreferenceUtil.getInstance().generalTheme == code.name.monkey.retromusic.R.style.Theme_RetroMusic_Color
|
||||
val primaryColor = ThemeStore.primaryColor(activity!!)
|
||||
primaryColorPref.setColor(primaryColor, ColorUtil.darkenColor(primaryColor))
|
||||
primaryColorPref.setOnPreferenceClickListener {
|
||||
MaterialDialog(activity!!).show {
|
||||
title(code.name.monkey.retromusic.R.string.primary_color)
|
||||
positiveButton(R.string.set)
|
||||
colorChooser(initialSelection = BLUE, allowCustomArgb = true, colors = PRIMARY_COLORS, subColors = PRIMARY_COLORS_SUB) { _, color ->
|
||||
val theme = if (ColorUtil.isColorLight(color))
|
||||
PreferenceUtil.getThemeResFromPrefValue("light")
|
||||
else
|
||||
PreferenceUtil.getThemeResFromPrefValue("dark")
|
||||
|
||||
ThemeStore.editTheme(context).activityTheme(theme).primaryColor(color).commit()
|
||||
|
||||
if (VersionUtils.hasNougatMR())
|
||||
DynamicShortcutManager(context).updateDynamicShortcuts()
|
||||
activity!!.recreate()
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
val generalTheme: Preference = findPreference("general_theme")!!
|
||||
setSummary(generalTheme)
|
||||
generalTheme.setOnPreferenceChangeListener { _, newValue ->
|
||||
val theme = newValue as String
|
||||
|
||||
if (theme == "color" && !App.isProVersion) {
|
||||
primaryColorPref.isVisible = false
|
||||
showProToastAndNavigate("Color theme")
|
||||
return@setOnPreferenceChangeListener false
|
||||
} else {
|
||||
primaryColorPref.isVisible = true
|
||||
}
|
||||
|
||||
setSummary(generalTheme, newValue)
|
||||
|
||||
|
||||
when (theme) {
|
||||
"light" -> ThemeStore.editTheme(context!!).primaryColor(Color.WHITE).commit()
|
||||
"black" -> ThemeStore.editTheme(context!!).primaryColor(Color.BLACK).commit()
|
||||
"dark" -> ThemeStore.editTheme(context!!).primaryColor(ContextCompat.getColor(context!!, code.name.monkey.retromusic.R.color.md_grey_900)).commit()
|
||||
"color" -> ThemeStore.editTheme(context!!).primaryColor(ContextCompat.getColor(context!!, code.name.monkey.retromusic.R.color.md_blue_grey_800)).commit()
|
||||
}
|
||||
|
||||
ThemeStore.editTheme(activity!!)
|
||||
.activityTheme(PreferenceUtil.getThemeResFromPrefValue(theme))
|
||||
.commit()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
activity!!.setTheme(PreferenceUtil.getThemeResFromPrefValue(theme))
|
||||
DynamicShortcutManager(activity!!).updateDynamicShortcuts()
|
||||
}
|
||||
activity!!.recreate()
|
||||
//invalidateSettings();
|
||||
true
|
||||
}
|
||||
|
||||
val accentColorPref: ATEColorPreference = findPreference("accent_color")!!
|
||||
val accentColor = ThemeStore.accentColor(activity!!)
|
||||
accentColorPref.setColor(accentColor, ColorUtil.darkenColor(accentColor))
|
||||
|
||||
accentColorPref.setOnPreferenceClickListener {
|
||||
MaterialDialog(activity!!).show {
|
||||
title(R.string.accent_color)
|
||||
positiveButton(R.string.set)
|
||||
colorChooser(colors = ACCENT_COLORS, allowCustomArgb = true, subColors = ACCENT_COLORS_SUB) { _, color ->
|
||||
/*var colorFinal = Color.BLACK;
|
||||
if (!ColorUtil.isColorSaturated(color)) {
|
||||
colorFinal = color
|
||||
}*/
|
||||
ThemeStore.editTheme(context).accentColor(color).commit()
|
||||
if (VersionUtils.hasNougatMR())
|
||||
DynamicShortcutManager(context).updateDynamicShortcuts()
|
||||
activity!!.recreate()
|
||||
}
|
||||
}
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
val colorAppShortcuts: TwoStatePreference = findPreference("should_color_app_shortcuts")!!
|
||||
if (!VersionUtils.hasNougatMR()) {
|
||||
colorAppShortcuts.isVisible = false
|
||||
} else {
|
||||
colorAppShortcuts.isChecked = PreferenceUtil.getInstance().coloredAppShortcuts()
|
||||
colorAppShortcuts.setOnPreferenceChangeListener { _, newValue ->
|
||||
// Save preference
|
||||
PreferenceUtil.getInstance().setColoredAppShortcuts(newValue as Boolean)
|
||||
DynamicShortcutManager(activity!!).updateDynamicShortcuts()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_general)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue