Fix buffering progress bar display

This commit is contained in:
Christophe Henry 2023-10-02 20:30:09 +02:00
parent 1a050c2d73
commit 31908b6175
5 changed files with 72 additions and 22 deletions

View File

@ -180,7 +180,9 @@ dependencies {
implementation("androidx.preference:preference-ktx:1.2.0")
implementation("androidx.recyclerview:recyclerview:1.2.1")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("com.google.android.material:material:1.8.0")
implementation("com.google.android.material:material:1.9.0") {
exclude("androidx.constraintlayout")
}
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("com.google.android.exoplayer:exoplayer-core:2.18.1")

View File

@ -1,6 +1,7 @@
package audio.funkwhale.ffa.fragments
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.view.View
import android.widget.SeekBar
@ -8,8 +9,13 @@ import android.widget.SeekBar.OnSeekBarChangeListener
import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData
import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.liveData
import androidx.lifecycle.map
import androidx.navigation.fragment.findNavController
import audio.funkwhale.ffa.MainNavDirections
import audio.funkwhale.ffa.R
@ -99,10 +105,6 @@ class NowPlayingFragment: Fragment(R.layout.fragment_now_playing) {
CommandBus.get().collect { onCommand(it) }
}
lifecycleScope.launch(Dispatchers.Main) {
EventBus.get().collect { onEvent(it) }
}
lifecycleScope.launch(Dispatchers.Main) {
ProgressBus.get().collect { onProgress(it) }
}
@ -135,12 +137,6 @@ class NowPlayingFragment: Fragment(R.layout.fragment_now_playing) {
else -> {}
}
private fun onEvent(event: Event): Unit = when (event) {
is Event.Buffering -> viewModel.isBuffering.postValue(event.value)
is Event.StateChanged -> viewModel.isPlaying.postValue(event.playing)
else -> {}
}
private fun onFavorite() {
val currentTrack = viewModel.currentTrack.value ?: return

View File

@ -12,6 +12,7 @@ import android.media.MediaMetadata
import android.os.Build
import android.os.IBinder
import android.support.v4.media.MediaMetadataCompat
import android.util.Log
import android.view.KeyEvent
import androidx.core.app.NotificationManagerCompat
import androidx.media.session.MediaButtonReceiver
@ -468,8 +469,11 @@ class PlayerService : Service() {
override fun onPlaybackStateChanged(playbackState: Int) {
super.onPlaybackStateChanged(playbackState)
EventBus.send(Event.Buffering(playbackState == Player.STATE_BUFFERING))
when (playbackState) {
Player.STATE_BUFFERING -> {
EventBus.send(Event.Buffering(true))
}
Player.STATE_ENDED -> {
setPlaybackState(false)
@ -488,6 +492,10 @@ class PlayerService : Service() {
mediaControlsManager.remove()
}
}
Player.STATE_READY -> {
EventBus.send(Event.Buffering(false))
}
}
}

View File

@ -2,27 +2,48 @@ package audio.funkwhale.ffa.viewmodel
import android.app.Application
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.util.Log
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.graphics.drawable.toDrawable
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData
import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.liveData
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope
import audio.funkwhale.ffa.FFA
import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.CoverArt
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.EventBus
import com.google.android.exoplayer2.Player
import com.squareup.picasso.Picasso
import com.squareup.picasso.Target
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
class NowPlayingViewModel(app: Application) : AndroidViewModel(app) {
val isBuffering = MutableLiveData(false)
val isPlaying = MutableLiveData(false)
val isBuffering = EventBus.get()
.filter { it is Event.Buffering }
.map { (it as Event.Buffering).value }
.stateIn(viewModelScope, SharingStarted.Lazily, false)
.asLiveData(viewModelScope.coroutineContext)
.distinctUntilChanged()
val isPlaying = EventBus.get()
.filter { it is Event.StateChanged }
.map { (it as Event.StateChanged).playing }
.stateIn(viewModelScope, SharingStarted.Lazily, false)
.asLiveData(viewModelScope.coroutineContext)
.distinctUntilChanged()
val repeatMode = MutableLiveData(0)
val progress = MutableLiveData(0)
val currentTrack = MutableLiveData<Track?>(null)
@ -32,6 +53,7 @@ class NowPlayingViewModel(app: Application) : AndroidViewModel(app) {
// Calling distinctUntilChanged() prevents triggering an event when the track hasn't changed
val currentTrackTitle = currentTrack.distinctUntilChanged().map { it?.title ?: "" }
val currentTrackArtist = currentTrack.distinctUntilChanged().map { it?.artist?.name ?: "" }
// Not calling distinctUntilChanged() here as we need to process every event
val isCurrentTrackFavorite = currentTrack.map {
it?.favorite ?: false

View File

@ -13,6 +13,14 @@
<Constraint android:id="@id/constraint_layout_placeholder">
<PropertySet android:visibility="visible" />
</Constraint>
<!--
I don't know why MotionLayout tries to control visibility for the buffer progress bar,
but it's messing with its display…
-->
<ConstraintOverride
android:id="@id/now_playing_buffering"
motion:visibilityMode="ignore"
/>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
@ -22,7 +30,14 @@
motion:layout_constraintStart_toStartOf="@id/detail_image_placeholder"
motion:layout_constraintTop_toBottomOf="@id/detail_image_placeholder"
motion:layout_constraintTop_toTopOf="@id/detail_image_placeholder"
motion:transitionEasing="accelerate"
/>
<!--
I don't know why MotionLayout tries to control visibility for the buffer progress bar,
but it's messing with its display…
-->
<ConstraintOverride
android:id="@id/now_playing_buffering"
motion:visibilityMode="ignore"
/>
<Constraint android:id="@id/now_playing_progress">
<PropertySet android:alpha="0" android:visibility="gone" />
@ -53,6 +68,13 @@
motion:curveFit="spline"
/>
<KeyPosition
motion:percentX="1"
motion:framePosition="50"
motion:motionTarget="@id/now_playing_buffering"
motion:curveFit="spline"
/>
<KeyAttribute
android:alpha="0"
motion:framePosition="10"