diff --git a/app/src/main/java/com/sadellie/unitto/App.kt b/app/src/main/java/com/sadellie/unitto/App.kt
index c6762e63..3b8cf1b0 100644
--- a/app/src/main/java/com/sadellie/unitto/App.kt
+++ b/app/src/main/java/com/sadellie/unitto/App.kt
@@ -112,7 +112,6 @@ internal fun ComponentActivity.App(prefs: AppPreferences?) {
navController = navController,
themmoController = it,
startDestination = prefs.startingScreen,
- rpnMode = prefs.rpnMode,
openDrawer = { drawerScope.launch { drawerState.open() } }
)
}
diff --git a/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt b/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt
index a6bae2ec..43be9a39 100644
--- a/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt
+++ b/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt
@@ -42,7 +42,6 @@ internal fun UnittoNavigation(
themmoController: ThemmoController,
startDestination: String,
openDrawer: () -> Unit,
- rpnMode: Boolean,
) {
NavHost(
navController = navController,
@@ -65,7 +64,6 @@ internal fun UnittoNavigation(
calculatorGraph(
openDrawer = openDrawer,
- rpnMode = rpnMode,
navigateToSettings = navController::navigateToSettings
)
diff --git a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNCalculation.kt b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNCalculation.kt
deleted file mode 100644
index ea6603cc..00000000
--- a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNCalculation.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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 io.github.sadellie.evaluatto
-
-sealed class RPNCalculation {
- data object Negate : RPNCalculation()
-
- data object Clear : RPNCalculation()
- data object Enter : RPNCalculation()
- data object RotateUp : RPNCalculation()
- data object RotateDown : RPNCalculation()
- data object Swap : RPNCalculation()
- data object Pop : RPNCalculation()
-
- data object Plus : RPNCalculation()
- data object Minus : RPNCalculation()
- data object Multiply : RPNCalculation()
- data object Divide : RPNCalculation()
- data object Percent : RPNCalculation()
- data object Power : RPNCalculation() // unused
-}
diff --git a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNEngine.kt b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNEngine.kt
deleted file mode 100644
index 40f531eb..00000000
--- a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNEngine.kt
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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 io.github.sadellie.evaluatto
-
-import com.sadellie.unitto.core.base.MAX_PRECISION
-import java.math.BigDecimal
-import java.math.RoundingMode
-
-sealed class RPNResult {
-
- /**
- * Both input and stack were changed.
- *
- * @property input New input. Empty when `null`.
- * @property stack New stack.
- */
- data class Result(
- val input: BigDecimal?,
- val stack: List,
- ) : RPNResult()
-
- /**
- * Only input has been changed.
- *
- * @property input New input.
- */
- data class NewInput(
- val input: BigDecimal,
- ) : RPNResult()
-
- /**
- * Only stack has been changed.
- *
- * @property stack New stack.
- */
- data class NewStack(
- val stack: List,
- ) : RPNResult()
-
- /**
- * Something is wrong. Input/stack is empty or there ane not enough stack objects.
- */
- data object BadInput : RPNResult()
-
- /**
- * Dividing by zero, duh
- */
- data object DivideByZero : RPNResult()
-}
-
-// vroom vroom mfs
-// overdose on early returns
-fun RPNCalculation.perform(
- input: String,
- stack: List,
-): RPNResult {
- when (this) {
- RPNCalculation.Clear -> {
- return RPNResult.Result(null, emptyList())
- }
-
- RPNCalculation.Enter -> {
- val inputBD = input.toBigDecimalOrNull() ?: return RPNResult.BadInput
- return RPNResult.Result(null, stack + inputBD)
- }
-
- RPNCalculation.Negate -> {
- val inputBD = input.toBigDecimalOrNull() ?: return RPNResult.BadInput
- val result = inputBD.negate()
- return RPNResult.NewInput(result)
- }
-
- RPNCalculation.RotateUp -> {
- if (stack.size < 2) return RPNResult.BadInput
- return RPNResult.NewStack(stack.rotateUp())
- }
-
- RPNCalculation.RotateDown -> {
- if (stack.size < 2) return RPNResult.BadInput
- return RPNResult.NewStack(stack.rotateDown())
- }
-
- RPNCalculation.Swap -> {
- if (stack.isEmpty()) return RPNResult.BadInput
- if (input.isEmpty()) {
- // Swap last 2 in stack
- if (stack.size < 2) return RPNResult.BadInput
- return RPNResult.NewStack(stack.swapLastTwo())
- }
-
- // Swap last and input
- val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput
- return RPNResult.Result(lastFromStack, stack.dropLast(1) + inputBD)
- }
-
- RPNCalculation.Pop -> {
- val lastStacked = stack.lastOrNull() ?: return RPNResult.BadInput
- return RPNResult.Result(lastStacked, stack.dropLast(1))
- }
-
- RPNCalculation.Plus -> {
- val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput
- val result = lastFromStack.plus(inputBD)
- return RPNResult.Result(result, stack.dropLast(1))
- }
-
- RPNCalculation.Minus -> {
- val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput
- val result = lastFromStack.minus(inputBD)
- return RPNResult.Result(result, stack.dropLast(1))
- }
-
- RPNCalculation.Multiply -> {
- val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput
- val result = lastFromStack.multiply(inputBD)
- return RPNResult.Result(result, stack.dropLast(1))
- }
-
- RPNCalculation.Divide -> {
- val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput
- if (inputBD.compareTo(BigDecimal.ZERO) == 0) return RPNResult.DivideByZero
-
- val result = lastFromStack.divide(inputBD, MAX_PRECISION, RoundingMode.HALF_EVEN)
- return RPNResult.Result(result, stack.dropLast(1))
- }
-
- RPNCalculation.Percent -> {
- val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput
- // 100 * 24 / 100 =
- val result = lastFromStack
- .multiply(inputBD)
- .divide(bigDecimalHundred, MAX_PRECISION, RoundingMode.HALF_EVEN)
- return RPNResult.Result(result, stack.dropLast(1))
- }
-
- RPNCalculation.Power -> {
- val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput
- val result = lastFromStack.pow(inputBD)
- return RPNResult.Result(result, stack.dropLast(1))
- }
- }
-}
-
-private val bigDecimalHundred by lazy { BigDecimal("100") }
-
-private fun operands(
- stack: List,
- input: String,
-): Pair? {
- val first = stack.lastOrNull() ?: return null
- val second = input.toBigDecimalOrNull() ?: return null
-
- return first to second
-}
-
-private fun List.swapLastTwo(): List {
- if (size < 2) return this
- return this
- .dropLast(2)
- .plus(get(lastIndex))
- .plus(get(lastIndex - 1))
-}
-
-private fun List.rotateUp(): List {
- if (size < 2) return this
- return this
- .drop(1)
- .plus(first())
-}
-
-private fun List.rotateDown(): List {
- if (size < 2) return this
- return listOf(last())
- .plus(this.dropLast(1))
-}
diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/RPNEngineKtTest.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/RPNEngineKtTest.kt
deleted file mode 100644
index 7d3a2e60..00000000
--- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/RPNEngineKtTest.kt
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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 io.github.sadellie.evaluatto
-
-import com.sadellie.unitto.core.base.MAX_PRECISION
-import org.junit.Assert.assertEquals
-import org.junit.Test
-import java.math.BigDecimal
-
-class RPNEngineKtTest {
-
- @Test
- fun testBadOperands() {
- // no funny business if input and/or stack is empty
- val actual = RPNCalculation.Divide.perform(
- input = "",
- stack = emptyList()
- )
-
- assertEquals(RPNResult.BadInput, actual)
- }
-
- @Test
- fun testDivide() {
- val actual = RPNCalculation.Divide.perform(
- input = "2",
- stack = listOf(BigDecimal("5"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(BigDecimal("2.5").setScale(MAX_PRECISION), actual.input)
- assertEquals(emptyList(), actual.stack)
- }
-
- @Test
- fun testDivideByZero() {
- val actual = RPNCalculation.Divide.perform(
- input = "0",
- stack = listOf(BigDecimal("5"))
- )
-
- assertEquals(RPNResult.DivideByZero, actual)
- }
-
- @Test
- fun testMinus() {
- val actual = RPNCalculation.Minus.perform(
- input = "2",
- stack = listOf(BigDecimal("5"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(BigDecimal("3"), actual.input)
- assertEquals(emptyList(), actual.stack)
- }
-
- @Test
- fun testMultiply() {
- val actual = RPNCalculation.Multiply.perform(
- input = "2",
- stack = listOf(BigDecimal("5"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(BigDecimal("10"), actual.input)
- assertEquals(emptyList(), actual.stack)
- }
-
- @Test
- fun testNegate() {
- val actual = RPNCalculation.Negate.perform(
- input = "2",
- stack = listOf(BigDecimal("5"))
- )
-
- if (actual !is RPNResult.NewInput) throw Exception("Wrong return")
-
- assertEquals(BigDecimal("-2"), actual.input)
- }
-
- @Test
- fun testPercent() {
- val actual = RPNCalculation.Percent.perform(
- input = "150",
- stack = listOf(BigDecimal("69"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(BigDecimal("103.5").setScale(MAX_PRECISION), actual.input)
- assertEquals(emptyList(), actual.stack)
- }
-
- @Test
- fun testPlus() {
- val actual = RPNCalculation.Plus.perform(
- input = "150",
- stack = listOf(BigDecimal("69"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(BigDecimal("219"), actual.input)
- assertEquals(emptyList(), actual.stack)
- }
-
- @Test
- fun testPower() {
- val actual = RPNCalculation.Power.perform(
- input = "3",
- stack = listOf(BigDecimal("2"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(BigDecimal("8"), actual.input)
- assertEquals(emptyList(), actual.stack)
- }
-
- @Test
- fun testRotateUp() {
- val actual = RPNCalculation.RotateUp.perform(
- input = "",
- stack = listOf(BigDecimal("1"), BigDecimal("2"), BigDecimal("3"))
- )
-
- if (actual !is RPNResult.NewStack) throw Exception("Wrong return")
-
- assertEquals(listOf(BigDecimal("2"), BigDecimal("3"), BigDecimal("1")), actual.stack)
- }
-
- @Test
- fun testRotateDown() {
- val actual = RPNCalculation.RotateDown.perform(
- input = "",
- stack = listOf(BigDecimal("1"), BigDecimal("2"), BigDecimal("3"))
- )
-
- if (actual !is RPNResult.NewStack) throw Exception("Wrong return")
-
- assertEquals(listOf(BigDecimal("3"), BigDecimal("1"), BigDecimal("2")), actual.stack)
- }
-
- @Test
- fun testPop() {
- val actual = RPNCalculation.Pop.perform(
- input = "",
- stack = listOf(BigDecimal("1"), BigDecimal("2"), BigDecimal("3"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(BigDecimal("3"), actual.input)
- assertEquals(listOf(BigDecimal("1"), BigDecimal("2")), actual.stack)
- }
-
- @Test
- fun testClear() {
- val actual = RPNCalculation.Clear.perform(
- input = "3",
- stack = listOf(BigDecimal("2"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(null, actual.input)
- assertEquals(emptyList(), actual.stack)
- }
-
- @Test
- fun testEnter() {
- val actual = RPNCalculation.Enter.perform(
- input = "3",
- stack = listOf(BigDecimal("2"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(null, actual.input)
- assertEquals(listOf(BigDecimal("2"), BigDecimal("3")), actual.stack)
- }
-
- @Test
- fun testSwap() {
- val actual = RPNCalculation.Swap.perform(
- input = "3",
- stack = listOf(BigDecimal("2"))
- )
-
- if (actual !is RPNResult.Result) throw Exception("Wrong return")
-
- assertEquals(BigDecimal("2"), actual.input)
- assertEquals(listOf(BigDecimal("3")), actual.stack)
- }
-
- @Test
- fun testSwapEmptyInput() {
- val actual = RPNCalculation.Swap.perform(
- input = "",
- stack = listOf(BigDecimal("1"), BigDecimal("2"))
- )
-
- if (actual !is RPNResult.NewStack) throw Exception("Wrong return")
-
- assertEquals(listOf(BigDecimal("2"), BigDecimal("1")), actual.stack)
- }
-
- @Test
- fun testSwapEmptyInputNotEnoughInStack() {
- val actual = RPNCalculation.Swap.perform(
- input = "",
- stack = listOf(BigDecimal("1"))
- )
-
- assertEquals(RPNResult.BadInput, actual)
- }
-
- @Test
- fun testSwapEmptyStack() {
- val actual = RPNCalculation.Swap.perform(
- input = "123",
- stack = emptyList()
- )
-
- assertEquals(RPNResult.BadInput, actual)
- }
-
- @Test
- fun testSwapEmptyBoth() {
- val actual = RPNCalculation.Swap.perform(
- input = "",
- stack = emptyList()
- )
-
- assertEquals(RPNResult.BadInput, actual)
- }
-}
diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt
index 36c65d62..b8d3d74b 100644
--- a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt
+++ b/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt
@@ -92,6 +92,4 @@ interface UserPreferencesRepository {
suspend fun updatePartialHistoryView(enabled: Boolean)
suspend fun updateAcButton(enabled: Boolean)
-
- suspend fun updateRpnMode(enabled: Boolean)
}
diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AppPreferences.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AppPreferences.kt
index 7de30184..00004d5b 100644
--- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AppPreferences.kt
+++ b/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AppPreferences.kt
@@ -30,6 +30,5 @@ interface AppPreferences {
val startingScreen: String
val enableToolsExperiment: Boolean
val systemFont: Boolean
- val rpnMode: Boolean
val enableVibrations: Boolean
}
diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt
index c0e6336a..cb394150 100644
--- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt
+++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt
@@ -134,10 +134,6 @@ fun Preferences.getAcButton(): Boolean {
return this[PrefsKeys.AC_BUTTON] ?: true
}
-fun Preferences.getRpnMode(): Boolean {
- return this[PrefsKeys.RPN_MODE] ?: false
-}
-
private inline fun T.letTryOrNull(block: (T) -> R): R? = try {
this?.let(block)
} catch (e: Exception) {
diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt
index 2a60d1d9..d9b09e13 100644
--- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt
+++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt
@@ -44,7 +44,6 @@ data class AppPreferencesImpl(
override val startingScreen: String,
override val enableToolsExperiment: Boolean,
override val systemFont: Boolean,
- override val rpnMode: Boolean,
override val enableVibrations: Boolean,
) : AppPreferences
diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PrefsKeys.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PrefsKeys.kt
index c3c23cb1..0c65ccce 100644
--- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PrefsKeys.kt
+++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PrefsKeys.kt
@@ -37,7 +37,7 @@ object PrefsKeys {
val ENABLE_VIBRATIONS = booleanPreferencesKey("ENABLE_VIBRATIONS_PREF_KEY")
val MIDDLE_ZERO = booleanPreferencesKey("MIDDLE_ZERO_PREF_KEY")
val AC_BUTTON = booleanPreferencesKey("AC_BUTTON_PREF_KEY")
- val RPN_MODE = booleanPreferencesKey("RPN_MODE_PREF_KEY")
+ // val RPN_MODE = booleanPreferencesKey("RPN_MODE_PREF_KEY")
// FORMATTER
val DIGITS_PRECISION = intPreferencesKey("DIGITS_PRECISION_PREF_KEY")
diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt
index 57d3e616..92213e0e 100644
--- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt
+++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt
@@ -62,7 +62,6 @@ class UserPreferencesRepositoryImpl @Inject constructor(
startingScreen = preferences.getStartingScreen(),
enableToolsExperiment = preferences.getEnableToolsExperiment(),
systemFont = preferences.getSystemFont(),
- rpnMode = preferences.getRpnMode(),
enableVibrations = preferences.getEnableVibrations(),
)
}
@@ -291,10 +290,4 @@ class UserPreferencesRepositoryImpl @Inject constructor(
preferences[PrefsKeys.AC_BUTTON] = enabled
}
}
-
- override suspend fun updateRpnMode(enabled: Boolean) {
- dataStore.edit { preferences ->
- preferences[PrefsKeys.RPN_MODE] = enabled
- }
- }
}
diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/InputBox.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/InputBox.kt
deleted file mode 100644
index a8b84558..00000000
--- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/InputBox.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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.foundation.background
-import androidx.compose.foundation.layout.Arrangement
-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.padding
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.items
-import androidx.compose.foundation.lazy.rememberLazyListState
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import com.sadellie.unitto.core.base.OutputFormat
-import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField
-import com.sadellie.unitto.core.ui.common.textfield.FixedInputTextField
-import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
-import com.sadellie.unitto.data.common.format
-import java.math.BigDecimal
-
-@Composable
-internal fun InputBox(
- modifier: Modifier,
- input: TextFieldValue,
- onCursorChange: (TextRange) -> Unit,
- stack: List,
- formatterSymbols: FormatterSymbols,
- precision: Int,
- outputFormat: Int,
-) {
- val listState = rememberLazyListState()
-
- LaunchedEffect(stack) {
- listState.animateScrollToItem(stack.lastIndex.coerceAtLeast(0))
- }
-
- Column(
- modifier = modifier
- .clip(RoundedCornerShape(24.dp))
- .fillMaxWidth()
- .background(MaterialTheme.colorScheme.surfaceVariant)
- .padding(start = 12.dp, end = 12.dp, bottom = 12.dp),
- verticalArrangement = Arrangement.Bottom
- ) {
- LazyColumn(
- modifier = Modifier.weight(1f),
- state = listState,
- verticalArrangement = Arrangement.Bottom,
- ) {
- items(stack) {
- FixedInputTextField(
- modifier = Modifier.fillMaxWidth(),
- value = it.format(precision, outputFormat),
- formatterSymbols = formatterSymbols,
- textColor = MaterialTheme.colorScheme.onSurfaceVariant,
- onClick = {}
- )
- }
- }
-
- ExpressionTextField(
- modifier = Modifier
- .fillMaxWidth()
- .fillMaxHeight(0.25f),
- value = input,
- minRatio = 0.6f,
- onCursorChange = onCursorChange,
- formatterSymbols = formatterSymbols,
- textColor = MaterialTheme.colorScheme.onSurfaceVariant
- )
- }
-}
-
-@Preview(device = "spec:width=1080px,height=2160px,dpi=440")
-@Composable
-fun PreviewInputBox() {
- InputBox(
- modifier = Modifier.fillMaxSize(),
- input = TextFieldValue("123456.789"),
- onCursorChange = {},
- stack = listOf(
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- ),
- formatterSymbols = FormatterSymbols.Spaces,
- precision = 3,
- outputFormat = OutputFormat.PLAIN
- )
-}
diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorKeyboard.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorKeyboard.kt
deleted file mode 100644
index f38788ab..00000000
--- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorKeyboard.kt
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.tooling.preview.Preview
-import com.sadellie.unitto.core.base.Token
-import com.sadellie.unitto.core.ui.LocalWindowSize
-import com.sadellie.unitto.core.ui.WindowHeightSizeClass
-import com.sadellie.unitto.core.ui.common.KeyboardButtonAdditional
-import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightShort
-import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTall
-import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTallAdditional
-import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled
-import com.sadellie.unitto.core.ui.common.KeyboardButtonLight
-import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary
-import com.sadellie.unitto.core.ui.common.KeypadFlow
-import com.sadellie.unitto.core.ui.common.icons.IconPack
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Backspace
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Clear
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Comma
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Divide
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Dot
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Down
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Enter
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key0
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key1
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key2
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key3
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key4
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key5
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key6
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key7
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key8
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Key9
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Minus
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Multiply
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Percent
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Plus
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Pop
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Swap
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Unary
-import com.sadellie.unitto.core.ui.common.icons.iconpack.Up
-import io.github.sadellie.evaluatto.RPNCalculation
-
-@Composable
-internal fun RPNCalculatorKeyboard(
- modifier: Modifier,
- fractional: String,
- middleZero: Boolean,
- onCalculationClick: (RPNCalculation) -> Unit,
- onInputEditClick: (RPNInputEdit) -> Unit,
-) {
- val fractionalIcon = remember(fractional) { if (fractional == Token.Digit.dot) IconPack.Dot else IconPack.Comma }
-
- if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) {
- RPNCalculatorKeyboardLandscape(
- modifier = modifier,
- fractionalIcon = fractionalIcon,
- middleZero = middleZero,
- onCalculationClick = onCalculationClick,
- onInputEditClick = onInputEditClick
- )
- } else {
- RPNCalculatorKeyboardPortrait(
- modifier = modifier,
- fractionalIcon = fractionalIcon,
- middleZero = middleZero,
- onCalculationClick = onCalculationClick,
- onInputEditClick = onInputEditClick
- )
- }
-}
-
-@Composable
-private fun RPNCalculatorKeyboardPortrait(
- modifier: Modifier,
- fractionalIcon: ImageVector,
- middleZero: Boolean,
- onCalculationClick: (RPNCalculation) -> Unit,
- onInputEditClick: (RPNInputEdit) -> Unit,
-) {
- Column(
- modifier = modifier
- ) {
- KeypadFlow(
- modifier = Modifier.fillMaxHeight(0.1f).fillMaxWidth(),
- rows = 1,
- columns = 4
- ) { width, height ->
- val aModifier = Modifier
- .fillMaxWidth(width)
- .fillMaxHeight(height)
-
- KeyboardButtonAdditional(aModifier, IconPack.Swap, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.Swap) }
- KeyboardButtonAdditional(aModifier, IconPack.Up, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.RotateUp) }
- KeyboardButtonAdditional(aModifier, IconPack.Down, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.RotateDown) }
- KeyboardButtonAdditional(aModifier, IconPack.Pop, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.Pop) }
- }
-
- KeypadFlow(
- modifier = Modifier.weight(1f).fillMaxSize(),
- rows = 5,
- columns = 4
- ) { width, height ->
- val bModifier = Modifier
- .fillMaxWidth(width)
- .fillMaxHeight(height)
-
- KeyboardButtonTertiary(bModifier, IconPack.Clear, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Clear) }
- KeyboardButtonFilled(bModifier, IconPack.Unary, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Negate) }
- KeyboardButtonFilled(bModifier, IconPack.Percent, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Percent) }
- KeyboardButtonFilled(bModifier, IconPack.Divide, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Divide) }
-
- KeyboardButtonLight(bModifier, IconPack.Key7, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._7)) }
- KeyboardButtonLight(bModifier, IconPack.Key8, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._8)) }
- KeyboardButtonLight(bModifier, IconPack.Key9, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._9)) }
- KeyboardButtonFilled(bModifier, IconPack.Multiply, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Multiply) }
-
- KeyboardButtonLight(bModifier, IconPack.Key4, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._4)) }
- KeyboardButtonLight(bModifier, IconPack.Key5, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._5)) }
- KeyboardButtonLight(bModifier, IconPack.Key6, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._6)) }
- KeyboardButtonFilled(bModifier, IconPack.Minus, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Minus) }
-
- KeyboardButtonLight(bModifier, IconPack.Key1, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._1)) }
- KeyboardButtonLight(bModifier, IconPack.Key2, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._2)) }
- KeyboardButtonLight(bModifier, IconPack.Key3, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._3)) }
- KeyboardButtonFilled(bModifier, IconPack.Plus, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Plus) }
-
- if (middleZero) {
- KeyboardButtonLight(bModifier, fractionalIcon, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Dot) }
- KeyboardButtonLight(bModifier, IconPack.Key0, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) }
- } else {
- KeyboardButtonLight(bModifier, IconPack.Key0, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) }
- KeyboardButtonLight(bModifier, fractionalIcon, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Dot) }
- }
- KeyboardButtonLight(bModifier, IconPack.Backspace, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Delete) }
- KeyboardButtonFilled(bModifier, IconPack.Enter, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Enter) }
- }
- }
-}
-
-@Composable
-private fun RPNCalculatorKeyboardLandscape(
- modifier: Modifier,
- fractionalIcon: ImageVector,
- middleZero: Boolean,
- onCalculationClick: (RPNCalculation) -> Unit,
- onInputEditClick: (RPNInputEdit) -> Unit,
-) {
- KeypadFlow(
- modifier = modifier,
- rows = 4,
- columns = 6
- ) { width, height ->
- val bModifier = Modifier
- .fillMaxHeight(height)
- .fillMaxWidth(width)
-
- KeyboardButtonAdditional(bModifier, IconPack.Swap, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.Swap) }
- KeyboardButtonLight(bModifier, IconPack.Key7, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._7)) }
- KeyboardButtonLight(bModifier, IconPack.Key8, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._8)) }
- KeyboardButtonLight(bModifier, IconPack.Key9, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._9)) }
- KeyboardButtonTertiary(bModifier, IconPack.Clear, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Clear) }
- KeyboardButtonFilled(bModifier, IconPack.Unary, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Negate) }
-
- KeyboardButtonAdditional(bModifier, IconPack.Up, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.RotateUp) }
- KeyboardButtonLight(bModifier, IconPack.Key4, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._4)) }
- KeyboardButtonLight(bModifier, IconPack.Key5, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._5)) }
- KeyboardButtonLight(bModifier, IconPack.Key6, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._6)) }
- KeyboardButtonFilled(bModifier, IconPack.Multiply, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Multiply) }
- KeyboardButtonFilled(bModifier, IconPack.Divide, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Divide) }
-
- KeyboardButtonAdditional(bModifier, IconPack.Down, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.RotateDown) }
- KeyboardButtonLight(bModifier, IconPack.Key1, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._1)) }
- KeyboardButtonLight(bModifier, IconPack.Key2, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._2)) }
- KeyboardButtonLight(bModifier, IconPack.Key3, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._3)) }
- KeyboardButtonFilled(bModifier, IconPack.Plus, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Plus) }
- KeyboardButtonFilled(bModifier, IconPack.Minus, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Minus) }
-
- KeyboardButtonAdditional(bModifier, IconPack.Pop, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.Pop) }
- if (middleZero) {
- KeyboardButtonLight(bModifier, fractionalIcon, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Dot) }
- KeyboardButtonLight(bModifier, IconPack.Key0, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) }
- } else {
- KeyboardButtonLight(bModifier, IconPack.Key0, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) }
- KeyboardButtonLight(bModifier, fractionalIcon, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Dot) }
- }
- KeyboardButtonLight(bModifier, IconPack.Backspace, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Delete) }
- KeyboardButtonFilled(bModifier, IconPack.Percent, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Percent) }
- KeyboardButtonFilled(bModifier, IconPack.Enter, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Enter) }
- }
-}
-
-@Preview(device = "spec:parent=pixel_5,orientation=portrait")
-@Preview(device = "spec:parent=pixel_5,orientation=landscape")
-@Composable
-private fun PreviewKeyboard() {
- RPNCalculatorKeyboard(
- modifier = Modifier.fillMaxSize(),
- fractional = Token.Digit.dot,
- middleZero = false,
- onCalculationClick = {},
- onInputEditClick = {}
- )
-}
diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorScreen.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorScreen.kt
deleted file mode 100644
index 7028b939..00000000
--- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorScreen.kt
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material3.Text
-import com.sadellie.unitto.core.ui.WindowHeightSizeClass
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import androidx.hilt.navigation.compose.hiltViewModel
-import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.sadellie.unitto.core.base.OutputFormat
-import com.sadellie.unitto.core.base.R
-import com.sadellie.unitto.core.ui.LocalWindowSize
-import com.sadellie.unitto.core.ui.common.MenuButton
-import com.sadellie.unitto.core.ui.common.SettingsButton
-import com.sadellie.unitto.core.ui.common.EmptyScreen
-import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar
-import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
-import io.github.sadellie.evaluatto.RPNCalculation
-import java.math.BigDecimal
-
-@Composable
-internal fun RPNCalculatorRoute(
- openDrawer: () -> Unit,
- navigateToSettings: () -> Unit,
- viewModel: RPNCalculatorViewModel = hiltViewModel(),
-) {
- when (val uiState = viewModel.uiState.collectAsStateWithLifecycle().value) {
- RPNCalculatorUIState.Loading -> EmptyScreen()
- is RPNCalculatorUIState.Ready -> RPNCalculatorScreen(
- uiState = uiState,
- openDrawer = openDrawer,
- navigateToSettings = navigateToSettings,
- onCursorChange = viewModel::onCursorChange,
- onCalculationClick = viewModel::onCalculationClick,
- onInputEditClick = viewModel::onInputEdit
- )
- }
-}
-
-@Composable
-internal fun RPNCalculatorScreen(
- uiState: RPNCalculatorUIState.Ready,
- openDrawer: () -> Unit,
- navigateToSettings: () -> Unit,
- onCursorChange: (TextRange) -> Unit,
- onCalculationClick: (RPNCalculation) -> Unit,
- onInputEditClick: (RPNInputEdit) -> Unit,
-) {
- ScaffoldWithTopBar(
- title = { Text(stringResource(id = R.string.calculator_title)) },
- navigationIcon = { MenuButton(openDrawer) },
- actions = { SettingsButton(navigateToSettings) }
- ) { paddingValues ->
- Column(
- Modifier.padding(paddingValues)
- ) {
- InputBox(
- modifier = Modifier
- .padding(8.dp)
- .fillMaxHeight(if (LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact) 0.3f else 0.5f),
- input = uiState.input,
- stack = uiState.stack,
- formatterSymbols = uiState.formatterSymbols,
- precision = uiState.precision,
- outputFormat = uiState.outputFormat,
- onCursorChange = onCursorChange
- )
- RPNCalculatorKeyboard(
- modifier = Modifier
- .padding(horizontal = 4.dp)
- .fillMaxSize(),
- fractional = uiState.formatterSymbols.fractional,
- middleZero = uiState.middleZero,
- onCalculationClick = onCalculationClick,
- onInputEditClick = onInputEditClick
- )
- }
- }
-}
-
-@Preview(widthDp = 432, heightDp = 1008, device = "spec:parent=pixel_5,orientation=portrait")
-@Preview(widthDp = 432, heightDp = 864, device = "spec:parent=pixel_5,orientation=portrait")
-@Preview(widthDp = 597, heightDp = 1393, device = "spec:parent=pixel_5,orientation=portrait")
-@Composable
-private fun RPNCalculatorScreenPreview() {
- RPNCalculatorScreen(
- uiState = RPNCalculatorUIState.Ready(
- input = TextFieldValue("test"),
- stack = listOf(
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- BigDecimal("123456.7890"),
- ),
- precision = 3,
- outputFormat = OutputFormat.PLAIN,
- formatterSymbols = FormatterSymbols.Spaces,
- middleZero = true,
- ),
- openDrawer = {},
- navigateToSettings = {},
- onCalculationClick = {},
- onInputEditClick = {},
- onCursorChange = {}
- )
-}
diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorUIState.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorUIState.kt
deleted file mode 100644
index 4db3230d..00000000
--- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorUIState.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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.ui.text.input.TextFieldValue
-import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
-import java.math.BigDecimal
-
-internal sealed class RPNCalculatorUIState {
- data object Loading : RPNCalculatorUIState()
-
- data class Ready(
- val input: TextFieldValue,
- val stack: List,
- val precision: Int,
- val outputFormat: Int,
- val formatterSymbols: FormatterSymbols,
- val middleZero: Boolean,
- ) : RPNCalculatorUIState()
-}
diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorViewModel.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorViewModel.kt
deleted file mode 100644
index 2de873d3..00000000
--- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorViewModel.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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.ui.text.TextRange
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.lifecycle.SavedStateHandle
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.viewModelScope
-import com.sadellie.unitto.core.base.Token
-import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols
-import com.sadellie.unitto.core.ui.common.textfield.addTokens
-import com.sadellie.unitto.core.ui.common.textfield.deleteTokens
-import com.sadellie.unitto.core.ui.common.textfield.getTextField
-import com.sadellie.unitto.data.common.format
-import com.sadellie.unitto.data.common.stateIn
-import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
-import dagger.hilt.android.lifecycle.HiltViewModel
-import io.github.sadellie.evaluatto.RPNCalculation
-import io.github.sadellie.evaluatto.RPNResult
-import io.github.sadellie.evaluatto.perform
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.update
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.math.BigDecimal
-import javax.inject.Inject
-
-@HiltViewModel
-internal class RPNCalculatorViewModel @Inject constructor(
- userPrefsRepository: UserPreferencesRepository,
- private val savedStateHandle: SavedStateHandle,
-) : ViewModel() {
-
- private val _inputKey = "RPN_CALCULATOR_INPUT"
- private val _input = MutableStateFlow(savedStateHandle.getTextField(_inputKey))
- private val _stack = MutableStateFlow(emptyList())
- private val _prefs = userPrefsRepository.calculatorPrefs.stateIn(viewModelScope, null)
-
- val uiState = combine(
- _prefs,
- _input,
- _stack
- ) { prefs, input, stack ->
- prefs ?: return@combine RPNCalculatorUIState.Loading
-
- return@combine RPNCalculatorUIState.Ready(
- input = input,
- stack = stack,
- precision = prefs.precision,
- outputFormat = prefs.outputFormat,
- formatterSymbols = AllFormatterSymbols.getById(prefs.separator),
- middleZero = prefs.middleZero
- )
- }
- .stateIn(viewModelScope, RPNCalculatorUIState.Loading)
-
- fun onInputEdit(action: RPNInputEdit) {
- val input = _input.value
- val newInput = when (action) {
- is RPNInputEdit.Digit -> input.addTokens(action.value)
- RPNInputEdit.Dot -> {
- if (_input.value.text.contains(Token.Digit.dot)) return
- input.addTokens(Token.Digit.dot)
- }
- RPNInputEdit.Delete -> input.deleteTokens()
- }
-
- _input.update { newInput }
- savedStateHandle[_inputKey] = newInput.text
- }
-
- fun onCalculationClick(action: RPNCalculation) = viewModelScope.launch {
- val prefs = _prefs.value ?: return@launch
-
- val newResult = withContext(Dispatchers.Default) {
- action.perform(_input.value.text, _stack.value)
- }
-
- when (newResult) {
- is RPNResult.Result -> {
- val newInput = newResult.input?.format(prefs.precision, prefs.outputFormat) ?: ""
- _input.update { TextFieldValue(newInput, TextRange(newInput.length)) }
- _stack.update { newResult.stack }
- }
-
- is RPNResult.NewStack -> {
- _stack.update { newResult.stack }
- }
-
- is RPNResult.NewInput -> {
- val newInput = newResult.input.format(prefs.precision, prefs.outputFormat)
- _input.update { TextFieldValue(newInput, TextRange(newInput.length)) }
- }
- RPNResult.BadInput, RPNResult.DivideByZero -> Unit
- }
- }
-
- fun onCursorChange(selection: TextRange) = _input.update { it.copy(selection = selection) }
-}
diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNInputEdit.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNInputEdit.kt
deleted file mode 100644
index 28a391d9..00000000
--- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNInputEdit.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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
-
-sealed class RPNInputEdit {
- data class Digit(val value: String) : RPNInputEdit()
- data object Delete : RPNInputEdit()
- data object Dot : RPNInputEdit()
-}
diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/navigation/CalculatorNavigation.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/navigation/CalculatorNavigation.kt
index d6f6f262..b3d62764 100644
--- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/navigation/CalculatorNavigation.kt
+++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/navigation/CalculatorNavigation.kt
@@ -24,13 +24,11 @@ import com.sadellie.unitto.core.ui.model.DrawerItem
import com.sadellie.unitto.core.ui.unittoComposable
import com.sadellie.unitto.core.ui.unittoNavigation
import com.sadellie.unitto.feature.calculator.CalculatorRoute
-import com.sadellie.unitto.feature.calculator.RPNCalculatorRoute
private val graph = DrawerItem.Calculator.graph
private val start = DrawerItem.Calculator.start
fun NavGraphBuilder.calculatorGraph(
- rpnMode: Boolean,
openDrawer: () -> Unit,
navigateToSettings: () -> Unit
) {
@@ -42,17 +40,10 @@ fun NavGraphBuilder.calculatorGraph(
)
) {
unittoComposable(start) {
- if (rpnMode) {
- RPNCalculatorRoute(
- openDrawer = openDrawer,
- navigateToSettings = navigateToSettings
- )
- } else {
- CalculatorRoute(
- navigateToMenu = openDrawer,
- navigateToSettings = navigateToSettings
- )
- }
+ CalculatorRoute(
+ navigateToMenu = openDrawer,
+ navigateToSettings = navigateToSettings
+ )
}
}
}
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsScreen.kt
index ee25cc90..480edaaa 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsScreen.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsScreen.kt
@@ -18,7 +18,6 @@
package com.sadellie.unitto.feature.settings.calculator
-import androidx.compose.animation.Crossfade
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
@@ -29,84 +28,51 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.sadellie.unitto.core.base.OutputFormat
import com.sadellie.unitto.core.base.R
-import com.sadellie.unitto.core.ui.common.NavigateUpButton
+import com.sadellie.unitto.core.base.Separator
import com.sadellie.unitto.core.ui.common.EmptyScreen
import com.sadellie.unitto.core.ui.common.ListItem
+import com.sadellie.unitto.core.ui.common.NavigateUpButton
import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar
+import com.sadellie.unitto.data.model.userprefs.CalculatorPreferences
+import com.sadellie.unitto.data.userprefs.CalculatorPreferencesImpl
@Composable
internal fun CalculatorSettingsRoute(
viewModel: CalculatorSettingsViewModel = hiltViewModel(),
navigateUpAction: () -> Unit,
) {
- when (val prefs = viewModel.uiState.collectAsStateWithLifecycle().value) {
- CalculatorSettingsUIState.Loading -> EmptyScreen()
+ when (val prefs = viewModel.prefs.collectAsStateWithLifecycle().value) {
+ null -> EmptyScreen()
else -> {
CalculatorSettingsScreen(
- uiState = prefs,
+ prefs = prefs,
navigateUpAction = navigateUpAction,
updatePartialHistoryView = viewModel::updatePartialHistoryView,
- updateRpnMode = viewModel::updateRpnMode,
)
}
}
}
-// TODO Translate
@Composable
private fun CalculatorSettingsScreen(
- uiState: CalculatorSettingsUIState,
+ prefs: CalculatorPreferences,
navigateUpAction: () -> Unit,
updatePartialHistoryView: (Boolean) -> Unit,
- updateRpnMode: (Boolean) -> Unit,
) {
ScaffoldWithLargeTopBar(
title = stringResource(R.string.calculator_title),
navigationIcon = { NavigateUpButton(navigateUpAction) }
) { padding ->
Column(Modifier.padding(padding)) {
-// SingleChoiceSegmentedButtonRow(
-// modifier = Modifier
-// .fillMaxWidth()
-// .padding(16.dp)
-// ) {
-// SegmentedButton(
-// selected = uiState is CalculatorSettingsUIState.Standard,
-// onClick = { updateRpnMode(false) },
-// shape = SegmentedButtonDefaults.itemShape(index = 0, count = 2),
-// ) {
-// Text("Standard")
-// }
-// SegmentedButton(
-// selected = uiState == CalculatorSettingsUIState.RPN,
-// onClick = { updateRpnMode(true) },
-// shape = SegmentedButtonDefaults.itemShape(index = 1, count = 2),
-// ) {
-// Text("RPN")
-// }
-// }
-
- Crossfade(
- targetState = uiState,
- label = "Mode switch"
- ) { state ->
- when (state) {
- is CalculatorSettingsUIState.Standard -> {
- Column {
- ListItem(
- headlineText = stringResource(R.string.settings_partial_history_view),
- icon = Icons.Default.Timer,
- supportingText = stringResource(R.string.settings_partial_history_view_support),
- switchState = state.partialHistoryView,
- onSwitchChange = updatePartialHistoryView
- )
- }
- }
-
- else -> Unit
- }
- }
+ ListItem(
+ headlineText = stringResource(R.string.settings_partial_history_view),
+ icon = Icons.Default.Timer,
+ supportingText = stringResource(R.string.settings_partial_history_view_support),
+ switchState = prefs.partialHistoryView,
+ onSwitchChange = updatePartialHistoryView
+ )
}
}
}
@@ -115,22 +81,16 @@ private fun CalculatorSettingsScreen(
@Composable
private fun PreviewCalculatorSettingsScreenStandard() {
CalculatorSettingsScreen(
- uiState = CalculatorSettingsUIState.Standard(
- partialHistoryView = true,
+ prefs = CalculatorPreferencesImpl(
+ radianMode = true,
+ separator = Separator.SPACE,
+ middleZero = false,
+ acButton = false,
+ partialHistoryView = false,
+ precision = 3,
+ outputFormat = OutputFormat.PLAIN
),
navigateUpAction = {},
updatePartialHistoryView = {},
- updateRpnMode = {}
- )
-}
-
-@Preview
-@Composable
-private fun PreviewCalculatorSettingsScreenRPN() {
- CalculatorSettingsScreen(
- uiState = CalculatorSettingsUIState.RPN,
- navigateUpAction = {},
- updatePartialHistoryView = {},
- updateRpnMode = {}
)
}
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsUIState.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsUIState.kt
deleted file mode 100644
index 899cb51e..00000000
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsUIState.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Unitto is a calculator for Android
- * Copyright (c) 2023-2024 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.settings.calculator
-
-internal sealed class CalculatorSettingsUIState {
- data object Loading : CalculatorSettingsUIState()
-
- data object RPN : CalculatorSettingsUIState()
-
- data class Standard(
- val partialHistoryView: Boolean,
- ) : CalculatorSettingsUIState()
-}
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsViewModel.kt
index 41b4c69a..eb4e3ff5 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsViewModel.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsViewModel.kt
@@ -23,7 +23,6 @@ import androidx.lifecycle.viewModelScope
import com.sadellie.unitto.data.common.stateIn
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -31,25 +30,10 @@ import javax.inject.Inject
internal class CalculatorSettingsViewModel @Inject constructor(
private val userPrefsRepository: UserPreferencesRepository,
) : ViewModel() {
- val uiState = combine(
- userPrefsRepository.appPrefs,
- userPrefsRepository.calculatorPrefs,
- ) { app, calc ->
- if (app.rpnMode) {
- CalculatorSettingsUIState.RPN
- } else {
- CalculatorSettingsUIState.Standard(
- partialHistoryView = calc.partialHistoryView,
- )
- }
- }
- .stateIn(viewModelScope, CalculatorSettingsUIState.Loading)
+ val prefs = userPrefsRepository.calculatorPrefs
+ .stateIn(viewModelScope, null)
fun updatePartialHistoryView(enabled: Boolean) = viewModelScope.launch {
userPrefsRepository.updatePartialHistoryView(enabled)
}
-
- fun updateRpnMode(enabled: Boolean) = viewModelScope.launch {
- userPrefsRepository.updateRpnMode(enabled)
- }
}