Skip to content

Commit

Permalink
Add repeating clickable to offset change #90
Browse files Browse the repository at this point in the history
  • Loading branch information
Lambada10 committed Oct 21, 2024
1 parent 5a0b81d commit 47cb72c
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package pl.lambada.songsync.ui.screens.lyricsFetch.components

import android.util.Log
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand All @@ -25,14 +32,25 @@ import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import pl.lambada.songsync.R
import pl.lambada.songsync.util.ext.repeatingClickable


@OptIn(ExperimentalFoundationApi::class)
@Composable
fun LyricsSuccessContent(
lyrics: String,
Expand All @@ -42,6 +60,8 @@ fun LyricsSuccessContent(
onEmbedLyrics: () -> Unit,
onCopyLyrics: () -> Unit
) {


Column {
Row(
verticalAlignment = Alignment.CenterVertically,
Expand All @@ -57,7 +77,17 @@ fun LyricsSuccessContent(
modifier = Modifier.padding(start = 6.dp)
)
Spacer(modifier = Modifier.weight(1f))
OutlinedButton(onClick = { onSetOffset(offset - 100) }) {
OutlinedButton(
onClick = { /* handled by repeatingClickable */ },
modifier = Modifier
.clip(RoundedCornerShape(20.dp)) // otherwise square ripple
.repeatingClickable(
interactionSource = remember { MutableInteractionSource() },
enabled = true,
maxDelayMillis = 500,
onClick = { onSetOffset(offset - 100) }
)
) {
Text(text = "-0.1s")
}
Spacer(modifier = Modifier.width(10.dp))
Expand All @@ -66,7 +96,17 @@ fun LyricsSuccessContent(
"${offset / 1000.0}s",
)
Spacer(modifier = Modifier.width(10.dp))
OutlinedButton(onClick = { onSetOffset(offset + 100) }) {
OutlinedButton(
onClick = { /* handled by repeatingClickable */ },
modifier = Modifier
.clip(RoundedCornerShape(20.dp)) // otherwise square ripple
.repeatingClickable(
interactionSource = remember { MutableInteractionSource() },
enabled = true,
maxDelayMillis = 500,
onClick = { onSetOffset(offset + 100) }
)
) {
Text(text = "+0.1s")
}
}
Expand Down
62 changes: 62 additions & 0 deletions app/src/main/java/pl/lambada/songsync/util/ext/ComposeExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,27 @@ package pl.lambada.songsync.util.ext
import androidx.activity.OnBackPressedCallback
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.waitForUpOrCancellation
import androidx.compose.foundation.indication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.isImeVisible
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.input.pointer.pointerInput
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@OptIn(ExperimentalLayoutApi::class)
@Composable
Expand Down Expand Up @@ -39,3 +52,52 @@ fun BackPressHandler(
}
}
}

fun Modifier.repeatingClickable(
interactionSource: MutableInteractionSource,
enabled: Boolean,
maxDelayMillis: Long = 1000,
minDelayMillis: Long = 5,
delayDecayFactor: Float = .20f,
onClick: () -> Unit
): Modifier = this.then(
composed {
val currentClickListener by rememberUpdatedState(onClick)
val scope = rememberCoroutineScope()

pointerInput(interactionSource, enabled) {
scope.launch {
awaitEachGesture {
val down = awaitFirstDown(requireUnconsumed = false)
// Create a down press interaction
val downPress = PressInteraction.Press(down.position)
val heldButtonJob = launch {
// Send the press through the interaction source
interactionSource.emit(downPress)
var currentDelayMillis = maxDelayMillis
while (enabled && down.pressed) {
currentClickListener()
delay(currentDelayMillis)
val nextMillis = currentDelayMillis - (currentDelayMillis * delayDecayFactor)
currentDelayMillis = nextMillis.toLong().coerceAtLeast(minDelayMillis)
}
}
val up = waitForUpOrCancellation()
heldButtonJob.cancel()
// Determine whether a cancel or release occurred, and create the interaction
val releaseOrCancel = when (up) {
null -> PressInteraction.Cancel(downPress)
else -> PressInteraction.Release(downPress)
}
launch {
// Send the result through the interaction source
interactionSource.emit(releaseOrCancel)
}
}
}
}.indication(
interactionSource = interactionSource,
indication = rememberRipple()
)
}
)

0 comments on commit 47cb72c

Please sign in to comment.