Improve skipButton visibility/usability

This commit is contained in:
cd16b 2024-06-21 14:36:11 +02:00
parent df984fb24b
commit 91cccc55a7
4 changed files with 63 additions and 32 deletions

View file

@ -37,6 +37,7 @@ import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.databinding.ActivityPlayerBinding import dev.jdtech.jellyfin.databinding.ActivityPlayerBinding
import dev.jdtech.jellyfin.dialogs.SpeedSelectionDialogFragment import dev.jdtech.jellyfin.dialogs.SpeedSelectionDialogFragment
import dev.jdtech.jellyfin.dialogs.TrackSelectionDialogFragment import dev.jdtech.jellyfin.dialogs.TrackSelectionDialogFragment
import dev.jdtech.jellyfin.models.FindroidSegment
import dev.jdtech.jellyfin.utils.PlayerGestureHelper import dev.jdtech.jellyfin.utils.PlayerGestureHelper
import dev.jdtech.jellyfin.utils.PreviewScrubListener import dev.jdtech.jellyfin.utils.PreviewScrubListener
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
@ -59,6 +60,8 @@ class PlayerActivity : BasePlayerActivity() {
override val viewModel: PlayerActivityViewModel by viewModels() override val viewModel: PlayerActivityViewModel by viewModels()
private var previewScrubListener: PreviewScrubListener? = null private var previewScrubListener: PreviewScrubListener? = null
private var wasZoom: Boolean = false private var wasZoom: Boolean = false
private var oldSegment: FindroidSegment? = null
private var buttonPressed: Boolean = false
private val isPipSupported by lazy { private val isPipSupported by lazy {
// Check if device has PiP feature // Check if device has PiP feature
@ -120,7 +123,7 @@ class PlayerActivity : BasePlayerActivity() {
val audioButton = binding.playerView.findViewById<ImageButton>(R.id.btn_audio_track) val audioButton = binding.playerView.findViewById<ImageButton>(R.id.btn_audio_track)
val subtitleButton = binding.playerView.findViewById<ImageButton>(R.id.btn_subtitle) val subtitleButton = binding.playerView.findViewById<ImageButton>(R.id.btn_subtitle)
val speedButton = binding.playerView.findViewById<ImageButton>(R.id.btn_speed) val speedButton = binding.playerView.findViewById<ImageButton>(R.id.btn_speed)
val skipIntroButton = binding.playerView.findViewById<Button>(R.id.btn_skip_intro) val skipButton = binding.playerView.findViewById<Button>(R.id.btn_skip_intro)
val pipButton = binding.playerView.findViewById<ImageButton>(R.id.btn_pip) val pipButton = binding.playerView.findViewById<ImageButton>(R.id.btn_pip)
val lockButton = binding.playerView.findViewById<ImageButton>(R.id.btn_lockview) val lockButton = binding.playerView.findViewById<ImageButton>(R.id.btn_lockview)
val unlockButton = binding.playerView.findViewById<ImageButton>(R.id.btn_unlock) val unlockButton = binding.playerView.findViewById<ImageButton>(R.id.btn_unlock)
@ -134,30 +137,42 @@ class PlayerActivity : BasePlayerActivity() {
// Title // Title
videoNameTextView.text = currentItemTitle videoNameTextView.text = currentItemTitle
// Skip Intro button // Skip button
// Visibility // Button Visibility
skipIntroButton.isVisible = !isInPictureInPictureMode && showSkip == true if (currentSegment != oldSegment) buttonPressed = false
// Text skipButton.isVisible =
!isInPictureInPictureMode && !buttonPressed && (showSkip == true || (binding.playerView.isControllerFullyVisible && currentSegment?.skip == true))
binding.playerView.setControllerVisibilityListener(
PlayerView.ControllerVisibilityListener { visibility ->
skipButton.isVisible =
!isInPictureInPictureMode && !buttonPressed && (showSkip == true || visibility == View.VISIBLE && currentSegment?.skip == true)
},
)
// Button Text
when (currentSegment?.type) { when (currentSegment?.type) {
"intro" -> { "intro" -> {
skipIntroButton.text = getString(CoreR.string.skip_intro_button) skipButton.text =
getString(CoreR.string.skip_intro_button)
} }
"credit" -> { "credit" -> {
skipIntroButton.text = if (binding.playerView.player?.hasNextMediaItem() == true) { skipButton.text =
getString(CoreR.string.skip_credit_button) if (binding.playerView.player?.hasNextMediaItem() == true) {
} else { getString(CoreR.string.skip_credit_button)
getString(CoreR.string.skip_credit_button_last) } else {
} getString(CoreR.string.skip_credit_button_last)
}
} }
} }
// onClick // onClick
skipIntroButton.setOnClickListener { skipButton.setOnClickListener {
when (currentSegment?.type) { when (currentSegment?.type) {
"intro" -> { "intro" -> {
currentSegment?.let { currentSegment?.let {
binding.playerView.player?.seekTo((it.endTime * 1000).toLong()) binding.playerView.player?.seekTo((it.endTime * 1000).toLong())
} }
} }
"credit" -> { "credit" -> {
if (binding.playerView.player?.hasNextMediaItem() == true) { if (binding.playerView.player?.hasNextMediaItem() == true) {
binding.playerView.player?.seekToNext() binding.playerView.player?.seekToNext()
@ -166,8 +181,10 @@ class PlayerActivity : BasePlayerActivity() {
} }
} }
} }
skipIntroButton.isVisible = false buttonPressed = true
skipButton.isVisible = false
} }
oldSegment = currentSegment
// Trick Play // Trick Play
previewScrubListener?.let { previewScrubListener?.let {

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn_skip_intro"
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginEnd="24dp"
android:layout_marginBottom="64dp"
android:textColor="@android:color/white"
android:visibility="gone"
app:backgroundTint="@color/player_background"
app:icon="@drawable/ic_skip_forward"
app:iconGravity="end"
app:iconTint="@android:color/white"
app:strokeColor="@android:color/white"
tools:visibility="visible" />
</FrameLayout>

View file

@ -48,23 +48,6 @@
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="14sp" /> android:textSize="14sp" />
<Button
android:id="@+id/btn_skip_intro"
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginEnd="24dp"
android:layout_marginBottom="64dp"
android:textColor="@android:color/white"
android:visibility="gone"
app:backgroundTint="@color/player_background"
app:icon="@drawable/ic_skip_forward"
app:iconGravity="end"
app:iconTint="@android:color/white"
app:strokeColor="@android:color/white"
tools:visibility="visible" />
</androidx.media3.ui.AspectRatioFrameLayout> </androidx.media3.ui.AspectRatioFrameLayout>
<androidx.media3.ui.SubtitleView <androidx.media3.ui.SubtitleView
@ -88,4 +71,10 @@
android:layout_height="match_parent" android:layout_height="match_parent"
app:animation_enabled="false"/> app:animation_enabled="false"/>
<include
layout="@layout/exo_player_skip_control"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</merge> </merge>

View file

@ -247,11 +247,11 @@ constructor(
val itemId = UUID.fromString(currentMediaItem.mediaId) val itemId = UUID.fromString(currentMediaItem.mediaId)
val seconds = player.currentPosition / 1000.0 val seconds = player.currentPosition / 1000.0
val currentSegment = segments[itemId]?.find { segment -> seconds in segment.startTime..segment.endTime } val currentSegment = segments[itemId]?.find { segment -> seconds in segment.startTime..<segment.endTime }
_uiState.update { it.copy(currentSegment = currentSegment) } _uiState.update { it.copy(currentSegment = currentSegment) }
Timber.tag("SegmentInfo").d("currentSegment: %s", currentSegment) Timber.tag("SegmentInfo").d("currentSegment: %s", currentSegment)
val showSkip = currentSegment?.let { it.skip && seconds in it.showAt..it.hideAt } ?: false val showSkip = currentSegment?.let { it.skip && seconds in it.showAt..<it.hideAt } ?: false
_uiState.update { it.copy(showSkip = showSkip) } _uiState.update { it.copy(showSkip = showSkip) }
} }
handler.postDelayed(this, 1000L) handler.postDelayed(this, 1000L)