Skip to content

Commit

Permalink
auto play next episode
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Dec 31, 2022
1 parent 5c971fc commit 7731620
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ fun Window?.enterFullScreen() {
this?.attributes?.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
this?.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
this?.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
this?.let { WindowCompat.setDecorFitsSystemWindows(it, false) }
}

Expand All @@ -19,5 +18,5 @@ fun Window?.exitFullScreen() {
this?.attributes?.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
}
this?.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
this?.let { WindowCompat.setDecorFitsSystemWindows(it, false) }
this?.let { WindowCompat.setDecorFitsSystemWindows(it, true) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package dev.datlag.burningseries.ui.custom

import android.view.WindowManager
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowInsetsControllerCompat
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import dev.datlag.burningseries.common.enterFullScreen
import dev.datlag.burningseries.common.exitFullScreen
import dev.datlag.burningseries.common.findWindow

@Composable
fun RequireFullScreen() {
val window = LocalView.current.context.findWindow()
val systemUiController = rememberSystemUiController()

DisposableEffect(Unit) {
val originalBehavior = systemUiController.systemBarsBehavior

systemUiController.isSystemBarsVisible = false
systemUiController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
window.enterFullScreen()
window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
onDispose {
systemUiController.isSystemBarsVisible = true
systemUiController.systemBarsBehavior = originalBehavior
window.exitFullScreen()
window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package dev.datlag.burningseries.ui.screen.video

import android.annotation.SuppressLint
import android.content.pm.ActivityInfo
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.TextView
Expand All @@ -14,7 +16,10 @@ import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.viewinterop.AndroidView
Expand All @@ -35,9 +40,11 @@ import dev.datlag.burningseries.LocalStringRes
import dev.datlag.burningseries.R
import dev.datlag.burningseries.common.*
import dev.datlag.burningseries.other.Logger
import dev.datlag.burningseries.ui.custom.RequireFullScreen
import dev.datlag.burningseries.ui.custom.RequireScreenOrientation
import kotlinx.coroutines.*

@SuppressLint("StateFlowValueCalledInComposition")
@Composable
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
fun VideoPlayer(component: VideoComponent) {
Expand All @@ -53,27 +60,21 @@ fun VideoPlayer(component: VideoComponent) {
.setAllowCrossProtocolRedirects(true)
.setKeepPostFor302Redirects(true))
}
val episode by component.episode.collectAsState(component.episode.value)
val videoStreams by component.videoStreams.collectAsState(component.videoStreams.value)
var streamListPos by remember { mutableStateOf(0) }
var srcListPos by remember { mutableStateOf(0) }
val stream = component.videoStreams[streamListPos].srcList[srcListPos]
val systemUiController = rememberSystemUiController()
val window = LocalView.current.context.findWindow()
val stream = videoStreams[streamListPos].srcList[srcListPos]

val strings = LocalStringRes.current
var appliedInitialPosition by remember { mutableStateOf(false) }
val buttonShape = MaterialTheme.shapes.medium.toLegacyShape()
val buttonColors = ButtonDefaults.legacyButtonTintList(MaterialTheme.colorScheme.primaryContainer)
val progressColor = MaterialTheme.colorScheme.primary.toArgb()
val initialPos by component.initialPosition.collectAsState(component.initialPosition.getValueBlocking(0))

RequireScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
DisposableEffect(Unit) {
systemUiController.isSystemBarsVisible = false
systemUiController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
window.enterFullScreen()
onDispose {
window.exitFullScreen()
systemUiController.isSystemBarsVisible = true
}
}
RequireFullScreen()

val exoPlayer = remember {
ExoPlayer.Builder(context)
Expand All @@ -89,10 +90,10 @@ fun VideoPlayer(component: VideoComponent) {
override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error)

if (component.videoStreams[streamListPos].srcList.size - 1 > srcListPos) {
if (videoStreams[streamListPos].srcList.size - 1 > srcListPos) {
srcListPos++
} else {
if (component.videoStreams.size - 1 > streamListPos) {
if (videoStreams.size - 1 > streamListPos) {
streamListPos++
srcListPos = 0
}
Expand Down Expand Up @@ -121,7 +122,7 @@ fun VideoPlayer(component: VideoComponent) {
super.onRenderedFirstFrame()

if (!appliedInitialPosition) {
component.seekTo(component.initialPosition)
component.seekTo(initialPos)
appliedInitialPosition = true
}
component.length.value = (this@apply as ExoPlayer).duration
Expand All @@ -134,13 +135,24 @@ fun VideoPlayer(component: VideoComponent) {
}
}
}

override fun onPlaybackStateChanged(playbackState: Int) {
super.onPlaybackStateChanged(playbackState)

if (playbackState == Player.STATE_ENDED) {
component.playNextEpisode()
}
}
})
playWhenReady = true
prepare()
}
}

SideEffect {
component.playListener = {
exoPlayer.play()
}
component.playPauseListener = {
if (exoPlayer.isPlaying) {
exoPlayer.pause()
Expand All @@ -160,6 +172,7 @@ fun VideoPlayer(component: VideoComponent) {
exoPlayer.setMediaItem(MediaItem.fromUri(stream))
exoPlayer.prepare()
}
var keyEventListener: ((KeyEvent) -> Boolean)? = null

DisposableEffect(
AndroidView(factory = {
Expand All @@ -183,11 +196,17 @@ fun VideoPlayer(component: VideoComponent) {
backButton.setOnClickListener {
component.onGoBack()
}
title.text = component.episode.title
title.text = episode.title
skipButton.shapeAppearanceModel = buttonShape
skipButton.backgroundTintList = buttonColors
progress.setPlayedColor(progressColor)
progress.setScrubberColor(progressColor)

keyEventListener = { event ->
it.dispatchKeyEvent(event.nativeKeyEvent)
}
}, modifier = Modifier.onKeyEvent {
keyEventListener?.invoke(it) ?: false
})
) {
onDispose {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,10 @@ class SeriesScreenComponent(
showDialog(DialogConfig.NoStream(episode))
}
} else {
val sortedList = episodeData.sortedBy { stream ->
hosterList.find { it.name.equals(stream.hoster.hoster, true) }?.position ?: Int.MAX_VALUE
}
withContext(CommonDispatcher.Main) {
val sortedList = episodeData.sortedBy { stream ->
hosterList.find { it.name.equals(stream.hoster.hoster, true) }?.position ?: Int.MAX_VALUE
}
onEpisodeClicked(seriesRepo.series.value!!, episode, sortedList)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import kotlinx.coroutines.flow.MutableStateFlow
interface VideoComponent : Component {

val series: Series
val episode: Series.Episode
val videoStreams: List<VideoStream>
val episode: MutableStateFlow<Series.Episode>
val videoStreams: MutableStateFlow<List<VideoStream>>
val onGoBack: () -> Unit

var playListener: (() -> Unit)?
var playPauseListener: (() -> Unit)?
var forwardListener: (() -> Unit)?
var rewindListener: (() -> Unit)?
Expand All @@ -24,11 +25,13 @@ interface VideoComponent : Component {
val position: MutableValue<Long>
val length: MutableValue<Long>

val initialPosition: Long
val initialPosition: Flow<Long>

fun triggerPlayPause()
fun forward()
fun rewind()

fun seekTo(time: Long)

fun playNextEpisode()
}
Loading

0 comments on commit 7731620

Please sign in to comment.