Improve position of video controlling buttons when top bars are present.
This commit is contained in:
@@ -29,6 +29,7 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -44,12 +45,11 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.layout.LayoutCoordinates
|
import androidx.compose.ui.layout.LayoutCoordinates
|
||||||
import androidx.compose.ui.layout.boundsInWindow
|
import androidx.compose.ui.layout.boundsInWindow
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
import androidx.compose.ui.layout.onSizeChanged
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.IntSize
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.isFinite
|
import androidx.compose.ui.unit.isFinite
|
||||||
import androidx.compose.ui.unit.isSpecified
|
import androidx.compose.ui.unit.isSpecified
|
||||||
@@ -71,6 +71,7 @@ import com.vitorpamplona.amethyst.ui.note.MuteIcon
|
|||||||
import com.vitorpamplona.amethyst.ui.note.MutedIcon
|
import com.vitorpamplona.amethyst.ui.note.MutedIcon
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize
|
import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size0dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size22Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size22Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size50Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size50Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.VolumeBottomIconSize
|
import com.vitorpamplona.amethyst.ui.theme.VolumeBottomIconSize
|
||||||
@@ -536,137 +537,132 @@ private fun RenderVideoPlayer(
|
|||||||
mutableStateOf(false)
|
mutableStateOf(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val parentVideoPlaybackSize = remember {
|
val videoPlaybackHeight = remember {
|
||||||
mutableStateOf<IntSize>(IntSize.Zero)
|
mutableStateOf<Dp>(Dp.Unspecified)
|
||||||
}
|
}
|
||||||
|
|
||||||
val videoPlaybackSize = remember {
|
val localDensity = LocalDensity.current
|
||||||
mutableStateOf<IntSize>(IntSize.Zero)
|
|
||||||
}
|
|
||||||
|
|
||||||
BoxWithConstraints(
|
BoxWithConstraints(
|
||||||
contentAlignment = Alignment.Center,
|
modifier = Modifier
|
||||||
modifier = Modifier.fillMaxSize().onSizeChanged {
|
.onGloballyPositioned { coordinates ->
|
||||||
parentVideoPlaybackSize.value = it
|
videoPlaybackHeight.value = with(localDensity) { coordinates.size.height.toDp() }
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
BoxWithConstraints(
|
val borders = MaterialTheme.colorScheme.imageModifier
|
||||||
modifier = Modifier.onSizeChanged {
|
|
||||||
videoPlaybackSize.value = it
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
val borders = MaterialTheme.colorScheme.imageModifier
|
|
||||||
|
|
||||||
val myModifier = remember {
|
val myModifier = remember {
|
||||||
if (roundedCorner) {
|
if (roundedCorner) {
|
||||||
modifier.then(
|
modifier.then(
|
||||||
borders
|
borders
|
||||||
.defaultMinSize(minHeight = 100.dp)
|
.defaultMinSize(minHeight = 75.dp)
|
||||||
.align(Alignment.Center)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.defaultMinSize(minHeight = 100.dp)
|
|
||||||
.align(Alignment.Center)
|
.align(Alignment.Center)
|
||||||
}
|
)
|
||||||
|
} else {
|
||||||
|
modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.defaultMinSize(minHeight = 75.dp)
|
||||||
|
.align(Alignment.Center)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val factory = remember(controller) {
|
val factory = remember(controller) {
|
||||||
{ context: Context ->
|
{ context: Context ->
|
||||||
PlayerView(context).apply {
|
PlayerView(context).apply {
|
||||||
player = controller
|
player = controller
|
||||||
layoutParams = FrameLayout.LayoutParams(
|
layoutParams = FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
)
|
)
|
||||||
controllerAutoShow = false
|
controllerAutoShow = false
|
||||||
thumbData?.thumb?.let { defaultArtwork = it }
|
thumbData?.thumb?.let { defaultArtwork = it }
|
||||||
hideController()
|
hideController()
|
||||||
resizeMode =
|
resizeMode =
|
||||||
if (maxHeight.isFinite) AspectRatioFrameLayout.RESIZE_MODE_FIT else AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH
|
if (maxHeight.isFinite) AspectRatioFrameLayout.RESIZE_MODE_FIT else AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH
|
||||||
onDialog?.let { innerOnDialog ->
|
onDialog?.let { innerOnDialog ->
|
||||||
setFullscreenButtonClickListener {
|
setFullscreenButtonClickListener {
|
||||||
controller.pause()
|
controller.pause()
|
||||||
innerOnDialog(it)
|
innerOnDialog(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setControllerVisibilityListener(
|
||||||
|
PlayerView.ControllerVisibilityListener { visible ->
|
||||||
|
controllerVisible.value = visible == View.VISIBLE
|
||||||
|
onControllerVisibilityChanged?.let { callback ->
|
||||||
|
callback(visible == View.VISIBLE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setControllerVisibilityListener(
|
)
|
||||||
PlayerView.ControllerVisibilityListener { visible ->
|
|
||||||
controllerVisible.value = visible == View.VISIBLE
|
|
||||||
onControllerVisibilityChanged?.let { callback ->
|
|
||||||
callback(visible == View.VISIBLE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AndroidView(
|
AndroidView(
|
||||||
modifier = myModifier,
|
modifier = myModifier,
|
||||||
factory = factory
|
factory = factory
|
||||||
)
|
)
|
||||||
|
|
||||||
waveform?.let {
|
waveform?.let {
|
||||||
Waveform(it, controller, remember { Modifier.align(Alignment.Center) })
|
Waveform(it, controller, remember { Modifier.align(Alignment.Center) })
|
||||||
}
|
}
|
||||||
|
|
||||||
val startingMuteState = remember(controller) {
|
val startingMuteState = remember(controller) {
|
||||||
controller.volume < 0.001
|
controller.volume < 0.001
|
||||||
}
|
}
|
||||||
|
|
||||||
val spaceModifier = remember {
|
val topPadding = remember {
|
||||||
if (topPaddingForControllers.isSpecified && videoPlaybackSize.value.height > 0) {
|
derivedStateOf {
|
||||||
val space = (abs(parentVideoPlaybackSize.value.height - videoPlaybackSize.value.height) / 2).dp
|
if (topPaddingForControllers.isSpecified && videoPlaybackHeight.value.value > 0) {
|
||||||
|
val space = (abs(this.maxHeight.value - videoPlaybackHeight.value.value) / 2).dp
|
||||||
if (space > topPaddingForControllers) {
|
if (space > topPaddingForControllers) {
|
||||||
Modifier
|
Size0dp
|
||||||
} else {
|
} else {
|
||||||
Modifier.padding(top = topPaddingForControllers - space)
|
topPaddingForControllers - space
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Size0dp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MuteButton(
|
MuteButton(
|
||||||
controllerVisible,
|
controllerVisible,
|
||||||
startingMuteState,
|
startingMuteState,
|
||||||
spaceModifier
|
topPadding
|
||||||
) { mute: Boolean ->
|
) { mute: Boolean ->
|
||||||
// makes the new setting the default for new creations.
|
// makes the new setting the default for new creations.
|
||||||
DefaultMutedSetting.value = mute
|
DefaultMutedSetting.value = mute
|
||||||
|
|
||||||
// if the user unmutes a video and it's not the current playing, switches to that one.
|
// if the user unmutes a video and it's not the current playing, switches to that one.
|
||||||
if (!mute && keepPlayingMutex != null && keepPlayingMutex != controller) {
|
if (!mute && keepPlayingMutex != null && keepPlayingMutex != controller) {
|
||||||
|
keepPlayingMutex?.stop()
|
||||||
|
keepPlayingMutex?.release()
|
||||||
|
keepPlayingMutex = null
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.volume = if (mute) 0f else 1f
|
||||||
|
}
|
||||||
|
|
||||||
|
KeepPlayingButton(
|
||||||
|
keepPlaying,
|
||||||
|
controllerVisible,
|
||||||
|
topPadding,
|
||||||
|
Modifier.align(Alignment.TopEnd)
|
||||||
|
) { newKeepPlaying: Boolean ->
|
||||||
|
// If something else is playing and the user marks this video to keep playing, stops the other one.
|
||||||
|
if (newKeepPlaying) {
|
||||||
|
if (keepPlayingMutex != null && keepPlayingMutex != controller) {
|
||||||
keepPlayingMutex?.stop()
|
keepPlayingMutex?.stop()
|
||||||
keepPlayingMutex?.release()
|
keepPlayingMutex?.release()
|
||||||
|
}
|
||||||
|
keepPlayingMutex = controller
|
||||||
|
} else {
|
||||||
|
if (keepPlayingMutex == controller) {
|
||||||
keepPlayingMutex = null
|
keepPlayingMutex = null
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.volume = if (mute) 0f else 1f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeepPlayingButton(
|
keepPlaying.value = newKeepPlaying
|
||||||
keepPlaying,
|
|
||||||
controllerVisible,
|
|
||||||
spaceModifier.align(Alignment.TopEnd)
|
|
||||||
) { newKeepPlaying: Boolean ->
|
|
||||||
// If something else is playing and the user marks this video to keep playing, stops the other one.
|
|
||||||
if (newKeepPlaying) {
|
|
||||||
if (keepPlayingMutex != null && keepPlayingMutex != controller) {
|
|
||||||
keepPlayingMutex?.stop()
|
|
||||||
keepPlayingMutex?.release()
|
|
||||||
}
|
|
||||||
keepPlayingMutex = controller
|
|
||||||
} else {
|
|
||||||
if (keepPlayingMutex == controller) {
|
|
||||||
keepPlayingMutex = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keepPlaying.value = newKeepPlaying
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -826,7 +822,7 @@ fun LayoutCoordinates.getDistanceToVertCenterIfVisible(view: View): Float? {
|
|||||||
private fun MuteButton(
|
private fun MuteButton(
|
||||||
controllerVisible: MutableState<Boolean>,
|
controllerVisible: MutableState<Boolean>,
|
||||||
startingMuteState: Boolean,
|
startingMuteState: Boolean,
|
||||||
modifier: Modifier,
|
topPadding: State<Dp>,
|
||||||
toggle: (Boolean) -> Unit
|
toggle: (Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
val holdOn = remember {
|
val holdOn = remember {
|
||||||
@@ -846,7 +842,7 @@ private fun MuteButton(
|
|||||||
|
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = holdOn.value || controllerVisible.value,
|
visible = holdOn.value || controllerVisible.value,
|
||||||
modifier = modifier,
|
modifier = Modifier.padding(top = topPadding.value),
|
||||||
enter = remember { fadeIn() },
|
enter = remember { fadeIn() },
|
||||||
exit = remember { fadeOut() }
|
exit = remember { fadeOut() }
|
||||||
) {
|
) {
|
||||||
@@ -880,6 +876,7 @@ private fun MuteButton(
|
|||||||
private fun KeepPlayingButton(
|
private fun KeepPlayingButton(
|
||||||
keepPlayingStart: MutableState<Boolean>,
|
keepPlayingStart: MutableState<Boolean>,
|
||||||
controllerVisible: MutableState<Boolean>,
|
controllerVisible: MutableState<Boolean>,
|
||||||
|
topPadding: State<Dp>,
|
||||||
alignment: Modifier,
|
alignment: Modifier,
|
||||||
toggle: (Boolean) -> Unit
|
toggle: (Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
@@ -887,7 +884,7 @@ private fun KeepPlayingButton(
|
|||||||
|
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = controllerVisible.value,
|
visible = controllerVisible.value,
|
||||||
modifier = alignment,
|
modifier = alignment.padding(top = topPadding.value),
|
||||||
enter = remember { fadeIn() },
|
enter = remember { fadeIn() },
|
||||||
exit = remember { fadeOut() }
|
exit = remember { fadeOut() }
|
||||||
) {
|
) {
|
||||||
|
|||||||
Reference in New Issue
Block a user