Skip to content

Commit

Permalink
Merge pull request #15 from THEOplayer/autoplay-hide-controls
Browse files Browse the repository at this point in the history
Hide controls when autoplaying
  • Loading branch information
MattiasBuelens authored Jun 30, 2023
2 parents f7fe542 + 0e9b22d commit 85ba553
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 21 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
## Unreleased

* 🚀 Added `Player.videoWidth` and `Player.videoHeight`
* 🐛 Fixed player not following device rotation while fullscreen.
* 🚀 Added `Player.source`, `.videoWidth` and `.videoHeight` properties.
* 🚀 Added `Player.play()` and `.pause()` shortcut methods.
* 🐛 Fixed player not following device rotation while fullscreen.
* 💅 When autoplaying a new video, the UI now starts out as hidden.

## v1.3.0 (2023-06-29)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Brush
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
Expand Down Expand Up @@ -44,7 +45,7 @@ fun MainContent() {

val player = rememberPlayer()
LaunchedEffect(player, source) {
player.player?.source = source
player.source = source
}

var themeMenuOpen by remember { mutableStateOf(false) }
Expand All @@ -60,6 +61,12 @@ fun MainContent() {
Text(text = "Demo")
},
actions = {
IconButton(onClick = {
player.source = source
player.play()
}) {
Icon(Icons.Rounded.Refresh, contentDescription = "Reload")
}
IconButton(onClick = { themeMenuOpen = true }) {
Icon(Icons.Rounded.Brush, contentDescription = "Theme")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fun NitflexUI(
) {
val player = rememberPlayer(config)
LaunchedEffect(player, source) {
player.player?.source = source
player.source = source
}

NitflexUI(modifier = modifier, player = player, title = title)
Expand Down
2 changes: 1 addition & 1 deletion ui/src/main/java/com/theoplayer/android/ui/DefaultUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fun DefaultUI(
) {
val player = rememberPlayer(config)
LaunchedEffect(player, source) {
player.player?.source = source
player.source = source
}

DefaultUI(modifier = modifier, player = player, title = title)
Expand Down
4 changes: 2 additions & 2 deletions ui/src/main/java/com/theoplayer/android/ui/PlayButton.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ fun PlayButton(
onClick = {
player?.let {
if (it.paused) {
it.player?.play()
it.play()
} else {
it.player?.pause()
it.pause()
}
}
}) {
Expand Down
36 changes: 36 additions & 0 deletions ui/src/main/java/com/theoplayer/android/ui/Player.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import com.theoplayer.android.api.player.track.mediatrack.quality.VideoQuality
import com.theoplayer.android.api.player.track.texttrack.TextTrack
import com.theoplayer.android.api.player.track.texttrack.TextTrackKind
import com.theoplayer.android.api.player.track.texttrack.TextTrackMode
import com.theoplayer.android.api.source.SourceDescription
import com.theoplayer.android.api.event.track.mediatrack.audio.list.AddTrackEvent as AudioAddTrackEvent
import com.theoplayer.android.api.event.track.mediatrack.audio.list.RemoveTrackEvent as AudioRemoveTrackEvent
import com.theoplayer.android.api.event.track.mediatrack.audio.list.TrackListChangeEvent as AudioTrackListChangeEvent
Expand Down Expand Up @@ -81,6 +82,11 @@ interface Player {
*/
val theoplayerView: THEOplayerView?

/**
* Returns or sets the player's source.
*/
var source: SourceDescription?

/**
* Returns the raw [Cast] API of the backing THEOplayer instance.
*/
Expand Down Expand Up @@ -231,6 +237,16 @@ interface Player {
*/
val castReceiverName: String?

/**
* Starts or resumes playback.
*/
fun play()

/**
* Pauses playback.
*/
fun pause()

/**
* Contains properties to access the current [Player].
*/
Expand Down Expand Up @@ -327,6 +343,7 @@ internal class PlayerImpl(override val theoplayerView: THEOplayerView?) : Player
EventListener<ReadyStateChangeEvent> { updateCurrentTimeAndPlaybackState() }
private val resizeListener = EventListener<ResizeEvent> { updateVideoWidthAndHeight() }
private val sourceChangeListener = EventListener<SourceChangeEvent> {
_source = player?.source
error = null
firstPlay = false
updateCurrentTimeAndPlaybackState()
Expand All @@ -335,13 +352,32 @@ internal class PlayerImpl(override val theoplayerView: THEOplayerView?) : Player
updateActiveVideoTrack()
}
private val errorListener = EventListener<ErrorEvent> { event ->
_source = player?.source
error = event.errorObject
updateCurrentTimeAndPlaybackState()
updateDuration()
updateVideoWidthAndHeight()
updateActiveVideoTrack()
}

override fun play() {
paused = false
player?.play()
}

override fun pause() {
paused = true
player?.pause()
}

private var _source by mutableStateOf(player?.source)
override var source: SourceDescription?
get() = _source
set(value) {
_source = value
player?.source = value
}

private var _volume by mutableStateOf(1.0)
private var _muted by mutableStateOf(false)
override var volume: Double
Expand Down
46 changes: 32 additions & 14 deletions ui/src/main/java/com/theoplayer/android/ui/UIController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.theoplayer.android.api.cast.chromecast.PlayerCastState
import com.theoplayer.android.api.source.SourceDescription
import com.theoplayer.android.ui.theme.THEOplayerTheme
import kotlinx.coroutines.*
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit

Expand Down Expand Up @@ -64,7 +65,7 @@ fun UIController(
) {
val player = rememberPlayer(config)
LaunchedEffect(player, source) {
player.player?.source = source
player.source = source
}

UIController(
Expand Down Expand Up @@ -115,17 +116,30 @@ fun UIController(
bottomChrome: (@Composable UIControllerScope.() -> Unit)? = null
) {
var tapCount by remember { mutableStateOf(0) }
var isRecentlyTapped by remember { mutableStateOf(true) }
var isRecentlyTapped by remember { mutableStateOf(false) }
LaunchedEffect(tapCount) {
isRecentlyTapped = true
delay(2.seconds)
isRecentlyTapped = false
if (tapCount > 0) {
isRecentlyTapped = true
delay(2.seconds)
isRecentlyTapped = false
}
}
val isPressed by interactionSource.collectIsPressedAsState()
var forceControlsHidden by remember { mutableStateOf(false) }

// Wait a little bit before showing the controls and enabling animations,
// so we can hide the UI immediately in case of autoplay.
var isReady by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
delay(50.milliseconds)
isReady = true
}

val controlsVisible = remember {
derivedStateOf {
if (!player.firstPlay) {
if (!isReady) {
false
} else if (!player.firstPlay) {
true
} else if (forceControlsHidden) {
false
Expand Down Expand Up @@ -224,6 +238,7 @@ fun UIController(
is UIState.Controls -> {
scope.PlayerControls(
controlsVisible = controlsVisible.value,
animationsActive = isReady,
centerOverlay = centerOverlay,
topChrome = topChrome,
centerChrome = centerChrome,
Expand Down Expand Up @@ -323,12 +338,14 @@ private fun PlayerContainer(
DisposableEffect(uiContainer, composeView) {
val container = uiContainer
val view = composeView
if (view != null) {
container?.addView(view)
if (container != null && view != null) {
container.addView(view)
theoplayerView.postInvalidate()
}
onDispose {
if (view != null) {
container?.removeView(view)
if (container != null && view != null) {
container.removeView(view)
theoplayerView.postInvalidate()
}
}
}
Expand All @@ -338,6 +355,7 @@ private fun PlayerContainer(
@Composable
private fun UIControllerScope.PlayerControls(
controlsVisible: Boolean,
animationsActive: Boolean,
centerOverlay: (@Composable UIControllerScope.() -> Unit)? = null,
topChrome: (@Composable UIControllerScope.() -> Unit)? = null,
centerChrome: (@Composable UIControllerScope.() -> Unit)? = null,
Expand All @@ -354,22 +372,22 @@ private fun UIControllerScope.PlayerControls(
}
AnimatedVisibility(
visible = controlsVisible,
enter = fadeIn(
enter = if (animationsActive) fadeIn(
animationSpec = tween(
easing = LinearEasing,
durationMillis = THEOplayerTheme.playerAnimations.controlsEnterDuration.toInt(
DurationUnit.MILLISECONDS
)
)
),
exit = fadeOut(
) else EnterTransition.None,
exit = if (animationsActive) fadeOut(
animationSpec = tween(
easing = LinearEasing,
durationMillis = THEOplayerTheme.playerAnimations.controlsExitDuration.toInt(
DurationUnit.MILLISECONDS
)
)
)
) else ExitTransition.None,
) {
centerChrome?.let {
Row(
Expand Down

0 comments on commit 85ba553

Please sign in to comment.