You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/compose/ext/Modifier.kt

103 lines
3.1 KiB
Kotlin

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.compose.ext
import android.os.SystemClock
import androidx.compose.foundation.clickable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.unit.Dp
/**
* Add a dashed border around the current composable.
*
* @param color [Color] to apply to the dashed border.
* @param cornerRadius The corner radius of the rounded rectangle.
* @param dashHeight The thickness of a dash.
* @param dashWidth The length of a dash.
* @param dashGap The size of the gap between the dashes.
*/
fun Modifier.dashedBorder(
color: Color,
cornerRadius: Dp,
dashHeight: Dp,
dashWidth: Dp,
dashGap: Dp = dashWidth,
) = this.then(
drawBehind {
val cornerRadiusPx = cornerRadius.toPx()
val borderHeightPx = dashHeight.toPx()
val dashWidthPx = dashWidth.toPx()
val dashGapPx = dashGap.toPx()
val dashedStroke = Stroke(
width = borderHeightPx,
pathEffect = PathEffect.dashPathEffect(
floatArrayOf(dashWidthPx, dashGapPx),
0f,
),
)
drawRoundRect(
color = color,
cornerRadius = CornerRadius(cornerRadiusPx),
style = dashedStroke,
)
},
)
/**
* Used when clickable needs to be debounced to prevent rapid successive clicks
* from calling the onClick function.
*
* @param debounceInterval The length of time to wait between click events in milliseconds
* @param onClick Callback for when item this modifier effects is clicked
*/
fun Modifier.debouncedClickable(
debounceInterval: Long = 1000L,
onClick: () -> Unit,
) = composed {
var lastClickTime: Long by remember { mutableStateOf(0) }
this.then(
Modifier.clickable(
onClick = {
val currentSystemTime = SystemClock.elapsedRealtime()
if (currentSystemTime - lastClickTime > debounceInterval) {
onClick()
lastClickTime = currentSystemTime
}
},
),
)
}
/**
* A conditional [Modifier.then] extension that allows chaining of conditional Modifiers.
*
* @param modifier The [Modifier] to return if the [predicate] is satisfied.
* @param predicate The predicate used to determine which [Modifier] to return.
*
* @return the appropriate [Modifier] given the [predicate].
*/
fun Modifier.thenConditional(
modifier: Modifier,
predicate: () -> Boolean,
): Modifier =
if (predicate()) {
then(modifier)
} else {
this
}