Skip to content

Commit

Permalink
fix: improve landscape viewing and cover placeholder animations in pl…
Browse files Browse the repository at this point in the history
…ayer.
  • Loading branch information
oxyroid committed Oct 5, 2023
1 parent 7bd26fd commit 6716b58
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 56 deletions.
42 changes: 35 additions & 7 deletions androidApp/src/main/java/com/m3u/androidApp/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Rect
import android.os.Bundle
import android.util.Log
import android.util.Rational
import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle
Expand All @@ -24,9 +25,11 @@ import kotlin.reflect.KMutableProperty0

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val controller = WindowInsetsControllerCompat(window, window.decorView).apply {
systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
private val controller by lazy {
WindowInsetsControllerCompat(window, window.decorView).apply {
systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
}
private var actualOnUserLeaveHint: (() -> Unit)? = null
private var actualOnPipModeChanged: Consumer<PictureInPictureModeChangedInfo>? = null
Expand All @@ -35,6 +38,7 @@ class MainActivity : ComponentActivity() {
installSplashScreen()
enableEdgeToEdge()
super.onCreate(savedInstanceState)
applyConfiguration(resources.configuration)
setContent {
App(
connector = this::createHelper
Expand All @@ -47,7 +51,6 @@ class MainActivity : ComponentActivity() {
actions: Method<List<Action>>,
fob: Method<Fob?>
): Helper = object : Helper {

override fun enterPipMode(size: Rect) {
val params = PictureInPictureParams.Builder()
.setAspectRatio(Rational(size.width(), size.height()))
Expand All @@ -58,17 +61,19 @@ class MainActivity : ComponentActivity() {
override var title: String by title
override var actions: List<Action> by actions
override var fob: Fob? by fob
override var systemUiVisibility: Boolean = true
override var statusBarsVisibility: Boolean = true
set(value) {
field = value
controller.apply {
if (value) {
show(WindowInsetsCompat.Type.systemBars())
show(WindowInsetsCompat.Type.statusBars())
} else {
hide(WindowInsetsCompat.Type.systemBars())
hide(WindowInsetsCompat.Type.statusBars())
}
}
}
override var navigationBarsVisibility: Boolean =
resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT

override var darkMode: Boolean =
resources.configuration.uiMode == Configuration.UI_MODE_NIGHT_YES
Expand Down Expand Up @@ -96,6 +101,29 @@ class MainActivity : ComponentActivity() {
super.onUserLeaveHint()
actualOnUserLeaveHint?.invoke()
}

override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
applyConfiguration(newConfig)
}

private fun applyConfiguration(configuration: Configuration) {
Log.d(
"MainActivity",
"applyConfiguration: ${configuration.orientation == Configuration.ORIENTATION_PORTRAIT}"
)
when (configuration.orientation) {
Configuration.ORIENTATION_PORTRAIT -> {
controller.show(WindowInsetsCompat.Type.navigationBars())
}

Configuration.ORIENTATION_LANDSCAPE -> {
controller.hide(WindowInsetsCompat.Type.navigationBars())
}

else -> {}
}
}
}

internal typealias Method<E> = KMutableProperty0<E>
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ internal fun LiveRoute(
helper.enterPipMode(state.playerState.videoSize)
}
}
systemUiVisibility = false
statusBarsVisibility = false
onPipModeChanged = Consumer { info ->
isPipMode = info.isInPictureInPictureMode
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.m3u.features.live.components

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.unit.dp
import com.m3u.ui.components.Image
import com.m3u.ui.model.LocalDuration

@Composable
internal fun CoverPlaceholder(
visible: Boolean,
cover: String,
modifier: Modifier = Modifier
) {
val configuration = LocalConfiguration.current
val duration = LocalDuration.current
val size = remember(configuration.screenHeightDp) {
configuration.screenHeightDp.dp
}
AnimatedVisibility(
visible = visible,
enter = scaleIn(
initialScale = 0.65f,
animationSpec = tween(duration.slow)
) + fadeIn(
animationSpec = tween(duration.slow)
),
exit = scaleOut(
targetScale = 0.65f,
animationSpec = tween(duration.slow)
) + fadeOut(
animationSpec = tween(duration.slow)
),
modifier = modifier
) {
Image(
model = cover,
modifier = Modifier.size(size)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.media3.common.Player
import com.m3u.core.annotation.ClipMode
import com.m3u.core.util.basic.isNotEmpty
import com.m3u.features.live.R
import com.m3u.features.live.components.CoverPlaceholder
import com.m3u.features.live.components.LiveMask
import com.m3u.ui.components.Background
import com.m3u.ui.components.ExoPlayer
Expand Down Expand Up @@ -99,12 +100,12 @@ internal fun LiveFragment(
)

val shouldShowPlaceholder = cover.isNotEmpty() && videoSize.isEmpty
if (shouldShowPlaceholder) {
Image(
model = cover,
modifier = Modifier.fillMaxSize()
)
}

CoverPlaceholder(
visible = shouldShowPlaceholder,
cover = cover,
modifier = Modifier.align(Alignment.Center)
)

LiveMask(
state = maskState,
Expand Down
42 changes: 21 additions & 21 deletions ui/src/main/java/com/m3u/ui/components/AppBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,6 @@ import com.m3u.ui.model.LocalDuration
import com.m3u.ui.model.LocalSpacing
import com.m3u.ui.model.LocalTheme

@Suppress("unused")
interface AppTopBarConsumer {
fun Float.value(min: Float, max: Float): Boolean

object Never : AppTopBarConsumer {
override fun Float.value(min: Float, max: Float): Boolean = false
}

object Edges : AppTopBarConsumer {
override fun Float.value(min: Float, max: Float): Boolean = (this == min) || (this == max)
}

object Always : AppTopBarConsumer {
override fun Float.value(min: Float, max: Float): Boolean = (this != min) && (this != max)
}
}

fun AppTopBarConsumer.consume(value: Float, min: Float, max: Float): Boolean = value.value(min, max)

@Composable
fun AppTopBar(
modifier: Modifier = Modifier,
Expand Down Expand Up @@ -237,12 +218,31 @@ internal object AppTopBarDefaults {

@OptIn(ExperimentalLayoutApi::class)
val windowInsets: WindowInsets
@Composable get() = WindowInsets.systemBarsIgnoringVisibility.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top)
@Composable get() = WindowInsets.systemBarsIgnoringVisibility.only(WindowInsetsSides.Top)

/**
* Linear interpolator through point (1, 1).
* @param slope the slope of the interpolator.
* @param input the x value between 0~1f.
*/
fun interpolator(slope: Float, input: Float): Float = lerp(input, 1f, 1 - slope)
}
}

@Suppress("unused")
interface AppTopBarConsumer {
fun Float.value(min: Float, max: Float): Boolean

object Never : AppTopBarConsumer {
override fun Float.value(min: Float, max: Float): Boolean = false
}

object Edges : AppTopBarConsumer {
override fun Float.value(min: Float, max: Float): Boolean = (this == min) || (this == max)
}

object Always : AppTopBarConsumer {
override fun Float.value(min: Float, max: Float): Boolean = (this != min) && (this != max)
}
}

fun AppTopBarConsumer.consume(value: Float, min: Float, max: Float): Boolean = value.value(min, max)
50 changes: 29 additions & 21 deletions ui/src/main/java/com/m3u/ui/model/Helper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ interface Helper {
var title: String
var actions: List<Action>
var fob: Fob?
var systemUiVisibility: Boolean
var statusBarsVisibility: Boolean
var navigationBarsVisibility: Boolean
var onUserLeaveHint: (() -> Unit)?
var onPipModeChanged: Consumer<PictureInPictureModeChangedInfo>?
var darkMode: Boolean
Expand All @@ -38,16 +39,26 @@ private data class HelperBundle(
val darkMode: Boolean
)

private fun Helper.loadBundle(properties: HelperBundle) {
title = properties.title
actions = properties.actions
fob = properties.fob
systemUiVisibility = properties.systemUiVisibility
onUserLeaveHint = properties.onUserLeaveHint
onPipModeChanged = properties.onPipModeChanged
darkMode = properties.darkMode
private fun Helper.restore(bundle: HelperBundle) {
title = bundle.title
actions = bundle.actions
fob = bundle.fob
statusBarsVisibility = bundle.systemUiVisibility
onUserLeaveHint = bundle.onUserLeaveHint
onPipModeChanged = bundle.onPipModeChanged
darkMode = bundle.darkMode
}

private fun Helper.backup(): HelperBundle = HelperBundle(
title = title,
actions = actions,
fob = fob,
systemUiVisibility = statusBarsVisibility,
onUserLeaveHint = onUserLeaveHint,
onPipModeChanged = onPipModeChanged,
darkMode = darkMode
)

@Composable
@SuppressLint("ComposableNaming")
fun Helper.repeatOnLifecycle(
Expand All @@ -57,24 +68,16 @@ fun Helper.repeatOnLifecycle(
check(state != Lifecycle.State.CREATED && state != Lifecycle.State.INITIALIZED) {
"state cannot be CREATED or INITIALIZED!"
}
var properties: HelperBundle? = null
var bundle: HelperBundle? = null
LifecycleEffect { event ->
when (event) {
Lifecycle.Event.upTo(state) -> {
properties = HelperBundle(
title = title,
actions = actions,
fob = fob,
systemUiVisibility = systemUiVisibility,
onUserLeaveHint = onUserLeaveHint,
onPipModeChanged = onPipModeChanged,
darkMode = darkMode
)
bundle = backup()
block()
}

Lifecycle.Event.downFrom(state) -> {
properties?.let(::loadBundle)
bundle?.let(::restore)
}

else -> {}
Expand All @@ -100,11 +103,16 @@ val EmptyHelper = object : Helper {
error("Cannot set fob")
}

override var systemUiVisibility: Boolean
override var statusBarsVisibility: Boolean
get() = error("Cannot get systemUiVisibility")
set(_) {
error("Cannot set systemUiVisibility")
}
override var navigationBarsVisibility: Boolean
get() = error("Cannot get navigationBarsVisibility")
set(_) {
error("Cannot set navigationBarsVisibility")
}

override var darkMode: Boolean
get() = error("Cannot get darkMode")
Expand Down

0 comments on commit 6716b58

Please sign in to comment.