mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
testing tag for tv focus + player popup fix
This commit is contained in:
parent
3e4a5bdf4c
commit
31da089eb1
9 changed files with 174 additions and 108 deletions
|
@ -744,23 +744,35 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
return ret
|
||||
}
|
||||
|
||||
var binding: ActivityMainBinding? = null
|
||||
var focusOutline: WeakReference<View> = WeakReference(null)
|
||||
var lastFocus: WeakReference<View> = WeakReference(null)
|
||||
val layoutListener: View.OnLayoutChangeListener =
|
||||
View.OnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
|
||||
private var binding: ActivityMainBinding? = null
|
||||
private var focusOutline: WeakReference<View> = WeakReference(null)
|
||||
private var lastFocus: WeakReference<View> = WeakReference(null)
|
||||
private val layoutListener: View.OnLayoutChangeListener =
|
||||
View.OnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
|
||||
updateFocusView(
|
||||
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?) {
|
||||
val focusOutline = focusOutline.get() ?: return
|
||||
//lastFocus.get()?.removeOnLayoutChangeListener(layoutListener)
|
||||
lastFocus.get()?.removeOnLayoutChangeListener(layoutListener)
|
||||
lastFocus.get()?.removeOnAttachStateChangeListener(attachListener)
|
||||
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) {
|
||||
lastFocus = WeakReference(newFocus)
|
||||
|
||||
|
@ -781,8 +793,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
}
|
||||
|
||||
}*/
|
||||
// newFocus.addOnLayoutChangeListener(layoutListener)
|
||||
|
||||
newFocus.addOnLayoutChangeListener(layoutListener)
|
||||
newFocus.addOnAttachStateChangeListener(attachListener)
|
||||
|
||||
// val set = AnimationSet(true)
|
||||
if(!wasGone) {
|
||||
|
|
|
@ -52,7 +52,15 @@ import javax.net.ssl.SSLSession
|
|||
const val TAG = "CS3ExoPlayer"
|
||||
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 {
|
||||
private var isPlaying = false
|
||||
|
@ -387,6 +395,7 @@ class CS3IPlayer : IPlayer {
|
|||
Log.i(TAG, "setPreferredSubtitles REQUIRES_RELOAD")
|
||||
return@let true
|
||||
}
|
||||
|
||||
SubtitleStatus.IS_ACTIVE -> {
|
||||
Log.i(TAG, "setPreferredSubtitles IS_ACTIVE")
|
||||
|
||||
|
@ -412,6 +421,7 @@ class CS3IPlayer : IPlayer {
|
|||
// }, 1)
|
||||
//}
|
||||
}
|
||||
|
||||
SubtitleStatus.NOT_FOUND -> {
|
||||
Log.i(TAG, "setPreferredSubtitles NOT_FOUND")
|
||||
return@let true
|
||||
|
@ -678,22 +688,22 @@ class CS3IPlayer : IPlayer {
|
|||
// Enable Ffmpeg extension
|
||||
// setExtensionRendererMode(EXTENSION_RENDERER_MODE_ON)
|
||||
}.createRenderers(
|
||||
eventHandler,
|
||||
videoRendererEventListener,
|
||||
audioRendererEventListener,
|
||||
textRendererOutput,
|
||||
metadataRendererOutput
|
||||
).map {
|
||||
if (it is TextRenderer) {
|
||||
currentTextRenderer = CustomTextRenderer(
|
||||
subtitleOffset,
|
||||
textRendererOutput,
|
||||
eventHandler.looper,
|
||||
CustomSubtitleDecoderFactory()
|
||||
)
|
||||
currentTextRenderer!!
|
||||
} else it
|
||||
}.toTypedArray()
|
||||
eventHandler,
|
||||
videoRendererEventListener,
|
||||
audioRendererEventListener,
|
||||
textRendererOutput,
|
||||
metadataRendererOutput
|
||||
).map {
|
||||
if (it is TextRenderer) {
|
||||
currentTextRenderer = CustomTextRenderer(
|
||||
subtitleOffset,
|
||||
textRendererOutput,
|
||||
eventHandler.looper,
|
||||
CustomSubtitleDecoderFactory()
|
||||
)
|
||||
currentTextRenderer!!
|
||||
} else it
|
||||
}.toTypedArray()
|
||||
}
|
||||
.setTrackSelector(
|
||||
trackSelector ?: getTrackSelector(
|
||||
|
@ -702,7 +712,7 @@ class CS3IPlayer : IPlayer {
|
|||
)
|
||||
)
|
||||
// Allows any seeking to be +- 0.3s to allow for faster seeking
|
||||
.setSeekParameters(SeekParameters(300_000, 300_000))
|
||||
.setSeekParameters(SeekParameters(toleranceBeforeUs, toleranceAfterUs))
|
||||
.setLoadControl(
|
||||
DefaultLoadControl.Builder()
|
||||
.setTargetBufferBytes(
|
||||
|
@ -769,7 +779,7 @@ class CS3IPlayer : IPlayer {
|
|||
private fun getCurrentTimestamp(writePosition: Long? = null): EpisodeSkip.SkipStamp? {
|
||||
val position = writePosition ?: this@CS3IPlayer.getPosition() ?: return null
|
||||
for (lastTimeStamp in lastTimeStamps) {
|
||||
if (lastTimeStamp.startMs <= position && position < lastTimeStamp.endMs) {
|
||||
if (lastTimeStamp.startMs <= position && (position + (toleranceBeforeUs / 1000L) + 1) < lastTimeStamp.endMs) {
|
||||
return lastTimeStamp
|
||||
}
|
||||
}
|
||||
|
@ -777,11 +787,12 @@ class CS3IPlayer : IPlayer {
|
|||
}
|
||||
|
||||
fun updatedTime(writePosition: Long? = null) {
|
||||
getCurrentTimestamp(writePosition)?.let { timestamp ->
|
||||
val position = writePosition ?: exoPlayer?.currentPosition
|
||||
|
||||
getCurrentTimestamp(position)?.let { timestamp ->
|
||||
onTimestampInvoked?.invoke(timestamp)
|
||||
}
|
||||
|
||||
val position = writePosition ?: exoPlayer?.currentPosition
|
||||
val duration = exoPlayer?.contentDuration
|
||||
if (duration != null && position != null) {
|
||||
playerPositionChanged?.invoke(Pair(position, duration))
|
||||
|
@ -810,9 +821,11 @@ class CS3IPlayer : IPlayer {
|
|||
CSPlayerEvent.Play -> {
|
||||
play()
|
||||
}
|
||||
|
||||
CSPlayerEvent.Pause -> {
|
||||
pause()
|
||||
}
|
||||
|
||||
CSPlayerEvent.ToggleMute -> {
|
||||
if (volume <= 0) {
|
||||
//is muted
|
||||
|
@ -823,6 +836,7 @@ class CS3IPlayer : IPlayer {
|
|||
volume = 0f
|
||||
}
|
||||
}
|
||||
|
||||
CSPlayerEvent.PlayPauseToggle -> {
|
||||
if (isPlaying) {
|
||||
pause()
|
||||
|
@ -830,6 +844,7 @@ class CS3IPlayer : IPlayer {
|
|||
play()
|
||||
}
|
||||
}
|
||||
|
||||
CSPlayerEvent.SeekForward -> seekTime(seekActionTime)
|
||||
CSPlayerEvent.SeekBack -> seekTime(-seekActionTime)
|
||||
CSPlayerEvent.NextEpisode -> nextEpisode?.invoke()
|
||||
|
@ -954,6 +969,7 @@ class CS3IPlayer : IPlayer {
|
|||
Player.STATE_READY -> {
|
||||
onRenderFirst()
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
||||
|
@ -963,6 +979,7 @@ class CS3IPlayer : IPlayer {
|
|||
Player.STATE_READY -> {
|
||||
|
||||
}
|
||||
|
||||
Player.STATE_ENDED -> {
|
||||
// Only play next episode if autoplay is on (default)
|
||||
if (PreferenceManager.getDefaultSharedPreferences(context)
|
||||
|
@ -974,12 +991,15 @@ class CS3IPlayer : IPlayer {
|
|||
handleEvent(CSPlayerEvent.NextEpisode)
|
||||
}
|
||||
}
|
||||
|
||||
Player.STATE_BUFFERING -> {
|
||||
updatedTime()
|
||||
}
|
||||
|
||||
Player.STATE_IDLE -> {
|
||||
// IDLE
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
@ -994,11 +1014,13 @@ class CS3IPlayer : IPlayer {
|
|||
&& exoPlayer?.duration != TIME_UNSET -> {
|
||||
exoPlayer?.prepare()
|
||||
}
|
||||
|
||||
error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> {
|
||||
// Re-initialize player at the current live window default position.
|
||||
exoPlayer?.seekToDefaultPosition()
|
||||
exoPlayer?.prepare()
|
||||
}
|
||||
|
||||
else -> {
|
||||
playerError?.invoke(error)
|
||||
}
|
||||
|
@ -1025,6 +1047,7 @@ class CS3IPlayer : IPlayer {
|
|||
Player.STATE_READY -> {
|
||||
|
||||
}
|
||||
|
||||
Player.STATE_ENDED -> {
|
||||
// Only play next episode if autoplay is on (default)
|
||||
if (PreferenceManager.getDefaultSharedPreferences(context)
|
||||
|
@ -1036,12 +1059,15 @@ class CS3IPlayer : IPlayer {
|
|||
handleEvent(CSPlayerEvent.NextEpisode)
|
||||
}
|
||||
}
|
||||
|
||||
Player.STATE_BUFFERING -> {
|
||||
updatedTime()
|
||||
}
|
||||
|
||||
Player.STATE_IDLE -> {
|
||||
// IDLE
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
@ -1052,9 +1078,9 @@ class CS3IPlayer : IPlayer {
|
|||
}
|
||||
|
||||
override fun onRenderedFirstFrame() {
|
||||
updatedTime()
|
||||
super.onRenderedFirstFrame()
|
||||
onRenderFirst()
|
||||
updatedTime()
|
||||
}
|
||||
})
|
||||
} catch (e: Exception) {
|
||||
|
@ -1082,42 +1108,43 @@ class CS3IPlayer : IPlayer {
|
|||
}
|
||||
|
||||
fun onRenderFirst() {
|
||||
if (!hasUsedFirstRender) { // this insures that we only call this once per player load
|
||||
Log.i(TAG, "Rendered first frame")
|
||||
val invalid = exoPlayer?.duration?.let { duration ->
|
||||
// Only errors short playback when not playing downloaded files
|
||||
duration < 20_000L && currentDownloadedFile == null
|
||||
// Concatenated sources (non 1 periodCount) bypasses the invalid check as exoPlayer.duration gives only the current period
|
||||
// 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 (hasUsedFirstRender) { // this insures that we only call this once per player load
|
||||
return
|
||||
}
|
||||
Log.i(TAG, "Rendered first frame")
|
||||
hasUsedFirstRender = true
|
||||
val invalid = exoPlayer?.duration?.let { duration ->
|
||||
// Only errors short playback when not playing downloaded files
|
||||
duration < 20_000L && currentDownloadedFile == null
|
||||
// Concatenated sources (non 1 periodCount) bypasses the invalid check as exoPlayer.duration gives only the current period
|
||||
// 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) {
|
||||
releasePlayer(saveTime = false)
|
||||
playerError?.invoke(InvalidFileException("Too short playback"))
|
||||
return
|
||||
}
|
||||
if (invalid) {
|
||||
releasePlayer(saveTime = false)
|
||||
playerError?.invoke(InvalidFileException("Too short playback"))
|
||||
return
|
||||
}
|
||||
|
||||
setPreferredSubtitles(currentSubtitles)
|
||||
hasUsedFirstRender = true
|
||||
val format = exoPlayer?.videoFormat
|
||||
val width = format?.width
|
||||
val height = format?.height
|
||||
if (height != null && width != null) {
|
||||
playerDimensionsLoaded?.invoke(Pair(width, height))
|
||||
updatedTime()
|
||||
exoPlayer?.apply {
|
||||
requestedListeningPercentages?.forEach { percentage ->
|
||||
createMessage { _, _ ->
|
||||
updatedTime()
|
||||
}
|
||||
.setLooper(Looper.getMainLooper())
|
||||
.setPosition( /* positionMs= */contentDuration * percentage / 100)
|
||||
// .setPayload(customPayloadData)
|
||||
.setDeleteAfterDelivery(false)
|
||||
.send()
|
||||
setPreferredSubtitles(currentSubtitles)
|
||||
val format = exoPlayer?.videoFormat
|
||||
val width = format?.width
|
||||
val height = format?.height
|
||||
if (height != null && width != null) {
|
||||
playerDimensionsLoaded?.invoke(Pair(width, height))
|
||||
updatedTime()
|
||||
exoPlayer?.apply {
|
||||
requestedListeningPercentages?.forEach { percentage ->
|
||||
createMessage { _, _ ->
|
||||
updatedTime()
|
||||
}
|
||||
.setLooper(Looper.getMainLooper())
|
||||
.setPosition(contentDuration * percentage / 100)
|
||||
// .setPayload(customPayloadData)
|
||||
.setDeleteAfterDelivery(false)
|
||||
.send()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1169,6 +1196,7 @@ class CS3IPlayer : IPlayer {
|
|||
null
|
||||
}
|
||||
}
|
||||
|
||||
SubtitleOrigin.URL -> {
|
||||
if (onlineSourceFactory != null) {
|
||||
activeSubtitles.add(sub)
|
||||
|
@ -1181,6 +1209,7 @@ class CS3IPlayer : IPlayer {
|
|||
null
|
||||
}
|
||||
}
|
||||
|
||||
SubtitleOrigin.EMBEDDED_IN_VIDEO -> {
|
||||
if (offlineSourceFactory != null) {
|
||||
activeSubtitles.add(sub)
|
||||
|
|
|
@ -1294,6 +1294,7 @@ class GeneratorPlayer : FullScreenPlayer() {
|
|||
|
||||
override fun onTimestamp(timestamp: EpisodeSkip.SkipStamp?) {
|
||||
if (timestamp != null) {
|
||||
println("timestamp: $timestamp")
|
||||
playerBinding?.skipChapterButton?.setText(timestamp.uiText)
|
||||
displayTimeStamp(true)
|
||||
val currentIndex = skipIndex
|
||||
|
|
|
@ -90,8 +90,8 @@
|
|||
android:id="@+id/focus_outline"
|
||||
android:src="@drawable/outline"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp">
|
||||
android:layout_height="100dp"
|
||||
android:importantForAccessibility="no">
|
||||
</ImageView>
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -93,7 +93,7 @@
|
|||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
<!-- <FrameLayout
|
||||
android:id="@+id/player_torrent_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -127,5 +127,5 @@
|
|||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/player_video_title"
|
||||
tools:text="17 seeders" />
|
||||
</FrameLayout>
|
||||
</FrameLayout>-->
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -78,6 +78,7 @@
|
|||
app:tint="@android:color/white" />
|
||||
|
||||
<ImageView
|
||||
android:tag="@string/tv_no_focus_tag"
|
||||
android:id="@+id/player_loading_go_back"
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="70dp"
|
||||
|
@ -92,7 +93,7 @@
|
|||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
<!--<FrameLayout
|
||||
android:id="@+id/player_torrent_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -126,5 +127,5 @@
|
|||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/player_video_title"
|
||||
tools:text="17 seeders" />
|
||||
</FrameLayout>
|
||||
</FrameLayout>-->
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -168,24 +168,23 @@
|
|||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:visibility="gone"
|
||||
android:id="@+id/player_intro_play"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp" />
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageView
|
||||
android:visibility="gone"
|
||||
android:id="@+id/player_open_source"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clickable="false"
|
||||
android:focusable="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? -->
|
||||
<ImageView
|
||||
android:visibility="gone"
|
||||
android:id="@+id/player_fullscreen"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
|
@ -193,6 +192,7 @@
|
|||
android:layout_marginEnd="20dp"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/baseline_fullscreen_24"
|
||||
android:visibility="gone"
|
||||
app:tint="@color/white" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
@ -209,6 +209,9 @@
|
|||
android:layout_marginEnd="100dp"
|
||||
android:backgroundTint="@color/skipOpTransparent"
|
||||
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:textColor="@color/white"
|
||||
android:visibility="gone"
|
||||
|
@ -302,7 +305,8 @@
|
|||
android:background="@drawable/video_tap_button_always_white"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/go_back_img_des"
|
||||
android:focusable="true" />
|
||||
android:focusable="true"
|
||||
android:tag="@string/tv_no_focus_tag" />
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
|
@ -323,11 +327,11 @@
|
|||
tools:visibility="visible">
|
||||
|
||||
<FrameLayout
|
||||
android:visibility="gone"
|
||||
android:id="@+id/player_rew_holder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@id/player_ffwd_holder"
|
||||
|
@ -356,7 +360,7 @@
|
|||
android:background="@drawable/video_tap_button_skip"
|
||||
android:nextFocusLeft="@id/exo_rew"
|
||||
android:nextFocusUp="@id/player_go_back"
|
||||
android:nextFocusDown="@id/player_lock"
|
||||
android:nextFocusDown="@id/player_pause_play"
|
||||
android:padding="10dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:scaleX="-1"
|
||||
|
@ -367,11 +371,11 @@
|
|||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:visibility="gone"
|
||||
android:id="@+id/player_ffwd_holder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@id/player_rew_holder"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
|
@ -398,7 +402,7 @@
|
|||
android:background="@drawable/video_tap_button_skip"
|
||||
android:nextFocusRight="@id/exo_rew"
|
||||
android:nextFocusUp="@id/player_go_back"
|
||||
android:nextFocusDown="@id/player_lock"
|
||||
android:nextFocusDown="@id/player_pause_play"
|
||||
android:padding="10dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/netflix_skip_forward"
|
||||
|
@ -508,6 +512,7 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/player_pause_play"
|
||||
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_gravity="center"
|
||||
|
@ -515,10 +520,11 @@
|
|||
android:background="@drawable/video_tap_button"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:nextFocusUp="@id/player_go_back"
|
||||
android:nextFocusDown="@id/player_lock"
|
||||
|
||||
android:nextFocusUp="@id/skip_chapter_button"
|
||||
android:nextFocusDown="@id/player_skip_op"
|
||||
android:src="@drawable/netflix_pause"
|
||||
|
||||
android:tag="@string/tv_no_focus_tag"
|
||||
app:tint="@color/player_button_tv"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
|
@ -582,9 +588,10 @@
|
|||
android:orientation="horizontal">
|
||||
|
||||
<FrameLayout
|
||||
android:visibility="gone"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp">
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/player_lock"
|
||||
style="@style/VideoButtonTV"
|
||||
|
@ -597,12 +604,35 @@
|
|||
app:icon="@drawable/video_locked" />
|
||||
</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
|
||||
android:id="@+id/player_resize_btt"
|
||||
style="@style/VideoButtonTV"
|
||||
android:nextFocusLeft="@id/player_lock"
|
||||
android:nextFocusLeft="@id/player_skip_episode"
|
||||
|
||||
android:nextFocusRight="@id/player_speed_btt"
|
||||
android:nextFocusUp="@id/player_pause_play"
|
||||
android:nextFocusDown="@id/player_speed_btt"
|
||||
android:text="@string/video_aspect_ratio_resize"
|
||||
app:icon="@drawable/ic_baseline_aspect_ratio_24" />
|
||||
|
||||
|
@ -610,8 +640,10 @@
|
|||
android:id="@+id/player_speed_btt"
|
||||
style="@style/VideoButtonTV"
|
||||
android:nextFocusLeft="@id/player_resize_btt"
|
||||
|
||||
android:nextFocusRight="@id/player_subtitle_offset_btt"
|
||||
android:nextFocusUp="@id/player_pause_play"
|
||||
android:nextFocusDown="@id/player_subtitle_offset_btt"
|
||||
app:icon="@drawable/ic_baseline_speed_24"
|
||||
tools:text="Speed" />
|
||||
|
||||
|
@ -620,6 +652,8 @@
|
|||
style="@style/VideoButtonTV"
|
||||
android:nextFocusLeft="@id/player_speed_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:visibility="gone"
|
||||
|
@ -632,6 +666,8 @@
|
|||
android:nextFocusLeft="@id/player_subtitle_offset_btt"
|
||||
android:nextFocusRight="@id/player_tracks_btt"
|
||||
android:nextFocusUp="@id/player_pause_play"
|
||||
android:nextFocusDown="@id/player_tracks_btt"
|
||||
|
||||
android:text="@string/video_source"
|
||||
app:icon="@drawable/ic_baseline_playlist_play_24" />
|
||||
|
||||
|
@ -643,25 +679,6 @@
|
|||
android:nextFocusUp="@id/player_pause_play"
|
||||
android:text="@string/tracks"
|
||||
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>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -678,4 +678,7 @@
|
|||
<string name="qualities">Qualities</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="tv_no_focus_tag" translatable="false">tv_no_focus_tag</string>
|
||||
</resources>
|
||||
|
|
|
@ -495,9 +495,10 @@
|
|||
<item name="android:paddingStart">20dp</item>
|
||||
<item name="android:paddingEnd">20dp</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:foreground">?attr/selectableItemBackgroundBorderless</item>
|
||||
<item name="android:textAppearance">?android:attr/textAppearanceListItemSmall</item>
|
||||
<item name="drawableEndCompat">@drawable/ic_baseline_keyboard_arrow_right_24</item>
|
||||
</style>
|
||||
|
@ -547,6 +548,7 @@
|
|||
<item name="android:insetTop">0dp</item>
|
||||
<item name="android:insetBottom">0dp</item>
|
||||
<item name="android:foreground">@drawable/outline_drawable_less</item>
|
||||
<item name="android:tag">@string/tv_no_focus_tag</item>
|
||||
</style>
|
||||
|
||||
<style name="WhiteButton" parent="NiceButton">
|
||||
|
@ -760,6 +762,7 @@
|
|||
</style>
|
||||
|
||||
<style name="VideoButtonTV">
|
||||
<item name="android:tag">@string/tv_no_focus_tag</item>
|
||||
<item name="android:stateListAnimator">@null</item>
|
||||
<item name="strokeColor">@color/transparent</item>
|
||||
<item name="backgroundTint">@null</item>
|
||||
|
|
Loading…
Reference in a new issue