make only one of the volume indicators vissible
This commit is contained in:
parent
1fde8569ce
commit
601dbf2e7f
|
@ -29,8 +29,8 @@ private const val TAG = "TouchUi"
|
||||||
|
|
||||||
|
|
||||||
const val DELAY_UNTIL_SHOWING_UI_AFTER_TOUCH_IN_MS: Long = 200
|
const val DELAY_UNTIL_SHOWING_UI_AFTER_TOUCH_IN_MS: Long = 200
|
||||||
const val SEEK_ANIMATION_DURATION_IN_MS = 400
|
const val SEEK_ANIMATION_DURATION_IN_MS = 300
|
||||||
const val FAST_SEEKMODE_DURATION = 500L
|
const val FAST_SEEK_MODE_DURATION = 500L
|
||||||
const val SEEK_ANIMATION_FADE_IN = 200
|
const val SEEK_ANIMATION_FADE_IN = 200
|
||||||
const val SEEK_ANIMATION_FADE_OUT = 500
|
const val SEEK_ANIMATION_FADE_OUT = 500
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||||
import net.newpipe.newplayer.ui.videoplayer.FAST_SEEKMODE_DURATION
|
import net.newpipe.newplayer.ui.videoplayer.FAST_SEEK_MODE_DURATION
|
||||||
|
|
||||||
private const val TAG = "EmbeddedGestureUI"
|
private const val TAG = "EmbeddedGestureUI"
|
||||||
|
|
||||||
|
@ -68,10 +68,10 @@ fun EmbeddedGestureUI(
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(modifier = modifier) {
|
Row(modifier = modifier) {
|
||||||
TouchSurface(
|
GestureSurface(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f),
|
.weight(1f),
|
||||||
multitapDurationInMs = FAST_SEEKMODE_DURATION,
|
multiTapTimeoutInMs = FAST_SEEK_MODE_DURATION,
|
||||||
onRegularTap = defaultOnRegularTap,
|
onRegularTap = defaultOnRegularTap,
|
||||||
onMultiTap = {
|
onMultiTap = {
|
||||||
fastSeek(-it)
|
fastSeek(-it)
|
||||||
|
@ -92,10 +92,10 @@ fun EmbeddedGestureUI(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TouchSurface(
|
GestureSurface(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f),
|
.weight(1f),
|
||||||
multitapDurationInMs = FAST_SEEKMODE_DURATION,
|
multiTapTimeoutInMs = FAST_SEEK_MODE_DURATION,
|
||||||
onRegularTap = defaultOnRegularTap,
|
onRegularTap = defaultOnRegularTap,
|
||||||
onMovement = handleDownwardMovement,
|
onMovement = handleDownwardMovement,
|
||||||
onMultiTap = fastSeek,
|
onMultiTap = fastSeek,
|
||||||
|
|
|
@ -41,7 +41,13 @@ import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||||
import net.newpipe.newplayer.ui.videoplayer.FAST_SEEKMODE_DURATION
|
import net.newpipe.newplayer.ui.videoplayer.FAST_SEEK_MODE_DURATION
|
||||||
|
|
||||||
|
private enum class IndicatorMode {
|
||||||
|
NONE,
|
||||||
|
VOLUME_INDICATOR_VISSIBLE,
|
||||||
|
BRIGHTNESS_INDICATOR_VISSIBLE
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FullscreenGestureUI(
|
fun FullscreenGestureUI(
|
||||||
|
@ -58,7 +64,17 @@ fun FullscreenGestureUI(
|
||||||
volumeChange: (Float) -> Unit,
|
volumeChange: (Float) -> Unit,
|
||||||
brightnesChange: (Float) -> Unit
|
brightnesChange: (Float) -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
var heightPx by remember {
|
||||||
|
mutableStateOf(0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
var indicatorMode by remember {
|
||||||
|
mutableStateOf(IndicatorMode.NONE)
|
||||||
|
}
|
||||||
|
|
||||||
val defaultOnRegularTap = {
|
val defaultOnRegularTap = {
|
||||||
|
|
||||||
if (uiVissible) {
|
if (uiVissible) {
|
||||||
hideUi()
|
hideUi()
|
||||||
} else {
|
} else {
|
||||||
|
@ -66,26 +82,14 @@ fun FullscreenGestureUI(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var heightPx by remember {
|
|
||||||
mutableStateOf(0f)
|
|
||||||
}
|
|
||||||
|
|
||||||
var volumeIndicatorVissible by remember {
|
|
||||||
mutableStateOf(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
var brightnesIndicatorVissible by remember {
|
|
||||||
mutableStateOf(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(modifier = modifier.onGloballyPositioned { coordinates ->
|
Box(modifier = modifier.onGloballyPositioned { coordinates ->
|
||||||
heightPx = coordinates.size.height.toFloat()
|
heightPx = coordinates.size.height.toFloat()
|
||||||
}) {
|
}) {
|
||||||
Row {
|
Row {
|
||||||
TouchSurface(
|
GestureSurface(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f),
|
.weight(1f),
|
||||||
multitapDurationInMs = FAST_SEEKMODE_DURATION,
|
multiTapTimeoutInMs = FAST_SEEK_MODE_DURATION,
|
||||||
onRegularTap = defaultOnRegularTap,
|
onRegularTap = defaultOnRegularTap,
|
||||||
onMultiTap = {
|
onMultiTap = {
|
||||||
println("multitap ${-it}")
|
println("multitap ${-it}")
|
||||||
|
@ -93,14 +97,19 @@ fun FullscreenGestureUI(
|
||||||
},
|
},
|
||||||
onMultiTapFinished = fastSeekFinished,
|
onMultiTapFinished = fastSeekFinished,
|
||||||
onUp = {
|
onUp = {
|
||||||
brightnesIndicatorVissible = false
|
indicatorMode = IndicatorMode.NONE
|
||||||
},
|
},
|
||||||
onMovement = {change ->
|
onMovement = { change ->
|
||||||
brightnesIndicatorVissible = true
|
if (indicatorMode == IndicatorMode.NONE
|
||||||
|
|| indicatorMode == IndicatorMode.BRIGHTNESS_INDICATOR_VISSIBLE
|
||||||
|
) {
|
||||||
|
indicatorMode = IndicatorMode.BRIGHTNESS_INDICATOR_VISSIBLE
|
||||||
|
|
||||||
if (heightPx != 0f) {
|
if (heightPx != 0f) {
|
||||||
brightnesChange(-change.y / heightPx)
|
brightnesChange(-change.y / heightPx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
FadedAnimationForSeekFeedback(
|
FadedAnimationForSeekFeedback(
|
||||||
fastSeekSeconds,
|
fastSeekSeconds,
|
||||||
|
@ -115,33 +124,37 @@ fun FullscreenGestureUI(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TouchSurface(
|
GestureSurface(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f),
|
.weight(1f),
|
||||||
onRegularTap = defaultOnRegularTap,
|
onRegularTap = defaultOnRegularTap,
|
||||||
multitapDurationInMs = FAST_SEEKMODE_DURATION,
|
multiTapTimeoutInMs = FAST_SEEK_MODE_DURATION,
|
||||||
onMovement = { movement ->
|
onMovement = { movement ->
|
||||||
if (0 < movement.y) {
|
if (0 < movement.y) {
|
||||||
switchToEmbeddedView()
|
switchToEmbeddedView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
TouchSurface(
|
GestureSurface(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f),
|
.weight(1f),
|
||||||
onRegularTap = defaultOnRegularTap,
|
onRegularTap = defaultOnRegularTap,
|
||||||
multitapDurationInMs = FAST_SEEKMODE_DURATION,
|
multiTapTimeoutInMs = FAST_SEEK_MODE_DURATION,
|
||||||
onMultiTap = fastSeek,
|
onMultiTap = fastSeek,
|
||||||
onMultiTapFinished = fastSeekFinished,
|
onMultiTapFinished = fastSeekFinished,
|
||||||
onUp = {
|
onUp = {
|
||||||
volumeIndicatorVissible = false
|
indicatorMode = IndicatorMode.NONE
|
||||||
},
|
},
|
||||||
onMovement = { change ->
|
onMovement = { change ->
|
||||||
volumeIndicatorVissible = true
|
if (indicatorMode == IndicatorMode.NONE
|
||||||
|
|| indicatorMode == IndicatorMode.VOLUME_INDICATOR_VISSIBLE
|
||||||
|
) {
|
||||||
|
indicatorMode = IndicatorMode.VOLUME_INDICATOR_VISSIBLE
|
||||||
if (heightPx != 0f) {
|
if (heightPx != 0f) {
|
||||||
volumeChange(-change.y / heightPx)
|
volumeChange(-change.y / heightPx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
FadedAnimationForSeekFeedback(fastSeekSeconds) { fastSeekSecondsToDisplay ->
|
FadedAnimationForSeekFeedback(fastSeekSeconds) { fastSeekSecondsToDisplay ->
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
|
@ -154,17 +167,21 @@ fun FullscreenGestureUI(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimatedVisibility(modifier = Modifier.align(Alignment.Center),
|
AnimatedVisibility(
|
||||||
visible = volumeIndicatorVissible,
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
visible = indicatorMode == IndicatorMode.VOLUME_INDICATOR_VISSIBLE,
|
||||||
enter = scaleIn(initialScale = 0.95f, animationSpec = tween(100)),
|
enter = scaleIn(initialScale = 0.95f, animationSpec = tween(100)),
|
||||||
exit = scaleOut(targetScale = 0.95f, animationSpec = tween(100))) {
|
exit = scaleOut(targetScale = 0.95f, animationSpec = tween(100))
|
||||||
|
) {
|
||||||
VolumeCircle(volumeFraction = volume)
|
VolumeCircle(volumeFraction = volume)
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimatedVisibility(modifier = Modifier.align(Alignment.Center),
|
AnimatedVisibility(
|
||||||
visible = brightnesIndicatorVissible,
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
visible = indicatorMode == IndicatorMode.BRIGHTNESS_INDICATOR_VISSIBLE,
|
||||||
enter = scaleIn(initialScale = 0.95f, animationSpec = tween(100)),
|
enter = scaleIn(initialScale = 0.95f, animationSpec = tween(100)),
|
||||||
exit = scaleOut(targetScale = 0.95f, animationSpec = tween(100))) {
|
exit = scaleOut(targetScale = 0.95f, animationSpec = tween(100))
|
||||||
|
) {
|
||||||
VolumeCircle(
|
VolumeCircle(
|
||||||
volumeFraction = brightnes,
|
volumeFraction = brightnes,
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
|
|
@ -40,10 +40,10 @@ import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalComposeUiApi::class)
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
fun TouchSurface(
|
fun GestureSurface(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
color: Color = Color.Transparent,
|
color: Color = Color.Transparent,
|
||||||
multitapDurationInMs: Long,
|
multiTapTimeoutInMs: Long,
|
||||||
onMultiTap: (Int) -> Unit = {},
|
onMultiTap: (Int) -> Unit = {},
|
||||||
onMultiTapFinished: () -> Unit = {},
|
onMultiTapFinished: () -> Unit = {},
|
||||||
onRegularTap: () -> Unit = {},
|
onRegularTap: () -> Unit = {},
|
||||||
|
@ -87,19 +87,19 @@ fun TouchSurface(
|
||||||
val currentTime = System.currentTimeMillis()
|
val currentTime = System.currentTimeMillis()
|
||||||
if (!moveOccured) {
|
if (!moveOccured) {
|
||||||
val timeSinceLastTouch = currentTime - lastTouchTime
|
val timeSinceLastTouch = currentTime - lastTouchTime
|
||||||
if (timeSinceLastTouch <= multitapDurationInMs) {
|
if (timeSinceLastTouch <= multiTapTimeoutInMs) {
|
||||||
regularTabJob?.cancel()
|
regularTabJob?.cancel()
|
||||||
cancelMultitapJob?.cancel()
|
cancelMultitapJob?.cancel()
|
||||||
multitapAmount++
|
multitapAmount++
|
||||||
onMultiTap(multitapAmount)
|
onMultiTap(multitapAmount)
|
||||||
cancelMultitapJob = composableScope.launch {
|
cancelMultitapJob = composableScope.launch {
|
||||||
delay(multitapDurationInMs)
|
delay(multiTapTimeoutInMs)
|
||||||
multitapAmount = 0
|
multitapAmount = 0
|
||||||
onMultiTapFinished()
|
onMultiTapFinished()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
regularTabJob = composableScope.launch {
|
regularTabJob = composableScope.launch {
|
||||||
delay(multitapDurationInMs)
|
delay(multiTapTimeoutInMs)
|
||||||
onRegularTap()
|
onRegularTap()
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue