Updated on 2026-08-14
This commit is contained in:
parent
6d69a5706a
commit
9c1931f7d7
81 changed files with 686 additions and 981 deletions
|
|
@ -14,10 +14,10 @@ import androidx.compose.ui.unit.sp
|
|||
@Suppress("MagicNumber")
|
||||
@Composable
|
||||
fun TextAutoSize(
|
||||
modifier: Modifier = Modifier,
|
||||
text: String,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
fontSizeRange: FontSizeRange,
|
||||
modifier: Modifier = Modifier,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
) {
|
||||
val fontSizeValue = remember { mutableStateOf(fontSizeRange.max.value) }
|
||||
val readyToDraw = remember { mutableStateOf(false) }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ fun BlockchainSpinner(
|
|||
textFieldConverter: (Blockchain) -> String,
|
||||
dropdownItemView: @Composable ((Blockchain) -> Unit)? = null,
|
||||
closePopupTrigger: ClosePopupTrigger = ClosePopupTrigger(),
|
||||
onItemSelected: (Blockchain) -> Unit,
|
||||
onItemSelect: (Blockchain) -> Unit,
|
||||
) {
|
||||
OutlinedSpinner(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
|
|
@ -27,7 +27,7 @@ fun BlockchainSpinner(
|
|||
textFieldConverter = textFieldConverter,
|
||||
dropdownItemView = dropdownItemView,
|
||||
isEnabled = isEnabled,
|
||||
onItemSelected = onItemSelected,
|
||||
onItemSelected = onItemSelect,
|
||||
closePopupTrigger = closePopupTrigger,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,137 +1,8 @@
|
|||
package com.tangem.tap.common.compose
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.ripple.LocalRippleTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.tangem.core.ui.components.SpacerH8
|
||||
import com.tangem.tap.common.compose.extensions.stringResourceDefault
|
||||
import com.tangem.wallet.R
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Composable
|
||||
fun RectangleButton(
|
||||
modifier: Modifier = Modifier,
|
||||
text: String = "",
|
||||
textId: Int? = null,
|
||||
isEnabled: Boolean = true,
|
||||
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
|
||||
leadingView: @Composable RowScope.() -> Unit = {},
|
||||
middleView: @Composable RowScope.() -> Unit = { TextInButton(text = text, textId = textId) },
|
||||
trailingView: @Composable RowScope.() -> Unit = {},
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
Button(
|
||||
modifier = modifier,
|
||||
contentPadding = contentPadding,
|
||||
enabled = isEnabled,
|
||||
onClick = onClick,
|
||||
) {
|
||||
leadingView()
|
||||
middleView()
|
||||
trailingView()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TextInButton(
|
||||
modifier: Modifier = Modifier,
|
||||
text: String = "",
|
||||
textId: Int? = null,
|
||||
) {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = stringResourceDefault(textId, text),
|
||||
maxLines = 1,
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 20.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PasteButton(
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
dpSize: DpSize = DpSize(40.dp, 40.dp),
|
||||
onClick: () -> Unit,
|
||||
tint: Color? = null,
|
||||
content: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
IconButton(
|
||||
modifier = modifier.size(dpSize),
|
||||
enabled = enabled,
|
||||
onClick = onClick,
|
||||
) {
|
||||
when (content) {
|
||||
null -> {
|
||||
val tintColor = tint
|
||||
?: colorResource(id = if (enabled) R.color.button_positive else R.color.button_positive_disabled)
|
||||
Icon(
|
||||
painterResource(id = R.drawable.ic_paste),
|
||||
contentDescription = "Paste",
|
||||
tint = tintColor,
|
||||
)
|
||||
}
|
||||
else -> content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ClearButton(
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
dpSize: DpSize = DpSize(40.dp, 40.dp),
|
||||
onClick: () -> Unit,
|
||||
tint: Color? = null,
|
||||
content: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
IconButton(
|
||||
modifier = modifier.size(dpSize),
|
||||
enabled = enabled,
|
||||
onClick = onClick,
|
||||
) {
|
||||
when (content) {
|
||||
null -> {
|
||||
val tintColor = tint
|
||||
?: colorResource(id = if (enabled) R.color.button_positive else R.color.button_positive_disabled)
|
||||
Icon(
|
||||
painterResource(id = R.drawable.ic_clear),
|
||||
contentDescription = "Clear",
|
||||
tint = tintColor,
|
||||
)
|
||||
}
|
||||
else -> content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for disable ripple if button is enable = false
|
||||
|
|
@ -143,34 +14,4 @@ fun ToggledRippleTheme(
|
|||
) {
|
||||
val theme = LocalRippleTheme provides if (isEnabled) LocalRippleTheme.current else NoRippleTheme()
|
||||
CompositionLocalProvider(theme) { content() }
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ButtonTest() {
|
||||
Scaffold {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
PreviewItem("Button") {
|
||||
RectangleButton(text = "Some button") {}
|
||||
}
|
||||
PreviewItem("PasteButton") {
|
||||
PasteButton(onClick = {})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PreviewItem(
|
||||
name: String,
|
||||
content: @Composable RowScope.() -> Unit,
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = name,
|
||||
)
|
||||
content()
|
||||
}
|
||||
SpacerH8()
|
||||
}
|
||||
|
|
@ -11,19 +11,19 @@ import com.tangem.domain.common.util.ValueDebouncer
|
|||
@Composable
|
||||
fun <T> valueDebouncerAsState(
|
||||
initialValue: T,
|
||||
onValueChange: (T) -> Unit,
|
||||
debounce: Long = 600,
|
||||
onEmitValueReceived: (T) -> Unit = {},
|
||||
onValueChanged: (T) -> Unit,
|
||||
onEmitValueReceive: (T) -> Unit = {},
|
||||
): ValueDebouncer<T> {
|
||||
return remember {
|
||||
ValueDebouncer<T>(
|
||||
ValueDebouncer(
|
||||
initialValue = initialValue,
|
||||
debounceDuration = debounce,
|
||||
onEmitValueReceived = { emitValue ->
|
||||
emitValue?.let { onEmitValueReceived(it) }
|
||||
emitValue?.let { onEmitValueReceive(it) }
|
||||
},
|
||||
onValueChanged = { changedValue ->
|
||||
changedValue?.let { onValueChanged(it) }
|
||||
changedValue?.let { onValueChange(it) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -32,16 +32,16 @@ fun <T> valueDebouncerAsState(
|
|||
@Composable
|
||||
fun <T> valueDebouncerNullableAsState(
|
||||
initialValue: T?,
|
||||
onValueChange: (T?) -> Unit,
|
||||
debounce: Long = 400,
|
||||
onEmitValueReceived: (T?) -> Unit = {},
|
||||
onValueChanged: (T?) -> Unit,
|
||||
onEmitValueReceive: (T?) -> Unit = {},
|
||||
): ValueDebouncer<T?> {
|
||||
return remember {
|
||||
ValueDebouncer(
|
||||
initialValue = initialValue,
|
||||
debounceDuration = debounce,
|
||||
onEmitValueReceived = onEmitValueReceived,
|
||||
onValueChanged = onValueChanged,
|
||||
onEmitValueReceived = onEmitValueReceive,
|
||||
onValueChanged = onValueChange,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.Box
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.LocalTextStyle
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -19,23 +18,20 @@ import androidx.compose.ui.unit.dp
|
|||
fun ErrorView(
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
style: TextStyle = LocalTextStyle.current
|
||||
style: TextStyle = LocalTextStyle.current,
|
||||
) {
|
||||
Text(
|
||||
text,
|
||||
color = MaterialTheme.colors.error,
|
||||
modifier = modifier,
|
||||
style = style
|
||||
style = style,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ErrorViewTest() {
|
||||
Scaffold(
|
||||
) {
|
||||
Box(Modifier.padding(16.dp)) {
|
||||
ErrorView(text = "Some error description")
|
||||
}
|
||||
private fun ErrorViewTest() {
|
||||
Box(Modifier.padding(16.dp)) {
|
||||
ErrorView(text = "Some error description")
|
||||
}
|
||||
}
|
||||
|
|
@ -21,11 +21,11 @@ import com.tangem.tap.common.extensions.ValueCallback
|
|||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun <T> OutlinedSpinner(
|
||||
modifier: Modifier = Modifier,
|
||||
label: String,
|
||||
itemList: List<T>,
|
||||
selectedItem: Field.Data<T>,
|
||||
onItemSelected: ValueCallback<T>,
|
||||
modifier: Modifier = Modifier,
|
||||
textFieldConverter: (T) -> String = { it.toString() },
|
||||
dropdownItemView: @Composable ((T) -> Unit)? = null,
|
||||
isEnabled: Boolean = true,
|
||||
|
|
@ -96,13 +96,11 @@ class ClosePopupTrigger {
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TestSpinnerPreview() {
|
||||
Scaffold {
|
||||
OutlinedSpinner(
|
||||
label = "Blockchain name",
|
||||
itemList = listOf(Blockchain.values()),
|
||||
selectedItem = Field.Data(Blockchain.Avalanche, false),
|
||||
onItemSelected = {},
|
||||
)
|
||||
}
|
||||
private fun TestSpinnerPreview() {
|
||||
OutlinedSpinner(
|
||||
label = "Blockchain name",
|
||||
itemList = listOf(Blockchain.values()),
|
||||
selectedItem = Field.Data(Blockchain.Avalanche, false),
|
||||
onItemSelected = {},
|
||||
)
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.material.OutlinedTextField
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextFieldColors
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -41,7 +40,6 @@ import com.tangem.tap.domain.moduleMessage.ModuleMessageConverter
|
|||
*/
|
||||
@Composable
|
||||
fun OutlinedTextFieldWidget(
|
||||
modifier: Modifier = Modifier,
|
||||
fieldData: Field.Data<String>,
|
||||
labelId: Int? = null,
|
||||
label: String = "",
|
||||
|
|
@ -56,15 +54,12 @@ fun OutlinedTextFieldWidget(
|
|||
debounceTextChanges: Long = 400,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
onTextChanged: (String) -> Unit,
|
||||
onTextChange: (String) -> Unit,
|
||||
) {
|
||||
if (!isVisible) return
|
||||
|
||||
Column(
|
||||
modifier = modifier.animateContentSize(),
|
||||
) {
|
||||
Column(modifier = Modifier.animateContentSize()) {
|
||||
OutlinedProgressTextField(
|
||||
modifier = modifier,
|
||||
fieldData = fieldData,
|
||||
label = stringResourceDefault(labelId, label),
|
||||
placeholder = stringResourceDefault(placeholderId, placeholder),
|
||||
|
|
@ -75,16 +70,15 @@ fun OutlinedTextFieldWidget(
|
|||
debounce = debounceTextChanges,
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
onTextChanged = onTextChanged,
|
||||
onTextChange = onTextChange,
|
||||
)
|
||||
errorConverter?.let { AnimatedErrorView(error, it) }
|
||||
errorConverter?.let { AnimatedErrorView(errorConverter = it, error = error) }
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "NestedBlockDepth", "MagicNumber", "MaxLineLength")
|
||||
@Composable
|
||||
private fun OutlinedProgressTextField(
|
||||
modifier: Modifier = Modifier,
|
||||
fieldData: Field.Data<String>,
|
||||
label: String = "",
|
||||
placeholder: String = "",
|
||||
|
|
@ -97,7 +91,7 @@ private fun OutlinedProgressTextField(
|
|||
colors: TextFieldColors = TangemTextFieldsDefault.defaultTextFieldColors,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
onTextChanged: (String) -> Unit,
|
||||
onTextChange: (String) -> Unit,
|
||||
) {
|
||||
val logger = remember {
|
||||
CompositionLogger(label, "OutlinedProgressTextField", listOf("Символ токена"))
|
||||
|
|
@ -108,14 +102,14 @@ private fun OutlinedProgressTextField(
|
|||
val textDebouncer = valueDebouncerAsState(
|
||||
initialValue = fieldData.value,
|
||||
debounce = debounce,
|
||||
onEmitValueReceived = {
|
||||
onEmitValueReceive = {
|
||||
logger.log("DEBOUNCER: onEmitValueReceived: [$it]")
|
||||
logger.log("DEBOUNCER: start RECOMPOSE by new value for textValueState.value = [$it]")
|
||||
textValueState.value = it
|
||||
},
|
||||
onValueChanged = {
|
||||
onValueChange = {
|
||||
logger.log("DEBOUNCER: onValueChanged: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dispatch.toStore([$it])")
|
||||
onTextChanged(it)
|
||||
onTextChange(it)
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -194,7 +188,7 @@ private fun OutlinedProgressTextField(
|
|||
interactionSource = interactionSource,
|
||||
)
|
||||
AnimatedVisibility(
|
||||
modifier = modifier
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(start = 6.dp, top = 0.dp, end = 6.dp, bottom = 6.dp),
|
||||
|
|
@ -209,8 +203,8 @@ private fun OutlinedProgressTextField(
|
|||
|
||||
@Composable
|
||||
private fun AnimatedErrorView(
|
||||
error: ModuleError? = null,
|
||||
errorConverter: ModuleMessageConverter,
|
||||
error: ModuleError? = null,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = error != null,
|
||||
|
|
@ -228,7 +222,7 @@ private fun AnimatedErrorView(
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
fun OutlinedTextFieldWithErrorTest() {
|
||||
private fun OutlinedTextFieldWithErrorTest() {
|
||||
val context = LocalContext.current
|
||||
val converter = remember { ModuleMessageConverter(context) }
|
||||
|
||||
|
|
@ -241,41 +235,35 @@ fun OutlinedTextFieldWithErrorTest() {
|
|||
val modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
Scaffold {
|
||||
Column {
|
||||
OutlinedTextFieldWidget(
|
||||
modifier = modifier,
|
||||
fieldData = Field.Data("", false),
|
||||
label = "First label",
|
||||
placeholder = "1 placeholder",
|
||||
error = null,
|
||||
errorConverter = converter,
|
||||
) {}
|
||||
OutlinedTextFieldWidget(
|
||||
modifier = modifier,
|
||||
fieldData = Field.Data("First", false),
|
||||
label = "First label",
|
||||
placeholder = "1 placeholder",
|
||||
error = null,
|
||||
errorConverter = converter,
|
||||
) {}
|
||||
OutlinedTextFieldWidget(
|
||||
modifier = modifier,
|
||||
fieldData = Field.Data("First", false),
|
||||
label = "First label",
|
||||
placeholder = "1 placeholder",
|
||||
isLoading = true,
|
||||
error = null,
|
||||
errorConverter = converter,
|
||||
) {}
|
||||
OutlinedTextFieldWidget(
|
||||
modifier = modifier,
|
||||
fieldData = Field.Data("First", false),
|
||||
label = "First label",
|
||||
placeholder = "1 placeholder",
|
||||
error = SimpleError(),
|
||||
errorConverter = converter,
|
||||
) {}
|
||||
}
|
||||
Column {
|
||||
OutlinedTextFieldWidget(
|
||||
fieldData = Field.Data("", false),
|
||||
label = "First label",
|
||||
placeholder = "1 placeholder",
|
||||
error = null,
|
||||
errorConverter = converter,
|
||||
) {}
|
||||
OutlinedTextFieldWidget(
|
||||
fieldData = Field.Data("First", false),
|
||||
label = "First label",
|
||||
placeholder = "1 placeholder",
|
||||
error = null,
|
||||
errorConverter = converter,
|
||||
) {}
|
||||
OutlinedTextFieldWidget(
|
||||
fieldData = Field.Data("First", false),
|
||||
label = "First label",
|
||||
placeholder = "1 placeholder",
|
||||
isLoading = true,
|
||||
error = null,
|
||||
errorConverter = converter,
|
||||
) {}
|
||||
OutlinedTextFieldWidget(
|
||||
fieldData = Field.Data("First", false),
|
||||
label = "First label",
|
||||
placeholder = "1 placeholder",
|
||||
error = SimpleError(),
|
||||
errorConverter = converter,
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ import androidx.core.text.isDigitsOnly
|
|||
@Composable
|
||||
fun PinCodeWidget(
|
||||
config: PinViewConfig = tangemPinConfig,
|
||||
onPinChanged: (String, Boolean) -> Unit = { pin, isLastSymbolEntered -> },
|
||||
onPinChange: (String, Boolean) -> Unit = { pin, isLastSymbolEntered -> },
|
||||
) {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
|
|
@ -65,7 +65,7 @@ fun PinCodeWidget(
|
|||
|
||||
if (value.text.length <= config.pinsCount) {
|
||||
rTextFieldValue.value = value
|
||||
onPinChanged(value.text, isLastSymbolEntered())
|
||||
onPinChange(value.text, isLastSymbolEntered())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ private val tangemPinConfig = PinViewConfig(
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PinCodeWidgetPreview() {
|
||||
private fun PinCodeWidgetPreview() {
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||
PinCodeWidget(tangemPinConfig)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ import com.tangem.wallet.R
|
|||
*/
|
||||
@Composable
|
||||
fun AddCustomTokenWarning(
|
||||
modifier: Modifier = Modifier,
|
||||
warning: ModuleMessage,
|
||||
converter: ModuleMessageConverter
|
||||
converter: ModuleMessageConverter,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier,
|
||||
|
|
|
|||
|
|
@ -8,11 +8,13 @@ import com.tangem.tap.common.extensions.getFromClipboard
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Suppress("ComposableFunctionName")
|
||||
@Composable
|
||||
fun copyToClipboard(value: Any, label: String = "") {
|
||||
LocalContext.current.copyToClipboard(value, label)
|
||||
}
|
||||
|
||||
@Suppress("ComposableFunctionName")
|
||||
@Composable
|
||||
fun getFromClipboard(default: CharSequence? = null): CharSequence? {
|
||||
return LocalContext.current.getFromClipboard(default)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
package com.tangem.tap.common.compose.extensions
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import com.tangem.tap.common.extensions.hideKeyboard
|
||||
|
||||
@Composable
|
||||
fun LazyListState.OnBottomReached(loadMoreThreshold: Int, loadMore: () -> Unit) {
|
||||
fun LazyListState.OnBottomReached(loadMoreThreshold: Int, onLoadMore: () -> Unit) {
|
||||
require(loadMoreThreshold >= 0)
|
||||
val shouldLoadMore by remember {
|
||||
derivedStateOf {
|
||||
|
|
@ -17,7 +21,7 @@ fun LazyListState.OnBottomReached(loadMoreThreshold: Int, loadMore: () -> Unit)
|
|||
}
|
||||
|
||||
LaunchedEffect(shouldLoadMore) {
|
||||
if (shouldLoadMore) loadMore()
|
||||
if (shouldLoadMore) onLoadMore()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue