package code.name.monkey.retromusic.activities.base import android.animation.ValueAnimator import android.graphics.Color import android.os.Bundle import android.view.View import android.view.ViewGroup import android.view.ViewTreeObserver import android.widget.FrameLayout import androidx.annotation.LayoutRes import androidx.fragment.app.Fragment 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.extensions.hide import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.fragments.MiniPlayerFragment import code.name.monkey.retromusic.fragments.NowPlayingScreen import code.name.monkey.retromusic.fragments.NowPlayingScreen.ADAPTIVE import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR_CARD import code.name.monkey.retromusic.fragments.NowPlayingScreen.CARD import code.name.monkey.retromusic.fragments.NowPlayingScreen.CIRCLE import code.name.monkey.retromusic.fragments.NowPlayingScreen.COLOR import code.name.monkey.retromusic.fragments.NowPlayingScreen.FIT import code.name.monkey.retromusic.fragments.NowPlayingScreen.FLAT import code.name.monkey.retromusic.fragments.NowPlayingScreen.FULL import code.name.monkey.retromusic.fragments.NowPlayingScreen.MATERIAL import code.name.monkey.retromusic.fragments.NowPlayingScreen.NORMAL import code.name.monkey.retromusic.fragments.NowPlayingScreen.PEAK import code.name.monkey.retromusic.fragments.NowPlayingScreen.PLAIN import code.name.monkey.retromusic.fragments.NowPlayingScreen.SIMPLE import code.name.monkey.retromusic.fragments.NowPlayingScreen.TINY import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment import code.name.monkey.retromusic.fragments.player.adaptive.AdaptiveFragment import code.name.monkey.retromusic.fragments.player.blur.BlurPlayerFragment import code.name.monkey.retromusic.fragments.player.card.CardFragment import code.name.monkey.retromusic.fragments.player.cardblur.CardBlurFragment import code.name.monkey.retromusic.fragments.player.circle.CirclePlayerFragment import code.name.monkey.retromusic.fragments.player.color.ColorFragment import code.name.monkey.retromusic.fragments.player.fit.FitFragment import code.name.monkey.retromusic.fragments.player.flat.FlatPlayerFragment import code.name.monkey.retromusic.fragments.player.full.FullPlayerFragment import code.name.monkey.retromusic.fragments.player.material.MaterialFragment import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment import code.name.monkey.retromusic.fragments.player.peak.PeakPlayerFragment import code.name.monkey.retromusic.fragments.player.plain.PlainPlayerFragment import code.name.monkey.retromusic.fragments.player.simple.SimplePlayerFragment import code.name.monkey.retromusic.fragments.player.tiny.TinyPlayerFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.model.CategoryInfo import code.name.monkey.retromusic.util.DensityUtil import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.views.BottomNavigationBarTinted import com.google.android.material.bottomsheet.BottomSheetBehavior import kotlinx.android.synthetic.main.sliding_music_panel_layout.bottomNavigationView import kotlinx.android.synthetic.main.sliding_music_panel_layout.dimBackground import kotlinx.android.synthetic.main.sliding_music_panel_layout.slidingPanel abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlayerFragment.Callbacks { companion object { val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName } private lateinit var bottomSheetBehavior: BottomSheetBehavior private var miniPlayerFragment: MiniPlayerFragment? = null private var playerFragment: AbsPlayerFragment? = null private var currentNowPlayingScreen: NowPlayingScreen? = null private var navigationBarColor: Int = 0 private var taskColor: Int = 0 private var lightStatusBar: Boolean = false private var lightNavigationBar: Boolean = false private var navigationBarColorAnimator: ValueAnimator? = null protected abstract fun createContentView(): View private val panelState: Int get() = bottomSheetBehavior.state private val bottomSheetCallbackList = object : BottomSheetBehavior.BottomSheetCallback() { override fun onSlide(bottomSheet: View, slideOffset: Float) { setMiniPlayerAlphaProgress(slideOffset) dimBackground.show() dimBackground.alpha = slideOffset } override fun onStateChanged(bottomSheet: View, newState: Int) { when (newState) { BottomSheetBehavior.STATE_EXPANDED -> { onPanelExpanded() } BottomSheetBehavior.STATE_COLLAPSED -> { onPanelCollapsed() dimBackground.hide() } else -> { } } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(createContentView()) chooseFragmentForTheme() setupSlidingUpPanel() updateTabs() bottomSheetBehavior = BottomSheetBehavior.from(slidingPanel) val themeColor = ATHUtil.resolveColor(this, android.R.attr.windowBackground, Color.GRAY) dimBackground.setBackgroundColor(ColorUtil.withAlpha(themeColor, 0.5f)) } override fun onResume() { super.onResume() if (currentNowPlayingScreen != PreferenceUtil.getInstance(this).nowPlayingScreen) { postRecreate() } bottomSheetBehavior.addBottomSheetCallback(bottomSheetCallbackList) if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED) { setMiniPlayerAlphaProgress(1f) } } override fun onDestroy() { super.onDestroy() bottomSheetBehavior.removeBottomSheetCallback(bottomSheetCallbackList) if (navigationBarColorAnimator != null) navigationBarColorAnimator?.cancel() // just in case } protected fun wrapSlidingMusicPanel(@LayoutRes resId: Int): View { val slidingMusicPanelLayout = layoutInflater.inflate(R.layout.sliding_music_panel_layout, null) val contentContainer = slidingMusicPanelLayout.findViewById(R.id.mainContentFrame) layoutInflater.inflate(resId, contentContainer) return slidingMusicPanelLayout } private fun collapsePanel() { bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED } fun expandPanel() { bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED setMiniPlayerAlphaProgress(1f) } private fun setMiniPlayerAlphaProgress(progress: Float) { if (miniPlayerFragment?.view == null) return val alpha = 1 - progress miniPlayerFragment?.view?.alpha = alpha // necessary to make the views below clickable miniPlayerFragment?.view?.visibility = if (alpha == 0f) View.GONE else View.VISIBLE bottomNavigationView.translationY = progress * 500 //bottomNavigationView.alpha = alpha } open fun onPanelCollapsed() { // restore values super.setLightStatusbar(lightStatusBar) super.setTaskDescriptionColor(taskColor) super.setNavigationbarColor(navigationBarColor) super.setLightNavigationBar(lightNavigationBar) playerFragment?.setMenuVisibility(false) playerFragment?.userVisibleHint = false playerFragment?.onHide() } open fun onPanelExpanded() { val playerFragmentColor = playerFragment!!.paletteColor super.setTaskDescriptionColor(playerFragmentColor) playerFragment?.setMenuVisibility(true) playerFragment?.userVisibleHint = true playerFragment?.onShow() onPaletteColorChanged() } private fun setupSlidingUpPanel() { slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this) if (currentNowPlayingScreen != PEAK) { val params = slidingPanel.layoutParams as ViewGroup.LayoutParams params.height = ViewGroup.LayoutParams.MATCH_PARENT slidingPanel.layoutParams = params } when (panelState) { BottomSheetBehavior.STATE_EXPANDED -> onPanelExpanded() BottomSheetBehavior.STATE_COLLAPSED -> onPanelCollapsed() else -> playerFragment!!.onHide() } } }) } fun toggleBottomNavigationView(toggle: Boolean) { bottomNavigationView.visibility = if (toggle) View.GONE else View.VISIBLE } fun getBottomNavigationView(): BottomNavigationBarTinted { return bottomNavigationView } private fun hideBottomBar(hide: Boolean) { val heightOfBar = resources.getDimensionPixelSize(R.dimen.mini_player_height) val heightOfBarWithTabs = resources.getDimensionPixelSize(R.dimen.mini_player_height_expanded) if (hide) { bottomSheetBehavior.isHideable = true bottomSheetBehavior.peekHeight = 0 collapsePanel() bottomNavigationView.elevation = DensityUtil.dip2px(this, 10f).toFloat() } else { if (MusicPlayerRemote.playingQueue.isNotEmpty()) { slidingPanel.cardElevation = DensityUtil.dip2px(this, 10f).toFloat() bottomNavigationView.elevation = DensityUtil.dip2px(this, 10f).toFloat() bottomSheetBehavior.isHideable = false bottomSheetBehavior.peekHeight = if (bottomNavigationView.visibility == View.VISIBLE) heightOfBarWithTabs else heightOfBar } } } fun setBottomBarVisibility(gone: Int) { bottomNavigationView.visibility = gone hideBottomBar(false) } private fun chooseFragmentForTheme() { currentNowPlayingScreen = PreferenceUtil.getInstance(this).nowPlayingScreen val fragment: Fragment = when (currentNowPlayingScreen) { BLUR -> BlurPlayerFragment() ADAPTIVE -> AdaptiveFragment() NORMAL -> PlayerFragment() CARD -> CardFragment() BLUR_CARD -> CardBlurFragment() FIT -> FitFragment() FLAT -> FlatPlayerFragment() FULL -> FullPlayerFragment() PLAIN -> PlainPlayerFragment() SIMPLE -> SimplePlayerFragment() MATERIAL -> MaterialFragment() COLOR -> ColorFragment() TINY -> TinyPlayerFragment() PEAK -> PeakPlayerFragment() CIRCLE -> CirclePlayerFragment() else -> PlayerFragment() } // must implement AbsPlayerFragment supportFragmentManager.beginTransaction().replace(R.id.playerFragmentContainer, fragment) .commit() supportFragmentManager.executePendingTransactions() playerFragment = supportFragmentManager.findFragmentById(R.id.playerFragmentContainer) as AbsPlayerFragment miniPlayerFragment = supportFragmentManager.findFragmentById(R.id.miniPlayerFragment) as MiniPlayerFragment miniPlayerFragment?.view?.setOnClickListener { expandPanel() } } override fun onServiceConnected() { super.onServiceConnected() if (MusicPlayerRemote.playingQueue.isNotEmpty()) { slidingPanel.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this) hideBottomBar(false) } }) } // don't call hideBottomBar(true) here as it causes a bug with the SlidingUpPanelLayout } override fun onQueueChanged() { super.onQueueChanged() hideBottomBar(MusicPlayerRemote.playingQueue.isEmpty()) } override fun onBackPressed() { if (!handleBackPress()) super.onBackPressed() } open fun handleBackPress(): Boolean { if (bottomSheetBehavior.peekHeight != 0 && playerFragment!!.onBackPressed()) return true if (panelState == BottomSheetBehavior.STATE_EXPANDED) { collapsePanel() return true } return false } override fun onPaletteColorChanged() { if (panelState == BottomSheetBehavior.STATE_EXPANDED) { val paletteColor = playerFragment!!.paletteColor super.setTaskDescriptionColor(paletteColor) val isColorLight = ColorUtil.isColorLight(paletteColor) if (PreferenceUtil.getInstance(this).adaptiveColor && (currentNowPlayingScreen == NORMAL || currentNowPlayingScreen == FLAT)) { super.setLightNavigationBar(true) super.setLightStatusbar(isColorLight) } else if (currentNowPlayingScreen == FULL || currentNowPlayingScreen == CARD || currentNowPlayingScreen == FIT || currentNowPlayingScreen == BLUR || currentNowPlayingScreen == BLUR_CARD) { super.setLightStatusbar(false) super.setLightNavigationBar(true) super.setNavigationbarColor(Color.BLACK) } else if (currentNowPlayingScreen == COLOR || currentNowPlayingScreen == TINY) { super.setNavigationbarColor(paletteColor) super.setLightNavigationBar(isColorLight) super.setLightStatusbar(isColorLight) } else { super.setLightStatusbar( ColorUtil.isColorLight( ATHUtil.resolveColor( this, android.R.attr.windowBackground ) ) ) super.setLightNavigationBar(true) } } } override fun setLightStatusbar(enabled: Boolean) { lightStatusBar = enabled if (panelState == BottomSheetBehavior.STATE_COLLAPSED) { super.setLightStatusbar(enabled) } } override fun setLightNavigationBar(enabled: Boolean) { lightNavigationBar = enabled if (panelState == BottomSheetBehavior.STATE_COLLAPSED) { super.setLightNavigationBar(enabled) } } override fun setNavigationbarColor(color: Int) { navigationBarColor = color if (panelState == BottomSheetBehavior.STATE_COLLAPSED) { if (navigationBarColorAnimator != null) navigationBarColorAnimator!!.cancel() super.setNavigationbarColor(color) } } override fun setTaskDescriptionColor(color: Int) { taskColor = color if (panelState == BottomSheetBehavior.STATE_COLLAPSED) { super.setTaskDescriptionColor(color) } } private fun updateTabs() { bottomNavigationView.menu.clear() val currentTabs: List = PreferenceUtil.getInstance(this).libraryCategoryInfos for (tab in currentTabs) { if (tab.visible) { val menu = tab.category bottomNavigationView.menu.add(0, menu.id, 0, menu.stringRes).setIcon(menu.icon) } } if (currentTabs.size <= 1) { toggleBottomNavigationView(true) } } /*override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { if (ev?.action == MotionEvent.ACTION_DOWN) { if (panelState == BottomSheetBehavior.STATE_EXPANDED) { val outRect = Rect() slidingPanel.getGlobalVisibleRect(outRect) if (!outRect.contains(ev.rawX.toInt(), ev.rawY.toInt())) { bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED } } } return super.dispatchTouchEvent(ev) }*/ }