Skip to content

Commit

Permalink
Add hide-able player
Browse files Browse the repository at this point in the history
  • Loading branch information
brahmkshatriya committed Feb 15, 2024
1 parent ed4dec1 commit 5dbb332
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 54 deletions.
2 changes: 2 additions & 0 deletions app/src/main/java/dev/brahmkshatriya/echo/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import dev.brahmkshatriya.echo.databinding.ActivityMainBinding
import dev.brahmkshatriya.echo.ui.player.initPlayer
import dev.brahmkshatriya.echo.ui.utils.checkPermissions
import dev.brahmkshatriya.echo.ui.utils.emit
import dev.brahmkshatriya.echo.ui.utils.updateBottomMarginWithSystemInsets
import kotlinx.coroutines.flow.MutableSharedFlow

@AndroidEntryPoint
Expand All @@ -42,6 +43,7 @@ class MainActivity : AppCompatActivity() {
val navView = binding.navView as NavigationBarView
val navHostFragment = binding.navHostFragment.getFragment<NavHostFragment>()
navView.setupWithNavController(navHostFragment.navController)
updateBottomMarginWithSystemInsets(binding.navHostFragment)

val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java))
val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ class OfflineExtension(val context: Context) : SearchClient, TrackClient, HomeFe
return try {
val items = if (page == 0) {
val albums = LocalAlbum.getAll(context, page, pageSize)
.map { it.toMediaItem() }
val tracks = LocalTrack.getAll(context, page, pageSize)
.map { it.toMediaItem() }
.map { it.toMediaItem() }.ifEmpty { null }
val tracks = LocalTrack.getShuffled(context, page, pageSize)
.map { it.toMediaItem() }.ifEmpty { null }
val artists = LocalArtist.getAll(context, page, pageSize)
.map { it.toMediaItem() }
.map { it.toMediaItem() }.ifEmpty { null }
val result = listOfNotNull(
tracks.toMediaItemsContainer("Tracks"),
albums.toMediaItemsContainer("Albums"),
artists.toMediaItemsContainer("Artists")
tracks?.toMediaItemsContainer("Tracks"),
albums?.toMediaItemsContainer("Albums"),
artists?.toMediaItemsContainer("Artists")
)
result
} else {
LocalTrack.getShuffled(context, page, pageSize)
LocalTrack.getAll(context, page, pageSize)
.map { MediaItemsContainer.TrackItem(it) }
}
val nextKey =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,22 @@ class MediaItemsContainerAdapter(
override fun areContentsTheSame(
oldItem: MediaItemsContainer,
newItem: MediaItemsContainer
) = areItemsTheSame(oldItem, newItem)
): Boolean {
when (oldItem) {
is MediaItemsContainer.Category -> {
val newCategory = newItem as? MediaItemsContainer.Category
newCategory ?: return true
oldItem.list.forEach {
if (!newCategory.list.contains(it)) return false
}
}

is MediaItemsContainer.TrackItem -> {
val newTrack = newItem as? MediaItemsContainer.TrackItem
return oldItem.track == newTrack?.track
}
}
return true
}
}
}
29 changes: 21 additions & 8 deletions app/src/main/java/dev/brahmkshatriya/echo/ui/player/InitPlayer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
import com.google.android.material.checkbox.MaterialCheckBox
import com.google.android.material.checkbox.MaterialCheckBox.OnCheckedStateChangedListener
import com.google.android.material.checkbox.MaterialCheckBox.STATE_CHECKED
Expand All @@ -30,6 +31,7 @@ import dev.brahmkshatriya.echo.ui.utils.loadInto
import dev.brahmkshatriya.echo.ui.utils.observe
import dev.brahmkshatriya.echo.ui.utils.updatePaddingWithSystemInsets
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlin.math.max

