testing tag for tv focus + player popup fix

This commit is contained in:
LagradOst 2023-07-25 21:15:10 +02:00
parent 3e4a5bdf4c
commit 31da089eb1
9 changed files with 174 additions and 108 deletions

View File

@ -744,23 +744,35 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
return ret return ret
} }
var binding: ActivityMainBinding? = null private var binding: ActivityMainBinding? = null
var focusOutline: WeakReference<View> = WeakReference(null) private var focusOutline: WeakReference<View> = WeakReference(null)
var lastFocus: WeakReference<View> = WeakReference(null) private var lastFocus: WeakReference<View> = WeakReference(null)
val layoutListener: View.OnLayoutChangeListener = private val layoutListener: View.OnLayoutChangeListener =
View.OnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom -> View.OnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
updateFocusView( updateFocusView(
v v
) )
} }
private val attachListener : View.OnAttachStateChangeListener = object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
updateFocusView(v)
}
override fun onViewDetachedFromWindow(v: View) {
// removes the focus view but not the listener as updateFocusView(null) will remove the listener
focusOutline.get()?.isVisible = false
}
}
private fun updateFocusView(newFocus: View?) { private fun updateFocusView(newFocus: View?) {
val focusOutline = focusOutline.get() ?: return val focusOutline = focusOutline.get() ?: return
//lastFocus.get()?.removeOnLayoutChangeListener(layoutListener) lastFocus.get()?.removeOnLayoutChangeListener(layoutListener)
lastFocus.get()?.removeOnAttachStateChangeListener(attachListener)
val wasGone = focusOutline.isGone val wasGone = focusOutline.isGone
focusOutline.isVisible =
newFocus != null && newFocus.measuredHeight > 0 && newFocus.measuredWidth > 0 && newFocus.isVisible && newFocus !is MaterialButton
val visible =
newFocus != null && newFocus.measuredHeight > 0 && newFocus.measuredWidth > 0 && newFocus.isVisible && newFocus.tag != "tv_no_focus_tag"
focusOutline.isVisible = visible
if (newFocus != null) { if (newFocus != null) {
lastFocus = WeakReference(newFocus) lastFocus = WeakReference(newFocus)
@ -781,8 +793,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
} }
}*/ }*/
// newFocus.addOnLayoutChangeListener(layoutListener) newFocus.addOnLayoutChangeListener(layoutListener)
newFocus.addOnAttachStateChangeListener(attachListener)
// val set = AnimationSet(true) // val set = AnimationSet(true)
if(!wasGone) { if(!wasGone) {

View File

@ -52,7 +52,15 @@ import javax.net.ssl.SSLSession
const val TAG = "CS3ExoPlayer" const val TAG = "CS3ExoPlayer"
const val PREFERRED_AUDIO_LANGUAGE_KEY = "preferred_audio_language" const val PREFERRED_AUDIO_LANGUAGE_KEY = "preferred_audio_language"
/** Cache */ /** toleranceBeforeUs The maximum time that the actual position seeked to may precede the
* requested seek position, in microseconds. Must be non-negative. */
const val toleranceBeforeUs = 300_000L
/**
* toleranceAfterUs The maximum time that the actual position seeked to may exceed the requested
* seek position, in microseconds. Must be non-negative.
*/
const val toleranceAfterUs = 300_000L
class CS3IPlayer : IPlayer { class CS3IPlayer : IPlayer {
private var isPlaying = false private var isPlaying = false
@ -387,6 +395,7 @@ class CS3IPlayer : IPlayer {
Log.i(TAG, "setPreferredSubtitles REQUIRES_RELOAD") Log.i(TAG, "setPreferredSubtitles REQUIRES_RELOAD")
return@let true return@let true
} }
SubtitleStatus.IS_ACTIVE -> { SubtitleStatus.IS_ACTIVE -> {
Log.i(TAG, "setPreferredSubtitles IS_ACTIVE") Log.i(TAG, "setPreferredSubtitles IS_ACTIVE")
@ -412,6 +421,7 @@ class CS3IPlayer : IPlayer {
// }, 1) // }, 1)
//} //}
} }
SubtitleStatus.NOT_FOUND -> { SubtitleStatus.NOT_FOUND -> {
Log.i(TAG, "setPreferredSubtitles NOT_FOUND") Log.i(TAG, "setPreferredSubtitles NOT_FOUND")
return@let true return@let true
@ -678,22 +688,22 @@ class CS3IPlayer : IPlayer {
// Enable Ffmpeg extension // Enable Ffmpeg extension
// setExtensionRendererMode(EXTENSION_RENDERER_MODE_ON) // setExtensionRendererMode(EXTENSION_RENDERER_MODE_ON)
}.createRenderers( }.createRenderers(
eventHandler, eventHandler,
videoRendererEventListener, videoRendererEventListener,
audioRendererEventListener, audioRendererEventListener,
textRendererOutput, textRendererOutput,
metadataRendererOutput metadataRendererOutput
).map { ).map {
if (it is TextRenderer) { if (it is TextRenderer) {
currentTextRenderer = CustomTextRenderer( currentTextRenderer = CustomTextRenderer(
subtitleOffset, subtitleOffset,
textRendererOutput, textRendererOutput,
eventHandler.looper, eventHandler.looper,
CustomSubtitleDecoderFactory() CustomSubtitleDecoderFactory()
) )
currentTextRenderer!! currentTextRenderer!!
} else it } else it
}.toTypedArray() }.toTypedArray()
} }
.setTrackSelector( .setTrackSelector(
trackSelector ?: getTrackSelector( trackSelector ?: getTrackSelector(
@ -702,7 +712,7 @@ class CS3IPlayer : IPlayer {
) )
) )
// Allows any seeking to be +- 0.3s to allow for faster seeking // Allows any seeking to be +- 0.3s to allow for faster seeking
.setSeekParameters(SeekParameters(300_000, 300_000)) .setSeekParameters(SeekParameters(toleranceBeforeUs, toleranceAfterUs))
.setLoadControl( .setLoadControl(
DefaultLoadControl.Builder() DefaultLoadControl.Builder()
.setTargetBufferBytes( .setTargetBufferBytes(
@ -769,7 +779,7 @@ class CS3IPlayer : IPlayer {
private fun getCurrentTimestamp(writePosition: Long? = null): EpisodeSkip.SkipStamp? { private fun getCurrentTimestamp(writePosition: Long? = null): EpisodeSkip.SkipStamp? {
val position = writePosition ?: this@CS3IPlayer.getPosition() ?: return null val position = writePosition ?: this@CS3IPlayer.getPosition() ?: return null
for (lastTimeStamp in lastTimeStamps) { for (lastTimeStamp in lastTimeStamps) {
if (lastTimeStamp.startMs <= position && position < lastTimeStamp.endMs) { if (lastTimeStamp.startMs <= position && (position + (toleranceBeforeUs / 1000L) + 1) < lastTimeStamp.endMs) {
return lastTimeStamp return lastTimeStamp
} }
} }
@ -777,11 +787,12 @@ class CS3IPlayer : IPlayer {
} }
fun updatedTime(writePosition: Long? = null) { fun updatedTime(writePosition: Long? = null) {
getCurrentTimestamp(writePosition)?.let { timestamp -> val position = writePosition ?: exoPlayer?.currentPosition
getCurrentTimestamp(position)?.let { timestamp ->
onTimestampInvoked?.invoke(timestamp) onTimestampInvoked?.invoke(timestamp)
} }
val position = writePosition ?: exoPlayer?.currentPosition
val duration = exoPlayer?.contentDuration val duration = exoPlayer?.contentDuration
if (duration != null && position != null) { if (duration != null && position != null) {
playerPositionChanged?.invoke(Pair(position, duration)) playerPositionChanged?.invoke(Pair(position, duration))
@ -810,9 +821,11 @@ class CS3IPlayer : IPlayer {
CSPlayerEvent.Play -> { CSPlayerEvent.Play -> {
play() play()
} }
CSPlayerEvent.Pause -> { CSPlayerEvent.Pause -> {
pause() pause()
} }
CSPlayerEvent.ToggleMute -> { CSPlayerEvent.ToggleMute -> {
if (volume <= 0) { if (volume <= 0) {
//is muted //is muted
@ -823,6 +836,7 @@ class CS3IPlayer : IPlayer {
volume = 0f volume = 0f
} }
} }
CSPlayerEvent.PlayPauseToggle -> { CSPlayerEvent.PlayPauseToggle -> {
if (isPlaying) { if (isPlaying) {
pause() pause()
@ -830,6 +844,7 @@ class CS3IPlayer : IPlayer {
play() play()
} }
} }
CSPlayerEvent.SeekForward -> seekTime(seekActionTime) CSPlayerEvent.SeekForward -> seekTime(seekActionTime)
CSPlayerEvent.SeekBack -> seekTime(-seekActionTime) CSPlayerEvent.SeekBack -> seekTime(-seekActionTime)
CSPlayerEvent.NextEpisode -> nextEpisode?.invoke() CSPlayerEvent.NextEpisode -> nextEpisode?.invoke()
@ -954,6 +969,7 @@ class CS3IPlayer : IPlayer {
Player.STATE_READY -> { Player.STATE_READY -> {
onRenderFirst() onRenderFirst()
} }
else -> {} else -> {}
} }
@ -963,6 +979,7 @@ class CS3IPlayer : IPlayer {
Player.STATE_READY -> { Player.STATE_READY -> {
} }
Player.STATE_ENDED -> { Player.STATE_ENDED -> {
// Only play next episode if autoplay is on (default) // Only play next episode if autoplay is on (default)
if (PreferenceManager.getDefaultSharedPreferences(context) if (PreferenceManager.getDefaultSharedPreferences(context)
@ -974,12 +991,15 @@ class CS3IPlayer : IPlayer {
handleEvent(CSPlayerEvent.NextEpisode) handleEvent(CSPlayerEvent.NextEpisode)
} }
} }
Player.STATE_BUFFERING -> { Player.STATE_BUFFERING -> {
updatedTime() updatedTime()
} }
Player.STATE_IDLE -> { Player.STATE_IDLE -> {
// IDLE // IDLE
} }
else -> Unit else -> Unit
} }
} }
@ -994,11 +1014,13 @@ class CS3IPlayer : IPlayer {
&& exoPlayer?.duration != TIME_UNSET -> { && exoPlayer?.duration != TIME_UNSET -> {
exoPlayer?.prepare() exoPlayer?.prepare()
} }
error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> { error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> {
// Re-initialize player at the current live window default position. // Re-initialize player at the current live window default position.
exoPlayer?.seekToDefaultPosition() exoPlayer?.seekToDefaultPosition()
exoPlayer?.prepare() exoPlayer?.prepare()
} }
else -> { else -> {
playerError?.invoke(error) playerError?.invoke(error)
} }
@ -1025,6 +1047,7 @@ class CS3IPlayer : IPlayer {
Player.STATE_READY -> { Player.STATE_READY -> {
} }
Player.STATE_ENDED -> { Player.STATE_ENDED -> {
// Only play next episode if autoplay is on (default) // Only play next episode if autoplay is on (default)
if (PreferenceManager.getDefaultSharedPreferences(context) if (PreferenceManager.getDefaultSharedPreferences(context)
@ -1036,12 +1059,15 @@ class CS3IPlayer : IPlayer {
handleEvent(CSPlayerEvent.NextEpisode) handleEvent(CSPlayerEvent.NextEpisode)
} }
} }
Player.STATE_BUFFERING -> { Player.STATE_BUFFERING -> {
updatedTime() updatedTime()
} }
Player.STATE_IDLE -> { Player.STATE_IDLE -> {
// IDLE // IDLE
} }
else -> Unit else -> Unit
} }
} }
@ -1052,9 +1078,9 @@ class CS3IPlayer : IPlayer {
} }
override fun onRenderedFirstFrame() { override fun onRenderedFirstFrame() {
updatedTime()
super.onRenderedFirstFrame() super.onRenderedFirstFrame()
onRenderFirst() onRenderFirst()
updatedTime()
} }
}) })
} catch (e: Exception) { } catch (e: Exception) {
@ -1082,42 +1108,43 @@ class CS3IPlayer : IPlayer {
} }
fun onRenderFirst() { fun onRenderFirst() {
if (!hasUsedFirstRender) { // this insures that we only call this once per player load if (hasUsedFirstRender) { // this insures that we only call this once per player load
Log.i(TAG, "Rendered first frame") return
val invalid = exoPlayer?.duration?.let { duration -> }
// Only errors short playback when not playing downloaded files Log.i(TAG, "Rendered first frame")
duration < 20_000L && currentDownloadedFile == null hasUsedFirstRender = true
// Concatenated sources (non 1 periodCount) bypasses the invalid check as exoPlayer.duration gives only the current period val invalid = exoPlayer?.duration?.let { duration ->
// If you can get the total time that'd be better, but this is already niche. // Only errors short playback when not playing downloaded files
&& exoPlayer?.currentTimeline?.periodCount == 1 duration < 20_000L && currentDownloadedFile == null
&& exoPlayer?.isCurrentMediaItemLive != true // Concatenated sources (non 1 periodCount) bypasses the invalid check as exoPlayer.duration gives only the current period
} ?: false // If you can get the total time that'd be better, but this is already niche.
&& exoPlayer?.currentTimeline?.periodCount == 1
&& exoPlayer?.isCurrentMediaItemLive != true
} ?: false
if (invalid) { if (invalid) {
releasePlayer(saveTime = false) releasePlayer(saveTime = false)
playerError?.invoke(InvalidFileException("Too short playback")) playerError?.invoke(InvalidFileException("Too short playback"))
return return
} }
setPreferredSubtitles(currentSubtitles) setPreferredSubtitles(currentSubtitles)
hasUsedFirstRender = true val format = exoPlayer?.videoFormat
val format = exoPlayer?.videoFormat val width = format?.width
val width = format?.width val height = format?.height
val height = format?.height if (height != null && width != null) {
if (height != null && width != null) { playerDimensionsLoaded?.invoke(Pair(width, height))
playerDimensionsLoaded?.invoke(Pair(width, height)) updatedTime()
updatedTime() exoPlayer?.apply {
exoPlayer?.apply { requestedListeningPercentages?.forEach { percentage ->
requestedListeningPercentages?.forEach { percentage -> createMessage { _, _ ->
createMessage { _, _ -> updatedTime()
updatedTime()
}
.setLooper(Looper.getMainLooper())
.setPosition( /* positionMs= */contentDuration * percentage / 100)
// .setPayload(customPayloadData)
.setDeleteAfterDelivery(false)
.send()
} }
.setLooper(Looper.getMainLooper())
.setPosition(contentDuration * percentage / 100)
// .setPayload(customPayloadData)
.setDeleteAfterDelivery(false)
.send()
} }
} }
} }
@ -1169,6 +1196,7 @@ class CS3IPlayer : IPlayer {
null null
} }
} }
SubtitleOrigin.URL -> { SubtitleOrigin.URL -> {
if (onlineSourceFactory != null) { if (onlineSourceFactory != null) {
activeSubtitles.add(sub) activeSubtitles.add(sub)
@ -1181,6 +1209,7 @@ class CS3IPlayer : IPlayer {
null null
} }
} }
SubtitleOrigin.EMBEDDED_IN_VIDEO -> { SubtitleOrigin.EMBEDDED_IN_VIDEO -> {
if (offlineSourceFactory != null) { if (offlineSourceFactory != null) {
activeSubtitles.add(sub) activeSubtitles.add(sub)

View File

@ -1294,6 +1294,7 @@ class GeneratorPlayer : FullScreenPlayer() {
override fun onTimestamp(timestamp: EpisodeSkip.SkipStamp?) { override fun onTimestamp(timestamp: EpisodeSkip.SkipStamp?) {
if (timestamp != null) { if (timestamp != null) {
println("timestamp: $timestamp")
playerBinding?.skipChapterButton?.setText(timestamp.uiText) playerBinding?.skipChapterButton?.setText(timestamp.uiText)
displayTimeStamp(true) displayTimeStamp(true)
val currentIndex = skipIndex val currentIndex = skipIndex

View File

@ -90,8 +90,8 @@
android:id="@+id/focus_outline" android:id="@+id/focus_outline"
android:src="@drawable/outline" android:src="@drawable/outline"
android:layout_width="100dp" android:layout_width="100dp"
android:layout_height="100dp"> android:layout_height="100dp"
android:importantForAccessibility="no">
</ImageView> </ImageView>
</FrameLayout> </FrameLayout>
</FrameLayout> </FrameLayout>

View File

@ -93,7 +93,7 @@
</FrameLayout> </FrameLayout>
</FrameLayout> </FrameLayout>
<FrameLayout <!-- <FrameLayout
android:id="@+id/player_torrent_info" android:id="@+id/player_torrent_info"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -127,5 +127,5 @@
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/player_video_title" app:layout_constraintTop_toBottomOf="@+id/player_video_title"
tools:text="17 seeders" /> tools:text="17 seeders" />
</FrameLayout> </FrameLayout>-->
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -78,6 +78,7 @@
app:tint="@android:color/white" /> app:tint="@android:color/white" />
<ImageView <ImageView
android:tag="@string/tv_no_focus_tag"
android:id="@+id/player_loading_go_back" android:id="@+id/player_loading_go_back"
android:layout_width="70dp" android:layout_width="70dp"
android:layout_height="70dp" android:layout_height="70dp"
@ -92,7 +93,7 @@
</FrameLayout> </FrameLayout>
</FrameLayout> </FrameLayout>
<FrameLayout <!--<FrameLayout
android:id="@+id/player_torrent_info" android:id="@+id/player_torrent_info"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -126,5 +127,5 @@
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/player_video_title" app:layout_constraintTop_toBottomOf="@+id/player_video_title"
tools:text="17 seeders" /> tools:text="17 seeders" />
</FrameLayout> </FrameLayout>-->
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -168,24 +168,23 @@
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<FrameLayout <FrameLayout
android:visibility="gone"
android:id="@+id/player_intro_play" android:id="@+id/player_intro_play"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" /> android:layout_height="0dp"
android:visibility="gone" />
<ImageView <ImageView
android:visibility="gone"
android:id="@+id/player_open_source" android:id="@+id/player_open_source"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:clickable="false" android:clickable="false"
android:focusable="false" android:focusable="false"
android:focusableInTouchMode="false" android:focusableInTouchMode="false"
android:importantForAccessibility="no" /> android:importantForAccessibility="no"
android:visibility="gone" />
<!-- atm this is useless, however it might be used for PIP one day? --> <!-- atm this is useless, however it might be used for PIP one day? -->
<ImageView <ImageView
android:visibility="gone"
android:id="@+id/player_fullscreen" android:id="@+id/player_fullscreen"
android:layout_width="30dp" android:layout_width="30dp"
android:layout_height="30dp" android:layout_height="30dp"
@ -193,6 +192,7 @@
android:layout_marginEnd="20dp" android:layout_marginEnd="20dp"
android:background="?android:attr/selectableItemBackgroundBorderless" android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/baseline_fullscreen_24" android:src="@drawable/baseline_fullscreen_24"
android:visibility="gone"
app:tint="@color/white" /> app:tint="@color/white" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
@ -209,6 +209,9 @@
android:layout_marginEnd="100dp" android:layout_marginEnd="100dp"
android:backgroundTint="@color/skipOpTransparent" android:backgroundTint="@color/skipOpTransparent"
android:maxLines="1" android:maxLines="1"
android:nextFocusLeft="@id/player_pause_play"
android:nextFocusUp="@id/player_go_back"
android:nextFocusDown="@id/player_pause_play"
android:padding="10dp" android:padding="10dp"
android:textColor="@color/white" android:textColor="@color/white"
android:visibility="gone" android:visibility="gone"
@ -302,7 +305,8 @@
android:background="@drawable/video_tap_button_always_white" android:background="@drawable/video_tap_button_always_white"
android:clickable="true" android:clickable="true"
android:contentDescription="@string/go_back_img_des" android:contentDescription="@string/go_back_img_des"
android:focusable="true" /> android:focusable="true"
android:tag="@string/tv_no_focus_tag" />
</FrameLayout> </FrameLayout>
</FrameLayout> </FrameLayout>
@ -323,11 +327,11 @@
tools:visibility="visible"> tools:visibility="visible">
<FrameLayout <FrameLayout
android:visibility="gone"
android:id="@+id/player_rew_holder" android:id="@+id/player_rew_holder"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start" android:layout_gravity="center_vertical|start"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/player_ffwd_holder" app:layout_constraintRight_toLeftOf="@id/player_ffwd_holder"
@ -356,7 +360,7 @@
android:background="@drawable/video_tap_button_skip" android:background="@drawable/video_tap_button_skip"
android:nextFocusLeft="@id/exo_rew" android:nextFocusLeft="@id/exo_rew"
android:nextFocusUp="@id/player_go_back" android:nextFocusUp="@id/player_go_back"
android:nextFocusDown="@id/player_lock" android:nextFocusDown="@id/player_pause_play"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:scaleX="-1" android:scaleX="-1"
@ -367,11 +371,11 @@
</FrameLayout> </FrameLayout>
<FrameLayout <FrameLayout
android:visibility="gone"
android:id="@+id/player_ffwd_holder" android:id="@+id/player_ffwd_holder"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end" android:layout_gravity="center_vertical|end"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/player_rew_holder" app:layout_constraintLeft_toRightOf="@id/player_rew_holder"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
@ -398,7 +402,7 @@
android:background="@drawable/video_tap_button_skip" android:background="@drawable/video_tap_button_skip"
android:nextFocusRight="@id/exo_rew" android:nextFocusRight="@id/exo_rew"
android:nextFocusUp="@id/player_go_back" android:nextFocusUp="@id/player_go_back"
android:nextFocusDown="@id/player_lock" android:nextFocusDown="@id/player_pause_play"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/netflix_skip_forward" android:src="@drawable/netflix_skip_forward"
@ -508,6 +512,7 @@
<ImageView <ImageView
android:id="@+id/player_pause_play" android:id="@+id/player_pause_play"
android:layout_width="30dp" android:layout_width="30dp"
android:layout_height="30dp" android:layout_height="30dp"
android:layout_gravity="center" android:layout_gravity="center"
@ -515,10 +520,11 @@
android:background="@drawable/video_tap_button" android:background="@drawable/video_tap_button"
android:focusable="true" android:focusable="true"
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
android:nextFocusUp="@id/player_go_back" android:nextFocusUp="@id/skip_chapter_button"
android:nextFocusDown="@id/player_lock" android:nextFocusDown="@id/player_skip_op"
android:src="@drawable/netflix_pause" android:src="@drawable/netflix_pause"
android:tag="@string/tv_no_focus_tag"
app:tint="@color/player_button_tv" app:tint="@color/player_button_tv"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
@ -582,9 +588,10 @@
android:orientation="horizontal"> android:orientation="horizontal">
<FrameLayout <FrameLayout
android:visibility="gone"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp"> android:layout_height="0dp"
android:visibility="gone">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/player_lock" android:id="@+id/player_lock"
style="@style/VideoButtonTV" style="@style/VideoButtonTV"
@ -597,12 +604,35 @@
app:icon="@drawable/video_locked" /> app:icon="@drawable/video_locked" />
</FrameLayout> </FrameLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/player_skip_op"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_pause_play"
android:nextFocusRight="@id/player_skip_episode"
android:nextFocusUp="@id/player_pause_play"
android:nextFocusDown="@id/player_skip_episode"
android:text="@string/video_skip_op"
app:icon="@drawable/ic_baseline_fast_forward_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/player_skip_episode"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_skip_op"
android:nextFocusRight="@id/player_resize_btt"
android:nextFocusUp="@id/player_pause_play"
android:nextFocusDown="@id/player_resize_btt"
android:text="@string/next_episode"
app:icon="@drawable/ic_baseline_skip_next_24" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/player_resize_btt" android:id="@+id/player_resize_btt"
style="@style/VideoButtonTV" style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_lock" android:nextFocusLeft="@id/player_skip_episode"
android:nextFocusRight="@id/player_speed_btt" android:nextFocusRight="@id/player_speed_btt"
android:nextFocusUp="@id/player_pause_play" android:nextFocusUp="@id/player_pause_play"
android:nextFocusDown="@id/player_speed_btt"
android:text="@string/video_aspect_ratio_resize" android:text="@string/video_aspect_ratio_resize"
app:icon="@drawable/ic_baseline_aspect_ratio_24" /> app:icon="@drawable/ic_baseline_aspect_ratio_24" />
@ -610,8 +640,10 @@
android:id="@+id/player_speed_btt" android:id="@+id/player_speed_btt"
style="@style/VideoButtonTV" style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_resize_btt" android:nextFocusLeft="@id/player_resize_btt"
android:nextFocusRight="@id/player_subtitle_offset_btt" android:nextFocusRight="@id/player_subtitle_offset_btt"
android:nextFocusUp="@id/player_pause_play" android:nextFocusUp="@id/player_pause_play"
android:nextFocusDown="@id/player_subtitle_offset_btt"
app:icon="@drawable/ic_baseline_speed_24" app:icon="@drawable/ic_baseline_speed_24"
tools:text="Speed" /> tools:text="Speed" />
@ -620,6 +652,8 @@
style="@style/VideoButtonTV" style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_speed_btt" android:nextFocusLeft="@id/player_speed_btt"
android:nextFocusRight="@id/player_sources_btt" android:nextFocusRight="@id/player_sources_btt"
android:nextFocusUp="@id/player_pause_play"
android:nextFocusDown="@id/player_sources_btt"
android:text="@string/subtitle_offset" android:text="@string/subtitle_offset"
android:visibility="gone" android:visibility="gone"
@ -632,6 +666,8 @@
android:nextFocusLeft="@id/player_subtitle_offset_btt" android:nextFocusLeft="@id/player_subtitle_offset_btt"
android:nextFocusRight="@id/player_tracks_btt" android:nextFocusRight="@id/player_tracks_btt"
android:nextFocusUp="@id/player_pause_play" android:nextFocusUp="@id/player_pause_play"
android:nextFocusDown="@id/player_tracks_btt"
android:text="@string/video_source" android:text="@string/video_source"
app:icon="@drawable/ic_baseline_playlist_play_24" /> app:icon="@drawable/ic_baseline_playlist_play_24" />
@ -643,25 +679,6 @@
android:nextFocusUp="@id/player_pause_play" android:nextFocusUp="@id/player_pause_play"
android:text="@string/tracks" android:text="@string/tracks"
app:icon="@drawable/ic_baseline_playlist_play_24" /> app:icon="@drawable/ic_baseline_playlist_play_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/player_skip_op"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_sources_btt"
android:nextFocusRight="@id/player_skip_episode"
android:nextFocusUp="@id/player_pause_play"
android:text="@string/video_skip_op"
app:icon="@drawable/ic_baseline_fast_forward_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/player_skip_episode"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_skip_op"
android:nextFocusRight="@id/player_lock"
android:nextFocusUp="@id/player_pause_play"
android:text="@string/next_episode"
app:icon="@drawable/ic_baseline_skip_next_24" />
</LinearLayout> </LinearLayout>
</HorizontalScrollView> </HorizontalScrollView>
</LinearLayout> </LinearLayout>

View File

@ -678,4 +678,7 @@
<string name="qualities">Qualities</string> <string name="qualities">Qualities</string>
<string name="profile_background_des">Profile background</string> <string name="profile_background_des">Profile background</string>
<string name="unable_to_inflate">UI was unable to be created correctly, this is a MAJOR BUG and should be reported immediately %s</string> <string name="unable_to_inflate">UI was unable to be created correctly, this is a MAJOR BUG and should be reported immediately %s</string>
<string name="tv_no_focus_tag" translatable="false">tv_no_focus_tag</string>
</resources> </resources>

View File

@ -495,9 +495,10 @@
<item name="android:paddingStart">20dp</item> <item name="android:paddingStart">20dp</item>
<item name="android:paddingEnd">20dp</item> <item name="android:paddingEnd">20dp</item>
<item name="android:selectAllOnFocus">true</item> <item name="android:selectAllOnFocus">true</item>
<item name="android:background">@drawable/outline_drawable_less</item> <!-- <item name="android:background">@drawable/outline_drawable_less</item>
<item name="android:foreground">?attr/selectableItemBackgroundBorderless</item>
-->
<item name="android:textColor">?attr/textColor</item> <item name="android:textColor">?attr/textColor</item>
<item name="android:foreground">?attr/selectableItemBackgroundBorderless</item>
<item name="android:textAppearance">?android:attr/textAppearanceListItemSmall</item> <item name="android:textAppearance">?android:attr/textAppearanceListItemSmall</item>
<item name="drawableEndCompat">@drawable/ic_baseline_keyboard_arrow_right_24</item> <item name="drawableEndCompat">@drawable/ic_baseline_keyboard_arrow_right_24</item>
</style> </style>
@ -547,6 +548,7 @@
<item name="android:insetTop">0dp</item> <item name="android:insetTop">0dp</item>
<item name="android:insetBottom">0dp</item> <item name="android:insetBottom">0dp</item>
<item name="android:foreground">@drawable/outline_drawable_less</item> <item name="android:foreground">@drawable/outline_drawable_less</item>
<item name="android:tag">@string/tv_no_focus_tag</item>
</style> </style>
<style name="WhiteButton" parent="NiceButton"> <style name="WhiteButton" parent="NiceButton">
@ -760,6 +762,7 @@
</style> </style>
<style name="VideoButtonTV"> <style name="VideoButtonTV">
<item name="android:tag">@string/tv_no_focus_tag</item>
<item name="android:stateListAnimator">@null</item> <item name="android:stateListAnimator">@null</item>
<item name="strokeColor">@color/transparent</item> <item name="strokeColor">@color/transparent</item>
<item name="backgroundTint">@null</item> <item name="backgroundTint">@null</item>