diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt index f99fbd4b..4b9f986d 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt +++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt @@ -20,18 +20,16 @@ package com.sadellie.unitto.feature.calculator import android.content.res.Configuration import androidx.compose.animation.Crossfade -import androidx.compose.animation.core.Animatable -import androidx.compose.animation.rememberSplineBasedDecay import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation -import androidx.compose.foundation.gestures.draggable -import androidx.compose.foundation.gestures.rememberDraggableState +import androidx.compose.foundation.gestures.anchoredDraggable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.shape.RoundedCornerShape @@ -45,18 +43,17 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.onPlaced import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextRange @@ -73,13 +70,9 @@ import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField import com.sadellie.unitto.core.ui.common.textfield.UnformattedTextField import com.sadellie.unitto.data.model.HistoryItem import com.sadellie.unitto.feature.calculator.components.CalculatorKeyboard -import com.sadellie.unitto.feature.calculator.components.DragDownView import com.sadellie.unitto.feature.calculator.components.HistoryList -import kotlinx.coroutines.launch import java.text.SimpleDateFormat import java.util.Locale -import kotlin.math.abs -import kotlin.math.roundToInt @Composable internal fun CalculatorRoute( @@ -117,24 +110,15 @@ private fun CalculatorScreen( clearHistory: () -> Unit ) { val focusManager = LocalFocusManager.current - val dragAmount = remember { Animatable(0f) } - val dragCoroutineScope = rememberCoroutineScope() - val dragAnimSpec = rememberSplineBasedDecay() - - var textThingyHeight by remember { mutableIntStateOf(0) } - var historyItemHeight by remember { mutableIntStateOf(0) } - var showClearHistoryDialog by rememberSaveable { mutableStateOf(false) } - val showClearHistoryButton by remember(dragAmount.value, historyItemHeight) { - derivedStateOf { dragAmount.value > historyItemHeight } - } + var showClearHistoryButton by rememberSaveable { mutableStateOf(false) } UnittoScreenWithTopBar( title = { Text(stringResource(R.string.calculator)) }, navigationIcon = { MenuButton { navigateToMenu() } }, colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceVariant), actions = { - Crossfade(showClearHistoryButton) { + Crossfade(showClearHistoryButton, label = "Clear button reveal") { if (it) { IconButton( onClick = { showClearHistoryDialog = true }, @@ -151,140 +135,152 @@ private fun CalculatorScreen( } } ) { paddingValues -> - DragDownView( + BoxWithConstraints( modifier = Modifier.padding(paddingValues), - drag = dragAmount.value.roundToInt().coerceAtLeast(0), - historyItemHeight = historyItemHeight, - historyList = { - HistoryList( - modifier = Modifier - .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)) - .fillMaxSize(), - historyItems = uiState.history, - historyItemHeightCallback = { historyItemHeight = it }, - formatterSymbols = uiState.formatterSymbols, - addTokens = addSymbol, - ) - }, - textFields = { maxDragAmount -> - Column( - Modifier - .fillMaxHeight(0.25f) - .onPlaced { textThingyHeight = it.size.height } - .background( - MaterialTheme.colorScheme.surfaceVariant, - RoundedCornerShape( - topStartPercent = 0, topEndPercent = 0, - bottomStartPercent = 20, bottomEndPercent = 20 - ) - ) - .draggable( - orientation = Orientation.Vertical, - state = rememberDraggableState { delta -> - dragCoroutineScope.launch { - val draggedAmount = (dragAmount.value + delta).coerceAtLeast(0f) - dragAmount.snapTo(draggedAmount) - } - }, - onDragStarted = { - // Moving composables with focus causes performance drop - focusManager.clearFocus(true) - }, - onDragStopped = { velocity -> - dragCoroutineScope.launch { - dragAmount.animateDecay(velocity, dragAnimSpec) + ) { + val density = LocalDensity.current + var historyItemHeight by remember { mutableStateOf(0.dp) } + val textBoxHeight = maxHeight * 0.25f + var dragStateCurrentValue by rememberSaveable { mutableStateOf(DragState.CLOSED) } - // Snap to closest anchor (0, one history item, all history items) - val draggedAmount = listOf(0, historyItemHeight, maxDragAmount) - .minBy { abs(dragAmount.value.roundToInt() - it) } - .toFloat() - dragAmount.animateTo(draggedAmount) - } - } + val dragState = rememberDragState( + historyItem = historyItemHeight, + max = maxHeight - textBoxHeight, + initialValue = dragStateCurrentValue + ) + val dragDp by remember(dragState.requireOffset()) { + derivedStateOf { + focusManager.clearFocus(true) + with(density) { dragState.requireOffset().toDp() } + } + } + val keyboardHeight by remember(dragState.requireOffset()) { + derivedStateOf { + if (dragDp > historyItemHeight) { + maxHeight - textBoxHeight - historyItemHeight + } else { + maxHeight - textBoxHeight - dragDp + } + } + } + + LaunchedEffect(dragState.currentValue) { + dragStateCurrentValue = dragState.currentValue + showClearHistoryButton = dragState.currentValue == DragState.OPEN + } + + // History + HistoryList( + modifier = Modifier + .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)) + .fillMaxWidth() + .height(dragDp), + historyItems = uiState.history, + heightCallback = { historyItemHeight = it }, + formatterSymbols = uiState.formatterSymbols, + addTokens = addSymbol, + ) + + // Input + Column( + Modifier + .offset(y = dragDp) + .height(textBoxHeight) + .background( + MaterialTheme.colorScheme.surfaceVariant, + RoundedCornerShape( + topStartPercent = 0, topEndPercent = 0, + bottomStartPercent = 20, bottomEndPercent = 20 ) - .padding(top = 12.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - ExpressionTextField( - modifier = Modifier - .weight(2f) - .fillMaxWidth() - .padding(horizontal = 8.dp), - value = uiState.input, - minRatio = 0.5f, - cutCallback = deleteSymbol, - pasteCallback = addSymbol, - onCursorChange = onCursorChange, - formatterSymbols = uiState.formatterSymbols ) - if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT) { - when (uiState.output) { - is CalculationResult.Default -> { - var output by remember(uiState.output) { - mutableStateOf(TextFieldValue(uiState.output.text)) - } - - ExpressionTextField( - modifier = Modifier - .weight(1f) - .fillMaxWidth() - .padding(horizontal = 8.dp), - value = output, - minRatio = 1f, - onCursorChange = { output = output.copy(selection = it) }, - formatterSymbols = uiState.formatterSymbols, - textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.6f), - readOnly = true, - ) + .anchoredDraggable( + state = dragState, + orientation = Orientation.Vertical + ) + .padding(top = 12.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + ExpressionTextField( + modifier = Modifier + .weight(2f) + .fillMaxWidth() + .padding(horizontal = 8.dp), + value = uiState.input, + minRatio = 0.5f, + cutCallback = deleteSymbol, + pasteCallback = addSymbol, + onCursorChange = onCursorChange, + formatterSymbols = uiState.formatterSymbols + ) + if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT) { + when (uiState.output) { + is CalculationResult.Default -> { + var output by remember(uiState.output) { + mutableStateOf(TextFieldValue(uiState.output.text)) } - else -> { - val label = uiState.output.label?.let { stringResource(it) } ?: "" - - UnformattedTextField( - modifier = Modifier - .weight(1f) - .fillMaxWidth() - .padding(horizontal = 8.dp), - value = TextFieldValue(label), - minRatio = 1f, - onCursorChange = {}, - textColor = MaterialTheme.colorScheme.error, - readOnly = true, - ) - } + ExpressionTextField( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .padding(horizontal = 8.dp), + value = output, + minRatio = 1f, + onCursorChange = { output = output.copy(selection = it) }, + formatterSymbols = uiState.formatterSymbols, + textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.6f), + readOnly = true, + ) } - } - // Handle - Box( - Modifier - .padding(8.dp) - .background( - MaterialTheme.colorScheme.onSurfaceVariant, - RoundedCornerShape(100) + else -> { + val label = uiState.output.label?.let { stringResource(it) } ?: "" + + UnformattedTextField( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .padding(horizontal = 8.dp), + value = TextFieldValue(label), + minRatio = 1f, + onCursorChange = {}, + textColor = MaterialTheme.colorScheme.error, + readOnly = true, ) - .sizeIn(24.dp, 4.dp) - ) + } + } + } - }, - numPad = { - CalculatorKeyboard( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 8.dp, vertical = 4.dp), - radianMode = uiState.radianMode, - fractional = uiState.formatterSymbols.fractional, - allowVibration = uiState.allowVibration, - addSymbol = addSymbol, - clearSymbols = clearSymbols, - deleteSymbol = deleteSymbol, - toggleAngleMode = toggleAngleMode, - evaluate = evaluate + // Handle + Box( + Modifier + .padding(8.dp) + .background( + MaterialTheme.colorScheme.onSurfaceVariant, + RoundedCornerShape(100) + ) + .sizeIn(24.dp, 4.dp) ) } - ) + + // Keyboard + CalculatorKeyboard( + modifier = Modifier + .offset(y = dragDp + textBoxHeight) + .height(keyboardHeight) + .fillMaxWidth() + .padding(horizontal = 8.dp, vertical = 4.dp), + radianMode = uiState.radianMode, + fractional = uiState.formatterSymbols.fractional, + allowVibration = uiState.allowVibration, + addSymbol = addSymbol, + clearSymbols = clearSymbols, + deleteSymbol = deleteSymbol, + toggleAngleMode = toggleAngleMode, + evaluate = evaluate + ) + } } if (showClearHistoryDialog) { diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/DragState.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/DragState.kt new file mode 100644 index 00000000..e668b9bc --- /dev/null +++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/DragState.kt @@ -0,0 +1,53 @@ +/* + * Unitto is a unit converter for Android + * Copyright (c) 2023 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.feature.calculator + +import androidx.compose.animation.core.tween +import androidx.compose.foundation.gestures.AnchoredDraggableState +import androidx.compose.foundation.gestures.DraggableAnchors +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.Dp + +internal enum class DragState { CLOSED, HALF, OPEN } + +@Composable +internal fun rememberDragState( + initialValue: DragState = DragState.CLOSED, + historyItem: Dp, + max: Dp, +): AnchoredDraggableState { + val historyItemHeight = with(LocalDensity.current) { historyItem.toPx() } + val maxHeight = with(LocalDensity.current) { max.toPx() } + + return remember(key1 = historyItem) { + AnchoredDraggableState( + initialValue = initialValue, + anchors = DraggableAnchors { + DragState.CLOSED at 0f + DragState.HALF at historyItemHeight + DragState.OPEN at maxHeight + }, + positionalThreshold = { 0f }, + velocityThreshold = { 0f }, + animationSpec = tween() + ) + } +} diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/CalculatorKeyboard.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/CalculatorKeyboard.kt index 36068f37..f2df5c0b 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/CalculatorKeyboard.kt +++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/CalculatorKeyboard.kt @@ -41,6 +41,7 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -50,7 +51,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.Dp import com.sadellie.unitto.core.base.Token import com.sadellie.unitto.core.ui.common.ColumnWithConstraints import com.sadellie.unitto.core.ui.common.KeyboardButtonAdditional @@ -160,23 +160,36 @@ private fun PortraitKeyboard( ColumnWithConstraints( modifier = modifier ) { constraints -> - fun verticalFraction(fraction: Float): Dp = constraints.maxHeight * fraction - fun horizontalFraction(fraction: Float): Dp = constraints.maxWidth * fraction + val mainButtonHorizontalPadding by remember { + derivedStateOf { (constraints.maxWidth * 0.01f) } + } + + val additionalButtonHeight by remember { + mutableStateOf(constraints.maxHeight * 0.09f) + } + + val spacerHeight by remember { + mutableStateOf(constraints.maxHeight * 0.025f) + } + + val additionalRowSpacedBy by remember { + mutableStateOf(constraints.maxWidth * 0.03f) + } val weightModifier = Modifier.weight(1f) val mainButtonModifier = Modifier .fillMaxSize() .weight(1f) - .padding(horizontalFraction(0.015f), verticalFraction(0.009f)) + .padding(mainButtonHorizontalPadding) val additionalButtonModifier = Modifier .weight(1f) - .height(verticalFraction(0.09f)) + .height(additionalButtonHeight) - Spacer(modifier = Modifier.height(verticalFraction(0.025f))) + Spacer(modifier = Modifier.height(spacerHeight)) Row( modifier = Modifier, - horizontalArrangement = Arrangement.spacedBy(horizontalFraction(0.03f)) + horizontalArrangement = Arrangement.spacedBy(additionalRowSpacedBy) ) { // Additional buttons Crossfade(invMode, weightModifier) { @@ -204,7 +217,7 @@ private fun PortraitKeyboard( } Box( - modifier = Modifier.size(verticalFraction(0.09f)), + modifier = Modifier.size(additionalButtonHeight), contentAlignment = Alignment.Center ) { // Expand/Collapse @@ -217,7 +230,7 @@ private fun PortraitKeyboard( } } - Spacer(modifier = Modifier.height(verticalFraction(0.025f))) + Spacer(modifier = Modifier.height(spacerHeight)) Row(weightModifier) { KeyboardButtonFilled(mainButtonModifier, UnittoIcons.LeftBracket, allowVibration) { addSymbol(Token.Operator.leftBracket) } @@ -250,7 +263,7 @@ private fun PortraitKeyboard( KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Equal, allowVibration) { evaluate() } } - Spacer(modifier = Modifier.height(verticalFraction(0.015f))) + Spacer(modifier = Modifier.height(spacerHeight)) } } diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/DragDownView.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/DragDownView.kt deleted file mode 100644 index 68b25e3d..00000000 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/DragDownView.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Unitto is a unit converter for Android - * Copyright (c) 2023 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.calculator.components - -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.SubcomposeLayout -import androidx.compose.ui.unit.offset - -/** - * Screen layout where [historyList] can be seen only when you drag [textFields] down. - * - * @param modifier [Modifier] that will be applied to [SubcomposeLayout]. - * @param drag Drag amount. Update this when dragging [textFields]. - * @param historyItemHeight Height of one item in [historyList]. - * @param textFields This part of the UI should be used as a handle. Offsets when dragging. - * @param numPad Composable with buttons. Offsets when drag amount is higher than [historyItemHeight] - * (otherwise will just shrink). - */ -@Composable -internal fun DragDownView( - modifier: Modifier, - drag: Int, - historyItemHeight: Int, - historyList: @Composable () -> Unit, - textFields: @Composable (maxDragAmount: Int) -> Unit, - numPad: @Composable () -> Unit -) { - SubcomposeLayout(modifier = modifier) { constraints -> - val showHistory = drag < historyItemHeight - val offset = if (showHistory) (drag - historyItemHeight).coerceAtLeast(0) else 0 - - val textFieldPlaceables = subcompose(DragDownContent.TextFields) { - textFields(constraints.maxHeight) - }.map { it.measure(constraints.offset(offset)) } - val textFieldsHeight = textFieldPlaceables.maxByOrNull { it.height }?.height ?: 0 - - val historyListPlaceables = subcompose(DragDownContent.HistoryList) { - historyList() - }.map { - it.measure( - constraints.copy( - maxHeight = drag.coerceAtMost(constraints.maxHeight - textFieldsHeight) - ) - ) - } - - val padding = if (showHistory) drag.coerceAtLeast(0) else historyItemHeight - val numPadConstraints = constraints - .offset(offset) - .copy(maxHeight = constraints.maxHeight - textFieldsHeight - padding) - val numPadPlaceables = subcompose(DragDownContent.NumPad, numPad).map { - it.measure(numPadConstraints) - } - - layout(constraints.maxWidth, constraints.maxHeight) { - var yPos = 0 - historyListPlaceables.forEach { - it.place(0, yPos) - yPos += it.height - } - - textFieldPlaceables.forEach { - it.place(0, yPos) - yPos += it.height - } - - numPadPlaceables.forEach { - it.place(0, yPos) - yPos += it.height - } - } - } -} - -private enum class DragDownContent { HistoryList, TextFields, NumPad } diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/HistoryList.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/HistoryList.kt index 2c7112cd..edd01a34 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/HistoryList.kt +++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/HistoryList.kt @@ -49,6 +49,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.onPlaced import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalTextInputService import androidx.compose.ui.platform.LocalTextToolbar import androidx.compose.ui.platform.LocalView @@ -57,6 +58,7 @@ import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.sadellie.unitto.core.base.R import com.sadellie.unitto.core.ui.common.textfield.ExpressionTransformer @@ -73,14 +75,14 @@ import java.util.Locale internal fun HistoryList( modifier: Modifier, historyItems: List, - historyItemHeightCallback: (Int) -> Unit, + heightCallback: (Dp) -> Unit, formatterSymbols: FormatterSymbols, addTokens: (String) -> Unit, ) { if (historyItems.isEmpty()) { HistoryListPlaceholder( modifier = modifier, - historyItemHeightCallback = historyItemHeightCallback + heightCallback = heightCallback ) } else { HistoryListContent( @@ -88,7 +90,7 @@ internal fun HistoryList( historyItems = historyItems, addTokens = addTokens, formatterSymbols = formatterSymbols, - historyItemHeightCallback = historyItemHeightCallback + heightCallback = heightCallback ) } } @@ -96,15 +98,17 @@ internal fun HistoryList( @Composable private fun HistoryListPlaceholder( modifier: Modifier, - historyItemHeightCallback: (Int) -> Unit + heightCallback: (Dp) -> Unit, ) { + val density = LocalDensity.current + Column( modifier = modifier.wrapContentHeight(unbounded = true), verticalArrangement = Arrangement.Center ) { Column( modifier = Modifier - .onPlaced { historyItemHeightCallback(it.size.height) } + .onPlaced { heightCallback(with(density) { it.size.height.toDp() }) } .fillMaxWidth() .padding(vertical = 32.dp), verticalArrangement = Arrangement.Center, @@ -122,8 +126,9 @@ private fun HistoryListContent( historyItems: List, addTokens: (String) -> Unit, formatterSymbols: FormatterSymbols, - historyItemHeightCallback: (Int) -> Unit + heightCallback: (Dp) -> Unit, ) { + val density = LocalDensity.current val state = rememberLazyListState() val firstItem by remember(historyItems) { mutableStateOf(historyItems.first()) } val restOfTheItems by remember(firstItem) { mutableStateOf(historyItems.drop(1)) } @@ -139,7 +144,7 @@ private fun HistoryListContent( // We do this so that callback for items height is called only once item(firstItem.id) { HistoryListItem( - modifier = Modifier.onPlaced { historyItemHeightCallback(it.size.height) }, + modifier = Modifier.onPlaced { heightCallback(with(density) { it.size.height.toDp() }) }, historyItem = historyItems.first(), formatterSymbols = formatterSymbols, addTokens = addTokens, @@ -270,7 +275,7 @@ private fun PreviewHistoryList() { .fillMaxSize(), historyItems = historyItems, formatterSymbols = FormatterSymbols.Spaces, - historyItemHeightCallback = {}, + heightCallback = {}, addTokens = {} ) }