fun initPlayer(
activity: MainActivity,
Expand Down Expand Up @@ -65,30 +67,34 @@ fun initPlayer(

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

override fun onSlide(bottomSheet: View, slideOffset: Float) {
val offset = max(0f, slideOffset)
playerBinding.collapsedContainer.translationY =
-collapsedCoverSize * slideOffset
-collapsedCoverSize * offset
playerBinding.expandedContainer.translationY =
collapsedCoverSize * (1 - slideOffset)
collapsedCoverSize * (1 - offset)

navView.translationY = bottomNavHeight * slideOffset
navView.translationY = bottomNavHeight * offset
}
})

PlayerBackButtonHelper.bottomSheetBehavior = bottomBehavior

container.post {
bottomBehavior.state = PlayerBackButtonHelper.playerCollapsed.value.let {
if (it) STATE_COLLAPSED else STATE_EXPANDED
}
bottomBehavior.state = PlayerBackButtonHelper.playerCollapsed.value
}
activity.observe(activity.fromNotification) {
bottomBehavior.state = STATE_EXPANDED
}

playerBinding.playerClose.setOnClickListener {
bottomBehavior.state = STATE_HIDDEN
}

//Connect the UI to the ViewModel

Expand Down Expand Up @@ -147,7 +153,7 @@ fun initPlayer(

val repeatMode = player.repeatMode
playerBinding.trackRepeat.icon = drawables[repeatModes.indexOf(repeatMode)]
playerBinding.trackRepeat.alpha = if(repeatMode == REPEAT_MODE_OFF) 0.4f else 1f
playerBinding.trackRepeat.alpha = if (repeatMode == REPEAT_MODE_OFF) 0.4f else 1f
(playerBinding.trackRepeat.icon as Animatable).start()

playerBinding.trackRepeat.setOnClickListener {
Expand Down Expand Up @@ -247,6 +253,8 @@ fun initPlayer(
}
observe(playerViewModel.audioIndexFlow) {
player.seekToDefaultPosition(it)
if (bottomBehavior.state == STATE_HIDDEN)
bottomBehavior.state = STATE_COLLAPSED
}
observe(playerViewModel.seekTo) {
player.seekTo(it)
Expand All @@ -260,5 +268,10 @@ fun initPlayer(
player.prepare()
player.playWhenReady = true
}
observe(playerViewModel.clearQueueFlow) {
player.pause()
player.clearMediaItems()
player.stop()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleOwner
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
import dev.brahmkshatriya.echo.MainActivity
import dev.brahmkshatriya.echo.ui.utils.observe
import kotlinx.coroutines.flow.MutableStateFlow

object PlayerBackButtonHelper {

var bottomSheetBehavior: BottomSheetBehavior<View>? = null
val playerCollapsed = MutableStateFlow(true)
val playerCollapsed = MutableStateFlow(STATE_HIDDEN)
private fun backPressedCallback(
viewLifecycleOwner: LifecycleOwner,
callback: ((Boolean) -> Unit)?
Expand All @@ -36,8 +38,9 @@ object PlayerBackButtonHelper {
}
}
viewLifecycleOwner.observe(playerCollapsed) {
backPress.isEnabled = !it
callback?.invoke(it)
val expanded = it == STATE_EXPANDED
backPress.isEnabled = expanded
callback?.invoke(expanded)
}
return backPress
}
Expand All @@ -48,9 +51,7 @@ object PlayerBackButtonHelper {
?: throw IllegalArgumentException("Fragment must be attached to MainActivity")
val backPressedCallback =
backPressedCallback(viewLifecycleOwner, callback)
mainActivity.onBackPressedDispatcher.addCallback(
viewLifecycleOwner,
backPressedCallback
)
mainActivity.onBackPressedDispatcher
.addCallback(viewLifecycleOwner, backPressedCallback)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class PlayerViewModel @Inject constructor(

val audioIndexFlow = MutableSharedFlow<Int>()
val audioQueueFlow = MutableSharedFlow<TrackWithStream>()
val clearQueueFlow = MutableSharedFlow<Unit>()

private suspend fun loadStreamable(track: Track) =
TrackWithStream(track, trackClient.getStreamable(track))
Expand All @@ -54,6 +55,13 @@ class PlayerViewModel @Inject constructor(
}
}

fun clearQueue() {
queue.clear()
viewModelScope.launch {
clearQueueFlow.emit(Unit)
}
}

// fun radio(track: Track){
// viewModelScope.launch(Dispatchers.IO) {
// val playlist = radioClient.radio(track)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ class ShimmerLayoutSelf @JvmOverloads constructor(
repeatCount = Animation.INFINITE
}
}

override fun onAttachedToWindow() {
super.onAttachedToWindow()
startAnimation(animation)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding

fun updatePaddingWithSystemInsets(view: View, bottom: Boolean = true) {
fun updatePaddingWithSystemInsets(view: View, bottom: Boolean = false) {
ViewCompat.setOnApplyWindowInsetsListener(view) { v, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
v.updatePadding(insets.left, insets.top, insets.right, if (bottom) insets.bottom else 0)
v.updatePadding(
insets.left,
insets.top,
insets.right,
if (bottom) insets.bottom else v.paddingBottom
)
WindowInsetsCompat.CONSUMED
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout-land/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="80dp"
android:layout_marginBottom="72dp"
app:defaultNavHost="true"
app:navGraph="@navigation/mobile_navigation" />

Expand All @@ -23,6 +22,7 @@
android:layout_height="match_parent"
android:background="?attr/colorSurfaceContainerLow"
app:behavior_peekHeight="72dp"
app:behavior_hideable="true"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

<include
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="152dp"
android:paddingBottom="80dp"
app:defaultNavHost="true"
app:navGraph="@navigation/mobile_navigation" />

Expand All @@ -33,6 +33,7 @@
android:layout_height="match_parent"
android:background="?attr/colorSurfaceContainerLow"
app:behavior_peekHeight="152dp"
app:behavior_hideable="true"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

<include
Expand Down
64 changes: 38 additions & 26 deletions app/src/main/res/layout/bottom_player.xml
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@
android:layout_width="64dp"
android:layout_height="64dp"
android:contentDescription="@string/repeat"
android:padding="12dp"
app:icon="@drawable/ic_repeat_to_repeat_one_40dp"
app:iconSize="32dp"
android:padding="12dp"
app:iconTint="?attr/colorOnSurface"/>
app:iconTint="?attr/colorOnSurface" />

<com.google.android.material.button.MaterialButton
android:id="@+id/trackPrevious"
Expand Down Expand Up @@ -179,8 +179,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSurfaceContainerLow"
android:orientation="horizontal"
tools:translationY="-72dp">
android:orientation="horizontal">

<ImageView
android:id="@+id/collapsedTrackCover"
Expand Down Expand Up @@ -217,7 +216,6 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="24dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:baselineAligned="false"
android:gravity="center"
Expand All @@ -239,31 +237,45 @@
tools:text="Author" />
</LinearLayout>

<FrameLayout
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp">
<LinearLayout
android:padding="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/collapsedProgressBar"
<FrameLayout
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone" />

<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/collapsedTrackPlayPause"
android:layout_height="wrap_content">

<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/collapsedProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone" />

<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/collapsedTrackPlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="@drawable/anim_play_pause"
android:contentDescription="@string/play_pause"
android:enabled="false"
app:buttonTint="@color/button_play_pause" />

</FrameLayout>

<com.google.android.material.button.MaterialButton
android:id="@+id/playerClose"
style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="@drawable/anim_play_pause"
android:contentDescription="@string/play_pause"
android:enabled="false"
app:buttonTint="@color/button_play_pause"
app:iconSize="24dp" />

</FrameLayout>

android:contentDescription="@string/next"
app:icon="@drawable/ic_close"
app:iconSize="24dp"
android:padding="8dp"
app:iconTint="@color/button_player" />
</LinearLayout>
</LinearLayout>
</FrameLayout>

Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/layout/fragment_recycler.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="80dp"
tools:itemCount="1"
tools:listitem="@layout/item_main_header" />

Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/layout/fragment_search.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
android:id="@+id/cat_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="80dp"
android:clipToPadding="false" />

<com.google.android.material.search.SearchView
Expand Down

0 comments on commit 5dbb332

Please sign in to comment.