diff --git a/core/base/src/main/res/values/strings.xml b/core/base/src/main/res/values/strings.xml
index 1144d3c6..de34f1ce 100644
--- a/core/base/src/main/res/values/strings.xml
+++ b/core/base/src/main/res/values/strings.xml
@@ -81,6 +81,12 @@ Used in this dialog window. Should be short -->
Select time
About Unitto
Learn about the app
+
+
+ AC button
+
+
+ Show separate clear button
Additional
AMOLED Dark
Use black background for dark themes
diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeyboardButton.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeyboardButton.kt
index e76a4e6b..a77994a7 100644
--- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeyboardButton.kt
+++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeyboardButton.kt
@@ -140,3 +140,24 @@ fun KeyboardButtonAdditional(
allowVibration = allowVibration,
)
}
+
+@Composable
+fun KeyboardButtonTertiary(
+ modifier: Modifier,
+ icon: ImageVector,
+ allowVibration: Boolean,
+ contentHeight: Float = if (isPortrait()) 0.578f else 0.793f,
+ onLongClick: (() -> Unit)? = null,
+ onClick: () -> Unit,
+) {
+ BasicKeyboardButton(
+ modifier = modifier,
+ contentHeight = contentHeight,
+ onClick = onClick,
+ onLongClick = onLongClick,
+ containerColor = MaterialTheme.colorScheme.tertiaryContainer,
+ icon = icon,
+ iconColor = MaterialTheme.colorScheme.onTertiaryContainer,
+ allowVibration = allowVibration,
+ )
+}
diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/CursorFixer.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/CursorFixer.kt
index acbd5134..010f8876 100644
--- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/CursorFixer.kt
+++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/CursorFixer.kt
@@ -85,14 +85,14 @@ private fun Int.isAfterToken(str: String, token: String): Boolean {
}
-// This can make [TextFieldValue.addTokens] better by checking tokens both ways. Needs more tests
-//fun String.tokenAfter(pos: Int): String {
-// Token.Func.allWithOpeningBracket.forEach {
-// if (pos.isBeforeToken(this, it)) return it
-// }
-//
-// return substring(pos, (pos + 1).coerceAtMost(this.length))
-//}
+// This can also make [TextFieldValue.addTokens] better by checking tokens both ways. Needs more tests
+fun String.tokenAfter(pos: Int): String {
+ Token.Func.allWithOpeningBracket.forEach {
+ if (pos.isBeforeToken(this, it)) return it
+ }
+
+ return substring(pos, (pos + 1).coerceAtMost(this.length))
+}
//private fun String.numberNearby(cursor: Int): String {
// val text = this
@@ -111,8 +111,8 @@ private fun Int.isAfterToken(str: String, token: String): Boolean {
// return text.substring(aheadCursor, afterCursor)
//}
-//private fun Int.isBeforeToken(str: String, token: String): Boolean {
-// return str
-// .substring(this, (this + token.length).coerceAtMost(str.length))
-// .contains(token)
-//}
+private fun Int.isBeforeToken(str: String, token: String): Boolean {
+ return str
+ .substring(this, (this + token.length).coerceAtMost(str.length))
+ .contains(token)
+}
diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/TextFieldValueExtensions.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/TextFieldValueExtensions.kt
index d97b1e8b..3df15e5b 100644
--- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/TextFieldValueExtensions.kt
+++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/TextFieldValueExtensions.kt
@@ -53,15 +53,52 @@ fun TextFieldValue.addTokens(tokens: String): TextFieldValue {
)
}
-/**
- * !!! Recursive !!! (one wrong step and you are dead 💀)
- */
-private fun TextFieldValue.deleteAheadAndAdd(tokens: String): TextFieldValue {
- var newValue = this
- if (!selection.collapsed) newValue = this.deleteTokens()
- return newValue
- .deleteTokens()
- .addTokens(tokens)
+fun TextFieldValue.addBracket(): TextFieldValue {
+ val subStringBeforeCursor = text.substring(0..!!! Recursive !!! (one wrong step and you are dead 💀)
+ */
+private fun TextFieldValue.deleteAheadAndAdd(tokens: String): TextFieldValue {
+ var newValue = this
+ if (!selection.collapsed) newValue = this.deleteTokens()
+ return newValue
+ .deleteTokens()
+ .addTokens(tokens)
+}
diff --git a/core/ui/src/test/java/com/sadellie/unitto/core/ui/TextFieldValueExtensionsTest.kt b/core/ui/src/test/java/com/sadellie/unitto/core/ui/TextFieldValueExtensionsTest.kt
index 4c419be3..8e350164 100644
--- a/core/ui/src/test/java/com/sadellie/unitto/core/ui/TextFieldValueExtensionsTest.kt
+++ b/core/ui/src/test/java/com/sadellie/unitto/core/ui/TextFieldValueExtensionsTest.kt
@@ -21,6 +21,7 @@ package com.sadellie.unitto.core.ui
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import com.sadellie.unitto.core.base.Token
+import com.sadellie.unitto.core.ui.common.textfield.addBracket
import com.sadellie.unitto.core.ui.common.textfield.addTokens
import org.junit.Assert.assertEquals
import org.junit.Test
@@ -260,6 +261,60 @@ class TextFieldValueExtensionsTest {
assertEquals(tf("123+45.[]78"), tf("123+45[6.]78").addTokens(Token.Digit.dot))
}
+ @Test
+ fun auto() {
+ // Open on empty in front
+ assertEquals(tf("([]"), tf("[]").addBracket())
+ assertEquals(tf("([]123("), tf("[]123(").addBracket())
+ assertEquals(tf("([]("), tf("[123](").addBracket())
+ assertEquals(tf("([]"), tf("[123(]").addBracket())
+
+ // Close before multiply
+ assertEquals(tf("123)[]*456"), tf("123[]*456").addBracket())
+ assertEquals(tf("(123)[]*456"), tf("(123[]*456").addBracket())
+ assertEquals(tf(")123)[]*456"), tf(")123[]*456").addBracket())
+ // Close before divide
+ assertEquals(tf("123)[]/456"), tf("123[]/456").addBracket())
+ assertEquals(tf("(123)[]/456"), tf("(123[]/456").addBracket())
+ assertEquals(tf(")123)[]/456"), tf(")123[]/456").addBracket())
+ // Close before plus
+ assertEquals(tf("123)[]+456"), tf("123[]+456").addBracket())
+ assertEquals(tf("(123)[]+456"), tf("(123[]+456").addBracket())
+ assertEquals(tf(")123)[]+456"), tf(")123[]+456").addBracket())
+ // Close before minus
+ assertEquals(tf("123)[]-456"), tf("123[]-456").addBracket())
+ assertEquals(tf("(123)[]-456"), tf("(123[]-456").addBracket())
+ assertEquals(tf(")123)[]-456"), tf(")123[]-456").addBracket())
+ // Close before power
+ assertEquals(tf("123)[]^456"), tf("123[]^456").addBracket())
+ assertEquals(tf("(123)[]^456"), tf("(123[]^456").addBracket())
+ assertEquals(tf(")123)[]^456"), tf(")123[]^456").addBracket())
+
+ // Open on balanced in front
+ assertEquals(tf("123([]"), tf("123[]").addBracket())
+ assertEquals(tf("123([](((("), tf("123[]((((").addBracket())
+
+ // Open after multiply
+ assertEquals(tf("123*([]456"), tf("123*[]456").addBracket())
+ assertEquals(tf("123*([]"), tf("123*[456]").addBracket())
+ // Open after divide
+ assertEquals(tf("123/([]456"), tf("123/[]456").addBracket())
+ assertEquals(tf("123/([]"), tf("123/[456]").addBracket())
+ // Open after plus
+ assertEquals(tf("123+([]456"), tf("123+[]456").addBracket())
+ assertEquals(tf("123+([]"), tf("123+[456]").addBracket())
+ // Open after minus
+ assertEquals(tf("123-([]456"), tf("123-[]456").addBracket())
+ assertEquals(tf("123-([]"), tf("123-[456]").addBracket())
+ // Open after power
+ assertEquals(tf("123^([]456"), tf("123^[]456").addBracket())
+ assertEquals(tf("123^([]"), tf("123^[456]").addBracket())
+
+ // Default
+ assertEquals(tf("123([]"), tf("123[]").addBracket())
+ assertEquals(tf("123(456+789)[]"), tf("123(456+789[]").addBracket())
+ }
+
// Use [] for selection
private fun tf(
text: String = "",
@@ -267,6 +322,9 @@ class TextFieldValueExtensionsTest {
val selectionStart = text.indexOf("[")
val selectionEnd = text.indexOf("]") - 1
+ if (selectionStart < 0) throw Exception("forgot selectionStart")
+ if (selectionEnd < 0) throw Exception("forgot selectionEnd")
+
return TextFieldValue(
text = text
.replace("[", "")
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 9a0ecb47..cf45c596 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
@@ -45,6 +45,7 @@ data class CalculatorPreferences(
val enableVibrations: Boolean,
val separator: Int,
val middleZero: Boolean,
+ val acButton: Boolean,
val partialHistoryView: Boolean,
val precision: Int,
val outputFormat: Int,
@@ -54,6 +55,7 @@ data class ConverterPreferences(
val enableVibrations: Boolean,
val separator: Int,
val middleZero: Boolean,
+ val acButton: Boolean,
val precision: Int,
val outputFormat: Int,
val unitConverterFormatTime: Boolean,
@@ -68,6 +70,7 @@ data class ConverterPreferences(
data class DisplayPreferences(
val systemFont: Boolean,
val middleZero: Boolean,
+ val acButton: Boolean,
)
data class FormattingPreferences(
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 36a4a18f..156a6c44 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
@@ -46,4 +46,5 @@ internal object PrefsKeys {
val MIDDLE_ZERO = booleanPreferencesKey("MIDDLE_ZERO_PREF_KEY")
val SYSTEM_FONT = booleanPreferencesKey("SYSTEM_FONT_PREF_KEY")
val PARTIAL_HISTORY_VIEW = booleanPreferencesKey("PARTIAL_HISTORY_VIEW_PREF_KEY")
+ val AC_BUTTON = booleanPreferencesKey("AC_BUTTON_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 a988391d..45912ddb 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
@@ -75,7 +75,8 @@ class UserPreferencesRepository @Inject constructor(
middleZero = preferences.getMiddleZero(),
partialHistoryView = preferences.getPartialHistoryView(),
precision = preferences.getDigitsPrecision(),
- outputFormat = preferences.getOutputFormat()
+ outputFormat = preferences.getOutputFormat(),
+ acButton = preferences.getAcButton(),
)
}
@@ -94,6 +95,7 @@ class UserPreferencesRepository @Inject constructor(
enableToolsExperiment = preferences.getEnableToolsExperiment(),
latestLeftSideUnit = preferences.getLatestLeftSide(),
latestRightSideUnit = preferences.getLatestRightSide(),
+ acButton = preferences.getAcButton(),
)
}
@@ -102,6 +104,7 @@ class UserPreferencesRepository @Inject constructor(
DisplayPreferences(
systemFont = preferences.getSystemFont(),
middleZero = preferences.getMiddleZero(),
+ acButton = preferences.getAcButton(),
)
}
@@ -263,6 +266,12 @@ class UserPreferencesRepository @Inject constructor(
preferences[PrefsKeys.PARTIAL_HISTORY_VIEW] = enabled
}
}
+
+ suspend fun updateAcButton(enabled: Boolean) {
+ dataStore.edit { preferences ->
+ preferences[PrefsKeys.AC_BUTTON] = enabled
+ }
+ }
}
private fun Preferences.getEnableDynamicTheme(): Boolean {
@@ -359,6 +368,10 @@ private fun Preferences.getLatestRightSide(): String {
return this[PrefsKeys.LATEST_RIGHT_SIDE] ?: MyUnitIDS.mile
}
+private fun Preferences.getAcButton(): Boolean {
+ return this[PrefsKeys.AC_BUTTON] ?: false
+}
+
private inline fun T.letTryOrNull(block: (T) -> R): R? = try {
this?.let(block)
} catch (e: Exception) {
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 20484ca3..2fa0d461 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
@@ -89,7 +89,8 @@ internal fun CalculatorRoute(
onCursorChange = viewModel::onCursorChange,
toggleCalculatorMode = viewModel::toggleCalculatorMode,
evaluate = viewModel::evaluate,
- clearHistory = viewModel::clearHistory
+ clearHistory = viewModel::clearHistory,
+ addBracket = viewModel::addBracket
)
}
@@ -99,6 +100,7 @@ internal fun CalculatorScreen(
navigateToMenu: () -> Unit,
navigateToSettings: () -> Unit,
addTokens: (String) -> Unit,
+ addBracket: () -> Unit,
clearInput: () -> Unit,
deleteTokens: () -> Unit,
onCursorChange: (TextRange) -> Unit,
@@ -118,7 +120,8 @@ internal fun CalculatorScreen(
onCursorChange = onCursorChange,
toggleAngleMode = toggleCalculatorMode,
evaluate = evaluate,
- clearHistory = clearHistory
+ clearHistory = clearHistory,
+ addBracket = addBracket
)
}
}
@@ -129,6 +132,7 @@ private fun Ready(
navigateToMenu: () -> Unit,
navigateToSettings: () -> Unit,
addSymbol: (String) -> Unit,
+ addBracket: () -> Unit,
clearSymbols: () -> Unit,
deleteSymbol: () -> Unit,
onCursorChange: (TextRange) -> Unit,
@@ -264,6 +268,8 @@ private fun Ready(
toggleAngleMode = toggleAngleMode,
evaluate = evaluate,
middleZero = uiState.middleZero,
+ acButton = uiState.acButton,
+ addBracket = addBracket
)
}
}
@@ -343,6 +349,7 @@ private fun PreviewCalculatorScreen() {
onCursorChange = {},
toggleCalculatorMode = {},
evaluate = {},
- clearHistory = {}
+ clearHistory = {},
+ addBracket = {}
)
}
\ No newline at end of file
diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorUIState.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorUIState.kt
index c1fc01eb..862d4b7a 100644
--- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorUIState.kt
+++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorUIState.kt
@@ -35,6 +35,7 @@ internal sealed class CalculatorUIState {
val allowVibration: Boolean = false,
val formatterSymbols: FormatterSymbols = FormatterSymbols.Spaces,
val middleZero: Boolean = false,
+ val acButton: Boolean = false,
val partialHistoryView: Boolean = true,
) : CalculatorUIState()
}
diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt
index e4816934..6cc81be5 100644
--- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt
+++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt
@@ -26,6 +26,7 @@ import com.sadellie.unitto.core.base.OutputFormat
import com.sadellie.unitto.core.base.Separator
import com.sadellie.unitto.core.base.Token
import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols
+import com.sadellie.unitto.core.ui.common.textfield.addBracket
import com.sadellie.unitto.core.ui.common.textfield.addTokens
import com.sadellie.unitto.core.ui.common.textfield.deleteTokens
import com.sadellie.unitto.data.calculator.CalculatorHistoryRepository
@@ -67,7 +68,8 @@ internal class CalculatorViewModel @Inject constructor(
middleZero = false,
partialHistoryView = true,
precision = 3,
- outputFormat = OutputFormat.PLAIN
+ outputFormat = OutputFormat.PLAIN,
+ acButton = false,
)
)
@@ -87,6 +89,7 @@ internal class CalculatorViewModel @Inject constructor(
allowVibration = userPrefs.enableVibrations,
formatterSymbols = AllFormatterSymbols.getById(userPrefs.separator),
middleZero = userPrefs.middleZero,
+ acButton = userPrefs.acButton,
partialHistoryView = userPrefs.partialHistoryView,
)
}
@@ -95,6 +98,7 @@ internal class CalculatorViewModel @Inject constructor(
)
fun addTokens(tokens: String) = _input.update { it.addTokens(tokens) }
+ fun addBracket() = _input.update { it.addBracket() }
fun deleteTokens() = _input.update { it.deleteTokens() }
fun clearInput() = _input.update { TextFieldValue() }
fun onCursorChange(selection: TextRange) = _input.update { it.copy(selection = selection) }
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 69f11377..b3475eb5 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
@@ -56,12 +56,15 @@ import com.sadellie.unitto.core.ui.common.ColumnWithConstraints
import com.sadellie.unitto.core.ui.common.KeyboardButtonAdditional
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.RowWithConstraints
import com.sadellie.unitto.core.ui.common.key.UnittoIcons
import com.sadellie.unitto.core.ui.common.key.unittoicons.AcTan
import com.sadellie.unitto.core.ui.common.key.unittoicons.ArCos
import com.sadellie.unitto.core.ui.common.key.unittoicons.ArSin
import com.sadellie.unitto.core.ui.common.key.unittoicons.Backspace
+import com.sadellie.unitto.core.ui.common.key.unittoicons.Brackets
+import com.sadellie.unitto.core.ui.common.key.unittoicons.Clear
import com.sadellie.unitto.core.ui.common.key.unittoicons.Comma
import com.sadellie.unitto.core.ui.common.key.unittoicons.Cos
import com.sadellie.unitto.core.ui.common.key.unittoicons.Deg
@@ -106,7 +109,9 @@ internal fun CalculatorKeyboard(
fractional: String,
allowVibration: Boolean,
middleZero: Boolean,
+ acButton: Boolean,
addSymbol: (String) -> Unit,
+ addBracket: () -> Unit,
clearSymbols: () -> Unit,
deleteSymbol: () -> Unit,
toggleAngleMode: () -> Unit,
@@ -123,7 +128,9 @@ internal fun CalculatorKeyboard(
toggleAngleMode = toggleAngleMode,
deleteSymbol = deleteSymbol,
clearSymbols = clearSymbols,
- evaluate = evaluate
+ evaluate = evaluate,
+ acButton = acButton,
+ addBracket = addBracket,
)
} else {
LandscapeKeyboard(
@@ -136,7 +143,9 @@ internal fun CalculatorKeyboard(
toggleAngleMode = toggleAngleMode,
deleteSymbol = deleteSymbol,
clearSymbols = clearSymbols,
- evaluate = evaluate
+ evaluate = evaluate,
+ acButton = acButton,
+ addBracket = addBracket,
)
}
}
@@ -152,7 +161,9 @@ private fun PortraitKeyboard(
toggleAngleMode: () -> Unit,
deleteSymbol: () -> Unit,
clearSymbols: () -> Unit,
- evaluate: () -> Unit
+ evaluate: () -> Unit,
+ acButton: Boolean,
+ addBracket: () -> Unit,
) {
val fractionalIcon = remember { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma }
var showAdditional: Boolean by remember { mutableStateOf(false) }
@@ -239,8 +250,13 @@ private fun PortraitKeyboard(
Spacer(modifier = Modifier.height(spacerHeight))
Row(weightModifier) {
- KeyboardButtonFilled(mainButtonModifier, UnittoIcons.LeftBracket, allowVibration) { addSymbol(Token.Operator.leftBracket) }
- KeyboardButtonFilled(mainButtonModifier, UnittoIcons.RightBracket, allowVibration) { addSymbol(Token.Operator.rightBracket) }
+ if (acButton) {
+ KeyboardButtonTertiary(mainButtonModifier, UnittoIcons.Clear, allowVibration) { clearSymbols() }
+ KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Brackets, allowVibration) { addBracket() }
+ } else {
+ KeyboardButtonFilled(mainButtonModifier, UnittoIcons.LeftBracket, allowVibration) { addSymbol(Token.Operator.leftBracket) }
+ KeyboardButtonFilled(mainButtonModifier, UnittoIcons.RightBracket, allowVibration) { addSymbol(Token.Operator.rightBracket) }
+ }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Percent, allowVibration) { addSymbol(Token.Operator.percent) }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Divide, allowVibration) { addSymbol(Token.Operator.divide) }
}
@@ -361,7 +377,9 @@ private fun LandscapeKeyboard(
toggleAngleMode: () -> Unit,
deleteSymbol: () -> Unit,
clearSymbols: () -> Unit,
- evaluate: () -> Unit
+ evaluate: () -> Unit,
+ acButton: Boolean,
+ addBracket: () -> Unit,
) {
val fractionalIcon = remember { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma }
var invMode: Boolean by remember { mutableStateOf(false) }
@@ -426,13 +444,21 @@ private fun LandscapeKeyboard(
}
Column(Modifier.weight(1f)) {
- KeyboardButtonFilled(buttonModifier, UnittoIcons.LeftBracket, allowVibration) { addSymbol(Token.Operator.leftBracket) }
+ if (acButton) {
+ KeyboardButtonTertiary(buttonModifier, UnittoIcons.Clear, allowVibration) { clearSymbols() }
+ } else {
+ KeyboardButtonFilled(buttonModifier, UnittoIcons.LeftBracket, allowVibration) { addSymbol(Token.Operator.leftBracket) }
+ }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Multiply, allowVibration) { addSymbol(Token.Operator.multiply) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Minus, allowVibration) { addSymbol(Token.Operator.minus) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Plus, allowVibration) { addSymbol(Token.Operator.plus) }
}
Column(Modifier.weight(1f)) {
- KeyboardButtonFilled(buttonModifier, UnittoIcons.RightBracket, allowVibration) { addSymbol(Token.Operator.rightBracket) }
+ if (acButton) {
+ KeyboardButtonTertiary(buttonModifier, UnittoIcons.Brackets, allowVibration) { addBracket() }
+ } else {
+ KeyboardButtonFilled(buttonModifier, UnittoIcons.RightBracket, allowVibration) { addSymbol(Token.Operator.rightBracket) }
+ }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Divide, allowVibration) { addSymbol(Token.Operator.divide) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Percent, allowVibration) { addSymbol(Token.Operator.percent) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Equal, allowVibration) { evaluate() }
@@ -518,5 +544,7 @@ private fun PreviewCalculatorKeyboard() {
evaluate = {},
allowVibration = false,
middleZero = false,
+ acButton = true,
+ addBracket = {}
)
}
diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt
index 8a675cd7..de4709fd 100644
--- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt
+++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt
@@ -110,6 +110,7 @@ internal fun ConverterRoute(
clearInput = viewModel::clearInput,
onCursorChange = viewModel::onCursorChange,
onErrorClick = viewModel::updateCurrencyRates,
+ addBracket = viewModel::addBracket
)
}
@@ -126,6 +127,7 @@ private fun ConverterScreen(
clearInput: () -> Unit,
onCursorChange: (TextRange) -> Unit,
onErrorClick: (AbstractUnit) -> Unit,
+ addBracket: () -> Unit,
) {
when (uiState) {
UnitConverterUIState.Loading -> UnittoEmptyScreen()
@@ -164,7 +166,8 @@ private fun ConverterScreen(
swapUnits = swapUnits,
navigateToRightScreen = navigateToRightScreen,
clearInput = clearInput,
- refreshCurrencyRates = onErrorClick
+ refreshCurrencyRates = onErrorClick,
+ addBracket = addBracket,
)
}
}
@@ -258,6 +261,7 @@ private fun Default(
navigateToRightScreen: () -> Unit,
clearInput: () -> Unit,
refreshCurrencyRates: (AbstractUnit) -> Unit,
+ addBracket: () -> Unit,
) {
val locale: Locale = LocalLocale.current
var calculation by remember(uiState.calculation) {
@@ -365,7 +369,9 @@ private fun Default(
clearInput = clearInput,
allowVibration = uiState.enableHaptic,
fractional = uiState.formatterSymbols.fractional,
- middleZero = uiState.middleZero
+ middleZero = uiState.middleZero,
+ acButton = uiState.acButton,
+ addBracket = addBracket
)
}
)
@@ -522,5 +528,6 @@ private fun PreviewConverterScreen() {
clearInput = {},
onCursorChange = {},
onErrorClick = {},
+ addBracket = {}
)
}
diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt
index e264d76e..cd91c026 100644
--- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt
+++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt
@@ -46,6 +46,7 @@ internal sealed class UnitConverterUIState {
val outputFormat: Int,
val formatTime: Boolean,
val currencyRateUpdateState: CurrencyRateUpdateState,
+ val acButton: Boolean,
) : UnitConverterUIState()
data class NumberBase(
diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt
index edc214ab..f07cc8f1 100644
--- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt
+++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt
@@ -25,6 +25,7 @@ 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.addBracket
import com.sadellie.unitto.core.ui.common.textfield.addTokens
import com.sadellie.unitto.core.ui.common.textfield.deleteTokens
import com.sadellie.unitto.data.common.combine
@@ -105,7 +106,8 @@ internal class ConverterViewModel @Inject constructor(
scale = prefs.precision,
outputFormat = prefs.outputFormat,
formatTime = prefs.unitConverterFormatTime,
- currencyRateUpdateState = currenciesState
+ currencyRateUpdateState = currenciesState,
+ acButton = prefs.acButton,
)
}
(unitFrom is NumberBaseUnit) and (unitTo is NumberBaseUnit) -> {
@@ -256,6 +258,12 @@ internal class ConverterViewModel @Inject constructor(
newValue
}
+ fun addBracket() = _input.update {
+ val newValue = it.addBracket()
+ savedStateHandle[converterInputKey] = newValue.text
+ newValue
+ }
+
fun deleteTokens() = _input.update {
val newValue = it.deleteTokens()
savedStateHandle[converterInputKey] = newValue.text
diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ConverterKeyboard.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ConverterKeyboard.kt
index b859ae97..b64df4f1 100644
--- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ConverterKeyboard.kt
+++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ConverterKeyboard.kt
@@ -31,8 +31,11 @@ import com.sadellie.unitto.core.base.Token
import com.sadellie.unitto.core.ui.common.ColumnWithConstraints
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.key.UnittoIcons
import com.sadellie.unitto.core.ui.common.key.unittoicons.Backspace
+import com.sadellie.unitto.core.ui.common.key.unittoicons.Brackets
+import com.sadellie.unitto.core.ui.common.key.unittoicons.Clear
import com.sadellie.unitto.core.ui.common.key.unittoicons.Comma
import com.sadellie.unitto.core.ui.common.key.unittoicons.Divide
import com.sadellie.unitto.core.ui.common.key.unittoicons.Dot
@@ -70,6 +73,8 @@ internal fun DefaultKeyboard(
allowVibration: Boolean,
fractional: String,
middleZero: Boolean,
+ acButton: Boolean,
+ addBracket: () -> Unit,
) {
ColumnWithConstraints(modifier) {
val fractionalIcon = remember { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma }
@@ -85,8 +90,13 @@ internal fun DefaultKeyboard(
// Column modifier
val cModifier = Modifier.weight(1f)
Row(cModifier) {
- KeyboardButtonFilled(bModifier, UnittoIcons.LeftBracket, allowVibration) { addDigit(Token.Operator.leftBracket) }
- KeyboardButtonFilled(bModifier, UnittoIcons.RightBracket, allowVibration) { addDigit(Token.Operator.rightBracket) }
+ if (acButton) {
+ KeyboardButtonTertiary(bModifier, UnittoIcons.Clear, allowVibration) { clearInput() }
+ KeyboardButtonFilled(bModifier, UnittoIcons.Brackets, allowVibration) { addBracket() }
+ } else {
+ KeyboardButtonFilled(bModifier, UnittoIcons.LeftBracket, allowVibration) { addDigit(Token.Operator.leftBracket) }
+ KeyboardButtonFilled(bModifier, UnittoIcons.RightBracket, allowVibration) { addDigit(Token.Operator.rightBracket) }
+ }
KeyboardButtonFilled(bModifier, UnittoIcons.Power, allowVibration) { addDigit(Token.Operator.power) }
KeyboardButtonFilled(bModifier, UnittoIcons.Root, allowVibration) { addDigit(Token.Operator.sqrt) }
}
@@ -188,7 +198,9 @@ private fun PreviewConverterKeyboard() {
deleteDigit = {},
allowVibration = false,
fractional = FormatterSymbols.Spaces.fractional,
- middleZero = false
+ middleZero = false,
+ acButton = true,
+ addBracket = {}
)
}
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 5fcaf898..1674c6c7 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
@@ -88,7 +88,8 @@ private fun PreviewCalculatorSettingsScreen() {
middleZero = false,
partialHistoryView = true,
precision = 3,
- outputFormat = OutputFormat.PLAIN
+ outputFormat = OutputFormat.PLAIN,
+ acButton = true,
),
navigateUpAction = {},
updatePartialHistoryView = {}
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt
index 61b5b4bb..0fa6c17c 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt
@@ -147,6 +147,7 @@ private fun PreviewConverterSettingsScreen() {
enableToolsExperiment = false,
latestLeftSideUnit = "kilometer",
latestRightSideUnit = "mile",
+ acButton = true,
),
navigateUpAction = {},
navigateToUnitsGroup = {},
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayScreen.kt
index b6da7f26..77209105 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayScreen.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayScreen.kt
@@ -62,6 +62,8 @@ import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
import com.sadellie.unitto.core.ui.common.UnittoListItem
import com.sadellie.unitto.core.ui.common.UnittoScreenWithLargeTopBar
+import com.sadellie.unitto.core.ui.common.key.UnittoIcons
+import com.sadellie.unitto.core.ui.common.key.unittoicons.Clear
import com.sadellie.unitto.feature.settings.components.ColorSelector
import com.sadellie.unitto.feature.settings.components.MonetModeSelector
import io.github.sadellie.themmo.MonetMode
@@ -113,6 +115,8 @@ internal fun DisplayRoute(
},
systemFont = prefs.systemFont,
updateSystemFont = viewModel::updateSystemFont,
+ acButton = prefs.acButton,
+ updateAcButton = viewModel::updateAcButton,
middleZero = prefs.middleZero,
updateMiddleZero = viewModel::updateMiddleZero,
navigateToLanguages = navigateToLanguages
@@ -136,6 +140,8 @@ private fun DisplayScreen(
onMonetModeChange: (MonetMode) -> Unit,
systemFont: Boolean,
updateSystemFont: (Boolean) -> Unit,
+ acButton: Boolean,
+ updateAcButton: (Boolean) -> Unit,
middleZero: Boolean,
updateMiddleZero: (Boolean) -> Unit,
navigateToLanguages: () -> Unit,
@@ -266,6 +272,15 @@ private fun DisplayScreen(
onSwitchChange = updateSystemFont
)
+ UnittoListItem(
+ icon = UnittoIcons.Clear,
+ iconDescription = stringResource(R.string.settings_middle_zero),
+ headlineText = stringResource(R.string.settings_ac_button),
+ supportingText = stringResource(R.string.settings_ac_button_support),
+ switchState = acButton,
+ onSwitchChange = updateAcButton
+ )
+
UnittoListItem(
icon = Icons.Default.ExposureZero,
iconDescription = stringResource(R.string.settings_middle_zero),
@@ -304,6 +319,8 @@ private fun Preview() {
onMonetModeChange = themmoController::setMonetMode,
systemFont = false,
updateSystemFont = {},
+ acButton = false,
+ updateAcButton = {},
middleZero = false,
updateMiddleZero = {},
navigateToLanguages = {}
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayViewModel.kt
index 21e9a5d7..7a4ce77c 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayViewModel.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayViewModel.kt
@@ -37,60 +37,48 @@ class DisplayViewModel @Inject constructor(
val prefs = userPrefsRepository.displayPrefs
.stateIn(viewModelScope, null)
- /**
- * @see UserPreferencesRepository.updateThemingMode
- */
fun updateThemingMode(themingMode: ThemingMode) {
viewModelScope.launch {
userPrefsRepository.updateThemingMode(themingMode)
}
}
- /**
- * @see UserPreferencesRepository.updateDynamicTheme
- */
fun updateDynamicTheme(enabled: Boolean) {
viewModelScope.launch {
userPrefsRepository.updateDynamicTheme(enabled)
}
}
- /**
- * @see UserPreferencesRepository.updateAmoledTheme
- */
fun updateAmoledTheme(enabled: Boolean) {
viewModelScope.launch {
userPrefsRepository.updateAmoledTheme(enabled)
}
}
- /**
- * @see UserPreferencesRepository.updateCustomColor
- */
fun updateCustomColor(color: Color) {
viewModelScope.launch {
userPrefsRepository.updateCustomColor(color)
}
}
- /**
- * @see UserPreferencesRepository.updateMonetMode
- */
fun updateMonetMode(monetMode: MonetMode) {
viewModelScope.launch {
userPrefsRepository.updateMonetMode(monetMode)
}
}
- /**
- * @see UserPreferencesRepository.updateSystemFont
- */
fun updateSystemFont(enabled: Boolean) {
viewModelScope.launch {
userPrefsRepository.updateSystemFont(enabled)
}
}
+ fun updateAcButton(enabled: Boolean) {
+ viewModelScope.launch {
+ userPrefsRepository.updateAcButton(enabled)
+ }
+ }
+
fun updateMiddleZero(enabled: Boolean) = viewModelScope.launch {
userPrefsRepository.updateMiddleZero(enabled)
}