Skip to content

Commit

Permalink
Refactor to PlayerBackButtonHelper
Browse files Browse the repository at this point in the history
  • Loading branch information
brahmkshatriya committed Feb 6, 2024
1 parent 647c032 commit 748b59c
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 61 deletions.
4 changes: 2 additions & 2 deletions app/src/main/java/dev/brahmkshatriya/echo/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.google.android.material.navigation.NavigationBarView
import com.google.common.util.concurrent.MoreExecutors
import dagger.hilt.android.AndroidEntryPoint
import dev.brahmkshatriya.echo.databinding.ActivityMainBinding
import dev.brahmkshatriya.echo.ui.player.PlayerView
import dev.brahmkshatriya.echo.ui.player.Player

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
Expand Down Expand Up @@ -45,7 +45,7 @@ class MainActivity : AppCompatActivity() {
val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync()
controllerFuture.addListener(
{
PlayerView(
Player(
this,
controllerFuture.get(),
binding.bottomPlayerContainer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import dev.brahmkshatriya.echo.R
import dev.brahmkshatriya.echo.databinding.FragmentRecyclerBinding
import dev.brahmkshatriya.echo.ui.adapters.ContainerLoadingAdapter
import dev.brahmkshatriya.echo.ui.adapters.HeaderAdapter
import dev.brahmkshatriya.echo.ui.adapters.MediaItemsContainerAdapter
import dev.brahmkshatriya.echo.ui.adapters.ContainerLoadingAdapter
import dev.brahmkshatriya.echo.ui.player.PlayerBackButtonHelper
import dev.brahmkshatriya.echo.ui.player.PlayerViewModel
import dev.brahmkshatriya.echo.ui.utils.autoCleared
import dev.brahmkshatriya.echo.ui.utils.dpToPx
Expand All @@ -25,7 +25,8 @@ import dev.brahmkshatriya.echo.ui.utils.updatePaddingWithSystemInsets
class HomeFragment : Fragment() {

private var binding: FragmentRecyclerBinding by autoCleared()
private val homeViewModel: HomeViewModel by viewModels()
private val homeViewModel: HomeViewModel by activityViewModels()
private val playerViewModel: PlayerViewModel by activityViewModels()

override fun onCreateView(inflater: LayoutInflater, parent: ViewGroup?, state: Bundle?): View {
binding = FragmentRecyclerBinding.inflate(inflater, parent, false)
Expand All @@ -35,16 +36,15 @@ class HomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val playerViewModel by activityViewModels<PlayerViewModel>()
playerViewModel.handleBackPress(this)
PlayerBackButtonHelper.addCallback(this)
updatePaddingWithSystemInsets(binding.recyclerView)
binding.swipeRefresh.setProgressViewOffset(true, 0, 72.dpToPx())

val headerAdapter = HeaderAdapter(R.string.home)
val mediaItemsContainerAdapter =
MediaItemsContainerAdapter(viewLifecycleOwner.lifecycle, playerViewModel::play)

mediaItemsContainerAdapter.withLoadStateFooter(ContainerLoadingAdapter{
mediaItemsContainerAdapter.withLoadStateFooter(ContainerLoadingAdapter {
homeViewModel.loadFeed(homeViewModel.genre)
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.LinearLayoutManager
import dev.brahmkshatriya.echo.R
import dev.brahmkshatriya.echo.databinding.FragmentRecyclerBinding
import dev.brahmkshatriya.echo.ui.adapters.HeaderAdapter
import dev.brahmkshatriya.echo.ui.adapters.ContainerLoadingAdapter
import dev.brahmkshatriya.echo.ui.player.PlayerViewModel
import dev.brahmkshatriya.echo.ui.adapters.HeaderAdapter
import dev.brahmkshatriya.echo.ui.player.PlayerBackButtonHelper
import dev.brahmkshatriya.echo.ui.utils.autoCleared
import dev.brahmkshatriya.echo.ui.utils.dpToPx
import dev.brahmkshatriya.echo.ui.utils.updatePaddingWithSystemInsets
Expand All @@ -29,14 +28,13 @@ class LibraryFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val playerViewModel by activityViewModels<PlayerViewModel>()
playerViewModel.handleBackPress(this)
PlayerBackButtonHelper.addCallback(this)
updatePaddingWithSystemInsets(binding.recyclerView)
binding.swipeRefresh.setProgressViewOffset(true, 0, 72.dpToPx())

val headerAdapter = HeaderAdapter(R.string.library)

binding.recyclerView.adapter = ConcatAdapter(headerAdapter, ContainerLoadingAdapter{ })
binding.recyclerView.adapter = ConcatAdapter(headerAdapter, ContainerLoadingAdapter { })
binding.recyclerView.layoutManager = LinearLayoutManager(context)

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import dev.brahmkshatriya.echo.ui.utils.updatePaddingWithSystemInsets
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

class PlayerView(
class Player(
private val activity: MainActivity,
private val player: MediaController,
private val view: View,
Expand Down Expand Up @@ -51,7 +51,7 @@ class PlayerView(

bottomBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
viewModel.playerCollapsed.value = (newState == STATE_COLLAPSED)
PlayerBackButtonHelper.playerCollapsed.value = (newState == STATE_COLLAPSED)
}

override fun onSlide(bottomSheet: View, slideOffset: Float) {
Expand All @@ -65,10 +65,10 @@ class PlayerView(
}
})

viewModel.bottomSheetBehavior = bottomBehavior
PlayerBackButtonHelper.bottomSheetBehavior = bottomBehavior

view.post {
bottomBehavior.state = viewModel.playerCollapsed.value.let {
bottomBehavior.state = PlayerBackButtonHelper.playerCollapsed.value.let {
if (it) STATE_COLLAPSED else STATE_EXPANDED
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package dev.brahmkshatriya.echo.ui.player

import android.view.View
import androidx.activity.BackEventCompat
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.google.android.material.bottomsheet.BottomSheetBehavior
import dev.brahmkshatriya.echo.MainActivity
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

object PlayerBackButtonHelper {

var bottomSheetBehavior: BottomSheetBehavior<View>? = null
val playerCollapsed = MutableStateFlow(true)
private fun backPressedCallback(
viewLifecycleOwner: LifecycleOwner,
callback: ((Boolean) -> Unit)?
): OnBackPressedCallback {
val backPress = object : OnBackPressedCallback(false) {
override fun handleOnBackStarted(backEvent: BackEventCompat) {
bottomSheetBehavior?.startBackProgress(backEvent)
}

override fun handleOnBackProgressed(backEvent: BackEventCompat) {
bottomSheetBehavior?.updateBackProgress(backEvent)
}

override fun handleOnBackPressed() {
bottomSheetBehavior?.handleBackInvoked()
}

override fun handleOnBackCancelled() {
bottomSheetBehavior?.cancelBackProgress()
}
}
viewLifecycleOwner.lifecycleScope.launch {
playerCollapsed.collectLatest {
backPress.isEnabled = !it
callback?.invoke(it)
}
}
return backPress
}

fun addCallback(fragment: Fragment, callback: ((Boolean) -> Unit)? = null) =
with(fragment) {
val mainActivity = (requireActivity() as? MainActivity)
?: throw IllegalArgumentException("Fragment must be attached to MainActivity")
val backPressedCallback =
backPressedCallback(viewLifecycleOwner, callback)
mainActivity.onBackPressedDispatcher.addCallback(
viewLifecycleOwner,
backPressedCallback
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ interface PlayerHelper {
String.format("%02d:%02d", minutes, seconds % 60)
}
}


}
}

Original file line number Diff line number Diff line change
@@ -1,55 +1,20 @@
package dev.brahmkshatriya.echo.ui.player

import android.view.View
import androidx.activity.BackEventCompat
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.android.material.bottomsheet.BottomSheetBehavior
import dagger.hilt.android.lifecycle.HiltViewModel
import dev.brahmkshatriya.echo.data.clients.TrackClient
import dev.brahmkshatriya.echo.data.models.StreamableAudio
import dev.brahmkshatriya.echo.data.models.Track
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class PlayerViewModel @Inject constructor(
private val trackClient: TrackClient
) : ViewModel() {
var bottomSheetBehavior: BottomSheetBehavior<View>? = null
val playerCollapsed = MutableStateFlow(true)

private fun backPressedCallback(callback: ((Boolean) -> Unit)?): OnBackPressedCallback {
val backPress = object : OnBackPressedCallback(false) {
override fun handleOnBackStarted(backEvent: BackEventCompat) {
bottomSheetBehavior?.startBackProgress(backEvent)
}

override fun handleOnBackProgressed(backEvent: BackEventCompat) {
bottomSheetBehavior?.updateBackProgress(backEvent)
}

override fun handleOnBackPressed() {
bottomSheetBehavior?.handleBackInvoked()
}

override fun handleOnBackCancelled() {
bottomSheetBehavior?.cancelBackProgress()
}
}
viewModelScope.launch {
playerCollapsed.collectLatest {
backPress.isEnabled = !it
callback?.invoke(it)
}
}
return backPress
}

val audioFlow = MutableStateFlow<Pair<Track, StreamableAudio>?>(null)

Expand All @@ -63,10 +28,4 @@ class PlayerViewModel @Inject constructor(
loadStreamable(track)
}

fun handleBackPress(fragment: Fragment, callback: ((Boolean) -> Unit)? = null) =
with(fragment) {
val backPressedCallback = backPressedCallback(callback)
requireActivity().onBackPressedDispatcher
.addCallback(viewLifecycleOwner, backPressedCallback)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import dagger.hilt.android.AndroidEntryPoint
import dev.brahmkshatriya.echo.databinding.FragmentSearchBinding
import dev.brahmkshatriya.echo.ui.adapters.MediaItemsContainerAdapter
import dev.brahmkshatriya.echo.ui.adapters.SearchHeaderAdapter
import dev.brahmkshatriya.echo.ui.player.PlayerBackButtonHelper
import dev.brahmkshatriya.echo.ui.player.PlayerViewModel
import dev.brahmkshatriya.echo.ui.utils.observeFlow
import dev.brahmkshatriya.echo.ui.utils.updatePaddingWithSystemInsets
Expand All @@ -21,6 +22,7 @@ class SearchFragment : Fragment() {

private lateinit var binding: FragmentSearchBinding
private val searchViewModel: SearchViewModel by activityViewModels()
private val playerViewModel: PlayerViewModel by activityViewModels()

override fun onCreateView(inflater: LayoutInflater, parent: ViewGroup?, state: Bundle?): View {
binding = FragmentSearchBinding.inflate(inflater, parent, false)
Expand All @@ -30,9 +32,8 @@ class SearchFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val playerViewModel by activityViewModels<PlayerViewModel>()

playerViewModel.handleBackPress(this) {
PlayerBackButtonHelper.addCallback(this) {
if (!it) binding.catSearchView.hide()
}

Expand Down

0 comments on commit 748b59c

Please sign in to comment.