diff --git a/core/base/src/main/res/values/strings.xml b/core/base/src/main/res/values/strings.xml
index debd58a2..e7778fdc 100644
--- a/core/base/src/main/res/values/strings.xml
+++ b/core/base/src/main/res/values/strings.xml
@@ -1028,6 +1028,7 @@
Clear
Clear history
All expressions from history will be deleted forever. This action can\'t be undone!
+ No history
Number of decimal places
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 3d8238e0..b5684f20 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
@@ -18,7 +18,10 @@
package com.sadellie.unitto.feature.calculator
+import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
@@ -101,6 +104,7 @@ private fun CalculatorScreen(
evaluate: () -> Unit,
clearHistory: () -> Unit
) {
+ var showClearHistoryButton by rememberSaveable { mutableStateOf(false) }
var showClearHistoryDialog by rememberSaveable { mutableStateOf(false) }
var draggedAmount by remember { mutableStateOf(0f) }
val dragAmountAnimated by animateFloatAsState(draggedAmount)
@@ -113,15 +117,21 @@ private fun CalculatorScreen(
navigateUpAction = navigateUpAction,
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceVariant),
actions = {
- IconButton(
- onClick = { showClearHistoryDialog = true },
- content = {
- Icon(
- Icons.Default.Delete,
- stringResource(R.string.calculator_clear_history_title)
- )
- }
- )
+ AnimatedVisibility(
+ visible = showClearHistoryButton,
+ enter = fadeIn(),
+ exit = fadeOut()
+ ) {
+ IconButton(
+ onClick = { showClearHistoryDialog = true },
+ content = {
+ Icon(
+ Icons.Default.Delete,
+ stringResource(R.string.calculator_clear_history_title)
+ )
+ }
+ )
+ }
}
) { paddingValues ->
DragDownView(
@@ -153,10 +163,14 @@ private fun CalculatorScreen(
state = rememberDraggableState { delta ->
draggedAmount = (draggedAmount + delta).coerceAtLeast(0f)
},
- onDragStopped = {
+ onDragStopped = { _ ->
// Snap to closest anchor (0, one history item, all history items)
draggedAmount = listOf(0, historyItemHeight, maxDragAmount)
.minBy { abs(draggedAmount.roundToInt() - it) }
+ .also {
+ // Show button only when fully history view is fully expanded
+ showClearHistoryButton = it == maxDragAmount
+ }
.toFloat()
}
),
@@ -218,12 +232,21 @@ private fun CalculatorScreen(
Text(stringResource(R.string.calculator_clear_history_support))
},
confirmButton = {
- TextButton(onClick = clearHistory) { Text(stringResource(R.string.calculator_clear_history_label)) }
+ TextButton(
+ onClick = {
+ clearHistory()
+ showClearHistoryDialog = false
+ }
+ ) {
+ Text(stringResource(R.string.calculator_clear_history_label))
+ }
},
dismissButton = {
- TextButton(onClick = {
- showClearHistoryDialog = false
- }) { Text(stringResource(R.string.cancel_label)) }
+ TextButton(
+ onClick = { showClearHistoryDialog = false }
+ ) {
+ Text(stringResource(R.string.cancel_label))
+ }
},
onDismissRequest = { showClearHistoryDialog = false }
)
@@ -247,7 +270,7 @@ private fun PreviewCalculatorScreen() {
).map {
HistoryItem(
date = dtf.parse(it)!!,
- expression = "12345123451234512345123451234512345123451234512345123451234512345",
+ expression = "12345".repeat(10),
result = "67890"
)
}
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 293ef413..d9b122a1 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
@@ -18,21 +18,35 @@
package com.sadellie.unitto.feature.calculator.components
+import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
+import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.History
+import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onPlaced
+import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
import com.sadellie.unitto.core.ui.theme.NumbersTextStyleDisplayMedium
import com.sadellie.unitto.data.model.HistoryItem
+import com.sadellie.unitto.feature.calculator.R
import java.text.SimpleDateFormat
import java.util.*
@@ -42,37 +56,77 @@ internal fun HistoryList(
historyItems: List,
historyItemHeightCallback: (Int) -> Unit
) {
- LazyColumn(
- modifier = modifier,
- reverseLayout = true
- ) {
- items(historyItems) { historyItem ->
- Column(
- Modifier.onPlaced { historyItemHeightCallback(it.size.height) }
- ) {
- Text(
- text = historyItem.expression,
- maxLines = 1,
- modifier = Modifier
- .fillMaxWidth()
- .horizontalScroll(rememberScrollState(), reverseScrolling = true),
- style = NumbersTextStyleDisplayMedium,
- color = MaterialTheme.colorScheme.onSurfaceVariant,
- textAlign = TextAlign.End
- )
- Text(
- text = historyItem.result,
- maxLines = 1,
- modifier = Modifier
- .fillMaxWidth()
- .horizontalScroll(rememberScrollState(), reverseScrolling = true),
- style = NumbersTextStyleDisplayMedium,
- color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f),
- textAlign = TextAlign.End
- )
+ val verticalArrangement by remember(historyItems) {
+ derivedStateOf {
+ if (historyItems.isEmpty()) {
+ Arrangement.Center
+ } else {
+ Arrangement.spacedBy(16.dp, Alignment.Bottom)
}
}
}
+
+ LazyColumn(
+ modifier = modifier,
+ reverseLayout = true,
+ verticalArrangement = verticalArrangement
+ ) {
+ if (historyItems.isEmpty()) {
+ item {
+ Column(
+ modifier = Modifier
+ .onPlaced { historyItemHeightCallback(it.size.height) }
+ .fillParentMaxWidth()
+ .padding(vertical = 32.dp),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Icon(Icons.Default.History, null)
+ Text(stringResource(R.string.calculator_no_history))
+ }
+ }
+ } else {
+ // We do this so that callback for items height is called only once
+ item {
+ HistoryListItem(
+ modifier = Modifier.onPlaced { historyItemHeightCallback(it.size.height) },
+ historyItem = historyItems.first()
+ )
+ }
+ items(historyItems.drop(1)) { historyItem ->
+ HistoryListItem(historyItem = historyItem)
+ }
+ }
+ }
+}
+
+@Composable
+private fun HistoryListItem(
+ modifier: Modifier = Modifier,
+ historyItem: HistoryItem
+) {
+ Column(modifier = modifier) {
+ Text(
+ text = historyItem.expression,
+ maxLines = 1,
+ modifier = Modifier
+ .fillMaxWidth()
+ .horizontalScroll(rememberScrollState(), reverseScrolling = true),
+ style = NumbersTextStyleDisplayMedium,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ textAlign = TextAlign.End
+ )
+ Text(
+ text = historyItem.result,
+ maxLines = 1,
+ modifier = Modifier
+ .fillMaxWidth()
+ .horizontalScroll(rememberScrollState(), reverseScrolling = true),
+ style = NumbersTextStyleDisplayMedium,
+ color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f),
+ textAlign = TextAlign.End
+ )
+ }
}
@Preview
@@ -98,7 +152,9 @@ private fun PreviewHistoryList() {
}
HistoryList(
- modifier = Modifier.fillMaxWidth(),
+ modifier = Modifier
+ .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
+ .fillMaxSize(),
historyItems = historyItems,
historyItemHeightCallback = {}
)