Improve skipButton visibility/usability
This commit is contained in:
parent
df984fb24b
commit
91cccc55a7
4 changed files with 63 additions and 32 deletions
|
@ -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 {
|
||||||
|
|
25
app/phone/src/main/res/layout/exo_player_skip_control.xml
Normal file
25
app/phone/src/main/res/layout/exo_player_skip_control.xml
Normal 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>
|
|
@ -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>
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue