From 89b9e4a30d805a7fc8937190eb05f45f0b7bb4d0 Mon Sep 17 00:00:00 2001
From: sosauce2 <98750531+sosauce@users.noreply.github.com>
Date: Thu, 6 Feb 2025 22:11:49 +0100
Subject: [PATCH] v2.4.0
---
app/build.gradle.kts | 4 +-
app/src/main/AndroidManifest.xml | 4 +-
.../main/java/com/sosauce/cutecalc/AppBar.kt | 157 -------------
.../sosauce/cutecalc/components/AboutCard.kt | 19 +-
.../sosauce/cutecalc/components/CuteButton.kt | 35 ++-
.../components/CuteNavigationButton.kt | 42 ++++
.../components/HistoryActionButtons.kt | 107 +++++++++
.../cutecalc/components/LongClickButton.kt | 173 ++++++++++++++
.../sosauce/cutecalc/components/Switches.kt | 217 +++++++++---------
.../cutecalc/history/HistoryViewModel.kt | 2 +-
.../cutecalc/logic/CalculatorViewModel.kt | 13 +-
.../com/sosauce/cutecalc/logic/Evaluator.kt | 21 +-
.../com/sosauce/cutecalc/logic/Settings.kt | 5 +
.../cutecalc/logic/navigation/Navigation.kt | 7 +-
.../sosauce/cutecalc/screens/Calculator.kt | 99 +++++---
.../sosauce/cutecalc/screens/HistoryScreen.kt | 78 +++----
.../cutecalc/screens/LandscapeLayout.kt | 17 +-
.../cutecalc/screens/SettingsScreen.kt | 34 +--
.../main/res/drawable/backspace_rounded.xml | 6 +-
app/src/main/res/drawable/history_rounded.xml | 6 +-
app/src/main/res/drawable/sort_rounded.xml | 6 +-
app/src/main/res/drawable/trash_rounded.xml | 6 +-
app/src/main/res/values-fr-rFR/strings.xml | 4 +
app/src/main/res/values/strings.xml | 2 +
24 files changed, 623 insertions(+), 441 deletions(-)
delete mode 100644 app/src/main/java/com/sosauce/cutecalc/AppBar.kt
create mode 100644 app/src/main/java/com/sosauce/cutecalc/components/CuteNavigationButton.kt
create mode 100644 app/src/main/java/com/sosauce/cutecalc/components/HistoryActionButtons.kt
create mode 100644 app/src/main/java/com/sosauce/cutecalc/components/LongClickButton.kt
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index e7d4805..df30a1c 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -13,8 +13,8 @@ android {
applicationId = "com.sosauce.cutecalc"
minSdk = 21
targetSdk = 35
- versionCode = 38
- versionName = "3.3.2"
+ versionCode = 39
+ versionName = "3.4.0"
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7cd9388..07ff196 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,7 +3,8 @@
xmlns:tools="http://schemas.android.com/tools">
-
+
diff --git a/app/src/main/java/com/sosauce/cutecalc/AppBar.kt b/app/src/main/java/com/sosauce/cutecalc/AppBar.kt
deleted file mode 100644
index 37cc187..0000000
--- a/app/src/main/java/com/sosauce/cutecalc/AppBar.kt
+++ /dev/null
@@ -1,157 +0,0 @@
-@file:OptIn(ExperimentalMaterial3Api::class)
-
-package com.sosauce.cutecalc
-
-import androidx.compose.foundation.background
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.automirrored.rounded.ArrowBack
-import androidx.compose.material.icons.rounded.Settings
-import androidx.compose.material3.DropdownMenu
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
-import androidx.compose.material3.TopAppBar
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
-import com.sosauce.cutecalc.logic.navigation.Screens
-import com.sosauce.cutecalc.logic.rememberSortHistoryASC
-import com.sosauce.cutecalc.ui.theme.GlobalFont
-import com.sosauce.cutecalc.utils.thenIf
-
-@Composable
-fun AppBar(
- title: @Composable () -> Unit = {},
- showBackArrow: Boolean,
- showSortButton: Boolean = false,
- onNavigate: (Screens) -> Unit,
-) {
- var dropDownExpanded by remember { mutableStateOf(false) }
- var sortASC by rememberSortHistoryASC()
- val surfaceContainer = MaterialTheme.colorScheme.surfaceContainer
-
-
- TopAppBar(
- title = title,
- navigationIcon = {
- if (showBackArrow) {
- IconButton(onClick = { onNavigate(Screens.MAIN) }) {
- Icon(
- imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
- contentDescription = "Back arrow"
- )
- }
- }
- },
- actions = {
- if (!showBackArrow) {
- Spacer(Modifier.width(5.dp))
- IconButton(onClick = { onNavigate(Screens.HISTORY) }) {
- Icon(
- painter = painterResource(R.drawable.history_rounded),
- contentDescription = stringResource(R.string.history),
- tint = MaterialTheme.colorScheme.onBackground
- )
- }
- IconButton(onClick = { onNavigate(Screens.SETTINGS) }) {
- Icon(
- imageVector = Icons.Rounded.Settings,
- contentDescription = stringResource(R.string.settings),
- tint = MaterialTheme.colorScheme.onBackground
- )
- }
- }
- if (showSortButton) {
- IconButton(
- onClick = { dropDownExpanded = true }
- ) {
- Icon(
- painter = painterResource(R.drawable.sort_rounded),
- contentDescription = null
- )
- }
- DropdownMenu(
- expanded = dropDownExpanded,
- onDismissRequest = { dropDownExpanded = false },
- modifier = Modifier
- .width(180.dp)
- .background(MaterialTheme.colorScheme.surface),
- shape = RoundedCornerShape(24.dp)
- ) {
- Column(
- verticalArrangement = Arrangement.Center
- ) {
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .height(56.dp)
- .padding(5.dp)
- .clip(RoundedCornerShape(12.dp))
- .clickable { sortASC = true }
- .thenIf(sortASC) {
- Modifier.background(
- color = surfaceContainer,
- shape = RoundedCornerShape(12.dp)
- )
- },
- verticalAlignment = Alignment.CenterVertically
- ) {
- Text(
- text = stringResource(R.string.ascending),
- fontFamily = GlobalFont,
- modifier = Modifier.padding(start = 15.dp)
- )
- }
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .height(56.dp)
- .padding(5.dp)
- .clip(RoundedCornerShape(12.dp))
- .clickable { sortASC = false }
- .thenIf(!sortASC) {
- Modifier.background(
- color = surfaceContainer,
- shape = RoundedCornerShape(12.dp)
- )
- },
- verticalAlignment = Alignment.CenterVertically
- ) {
- Text(
- text = stringResource(R.string.descending),
- fontFamily = GlobalFont,
- modifier = Modifier.padding(start = 15.dp)
- )
- }
- }
-
- }
- }
- }
- )
-}
-
-
-
-
-
diff --git a/app/src/main/java/com/sosauce/cutecalc/components/AboutCard.kt b/app/src/main/java/com/sosauce/cutecalc/components/AboutCard.kt
index 086e30f..8f8c424 100644
--- a/app/src/main/java/com/sosauce/cutecalc/components/AboutCard.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/components/AboutCard.kt
@@ -6,12 +6,12 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -22,7 +22,6 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.sosauce.cutecalc.R
-import com.sosauce.cutecalc.ui.theme.GlobalFont
import com.sosauce.cutecalc.utils.GITHUB_RELEASES
@Composable
@@ -35,6 +34,7 @@ fun AboutCard() {
Card(
colors = CardDefaults.cardColors(MaterialTheme.colorScheme.surfaceContainer),
modifier = Modifier
+ .statusBarsPadding()
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 2.dp),
shape = RoundedCornerShape(24.dp)
@@ -49,13 +49,9 @@ fun AboutCard() {
.clip(RoundedCornerShape(15))
)
Column {
- Text(
- text = stringResource(R.string.cc_by_sosauce),
- fontFamily = GlobalFont
- )
- Text(
+ CuteText(stringResource(R.string.cc_by_sosauce))
+ CuteText(
text = "${stringResource(R.string.version)} $version",
- fontFamily = GlobalFont,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.85f)
)
}
@@ -69,12 +65,7 @@ fun AboutCard() {
onClick = { uriHandler.openUri(GITHUB_RELEASES) },
shape = RoundedCornerShape(24.dp),
modifier = Modifier.fillMaxWidth()
- ) {
- Text(
- text = stringResource(R.string.update),
- fontFamily = GlobalFont
- )
- }
+ ) { CuteText(stringResource(R.string.update)) }
}
}
}
diff --git a/app/src/main/java/com/sosauce/cutecalc/components/CuteButton.kt b/app/src/main/java/com/sosauce/cutecalc/components/CuteButton.kt
index da9a52d..88a4763 100644
--- a/app/src/main/java/com/sosauce/cutecalc/components/CuteButton.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/components/CuteButton.kt
@@ -1,6 +1,9 @@
+@file:OptIn(ExperimentalFoundationApi::class)
+
package com.sosauce.cutecalc.components
import androidx.compose.animation.core.animateIntAsState
+import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.size
@@ -10,7 +13,6 @@ import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
@@ -24,15 +26,16 @@ import androidx.compose.ui.unit.sp
import com.sosauce.cutecalc.R
import com.sosauce.cutecalc.logic.rememberUseButtonsAnimation
import com.sosauce.cutecalc.logic.rememberVibration
-import com.sosauce.cutecalc.ui.theme.GlobalFont
@Composable
fun CuteButton(
modifier: Modifier = Modifier,
text: String,
color: ButtonColors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.surfaceContainer),
+
onClick: () -> Unit,
- textColor: Color = MaterialTheme.colorScheme.onBackground
+ textColor: Color = MaterialTheme.colorScheme.onBackground,
+ enabled: Boolean = true
) {
val shouldVibrate by rememberVibration()
val useButtonsAnimation by rememberUseButtonsAnimation()
@@ -52,21 +55,23 @@ fun CuteButton(
colors = color,
modifier = modifier,
shape = RoundedCornerShape(cornerRadius),
- interactionSource = interactionSource
+ interactionSource = interactionSource,
+ enabled = enabled
) {
- Text(
+ CuteText(
text = text,
color = textColor,
- fontSize = 35.sp,
- fontFamily = GlobalFont
+ fontSize = 35.sp
)
}
}
+@OptIn(ExperimentalFoundationApi::class)
@Composable
fun CuteIconButton(
modifier: Modifier,
onClick: () -> Unit,
+ onLongClick: () -> Unit = {},
color: ButtonColors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.surfaceContainer)
) {
val shouldVibrate by rememberVibration()
@@ -79,11 +84,16 @@ fun CuteIconButton(
targetValue = if (isPressed && useButtonsAnimation) 24 else 50, label = ""
)
- Button(
+
+ LongClickButton(
onClick = {
onClick()
if (shouldVibrate) haptic.performHapticFeedback(HapticFeedbackType.LongPress)
},
+ onLongClick = {
+ onLongClick()
+ if (shouldVibrate) haptic.performHapticFeedback(HapticFeedbackType.LongPress)
+ },
colors = color,
modifier = modifier,
shape = RoundedCornerShape(cornerRadius),
@@ -96,4 +106,11 @@ fun CuteIconButton(
modifier = Modifier.size(45.dp)
)
}
-}
\ No newline at end of file
+
+
+}
+
+
+
+
+
diff --git a/app/src/main/java/com/sosauce/cutecalc/components/CuteNavigationButton.kt b/app/src/main/java/com/sosauce/cutecalc/components/CuteNavigationButton.kt
new file mode 100644
index 0000000..9c41686
--- /dev/null
+++ b/app/src/main/java/com/sosauce/cutecalc/components/CuteNavigationButton.kt
@@ -0,0 +1,42 @@
+package com.sosauce.cutecalc.components
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.rounded.ArrowBack
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButtonDefaults
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedIconButton
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import com.sosauce.cutecalc.logic.navigation.Screens
+
+@Composable
+fun BoxScope.CuteNavigationButton(
+ onNavigate: (Screens) -> Unit
+) {
+ OutlinedIconButton(
+ onClick = { onNavigate(Screens.MAIN) },
+ modifier = Modifier
+ .padding(start = 15.dp)
+ .align(Alignment.BottomStart)
+ .navigationBarsPadding(),
+ colors = IconButtonDefaults.iconButtonColors(
+ containerColor = MaterialTheme.colorScheme.background,
+ ),
+ border = BorderStroke(
+ width = 1.dp,
+ color = MaterialTheme.colorScheme.onBackground.copy(0.2f)
+ )
+ ) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
+ contentDescription = null
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sosauce/cutecalc/components/HistoryActionButtons.kt b/app/src/main/java/com/sosauce/cutecalc/components/HistoryActionButtons.kt
new file mode 100644
index 0000000..960b924
--- /dev/null
+++ b/app/src/main/java/com/sosauce/cutecalc/components/HistoryActionButtons.kt
@@ -0,0 +1,107 @@
+package com.sosauce.cutecalc.components
+
+import androidx.compose.animation.AnimatedContent
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.rounded.Close
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.vector.rememberVectorPainter
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.sosauce.cutecalc.R
+import com.sosauce.cutecalc.logic.rememberSortHistoryASC
+import com.sosauce.cutecalc.utils.thenIf
+
+@Composable
+fun BoxScope.HistoryActionButtons(
+ onDeleteHistory: () -> Unit
+) {
+ var dropDownExpanded by remember { mutableStateOf(false) }
+ var sortASC by rememberSortHistoryASC()
+ val surfaceContainer = MaterialTheme.colorScheme.surfaceContainer
+ val sorting = remember {
+ listOf(
+ R.string.ascending,
+ R.string.descending
+ )
+ }
+
+ Row(
+ modifier = Modifier
+ .padding(end = 15.dp)
+ .align(Alignment.BottomEnd)
+ .clip(RoundedCornerShape(24.dp))
+ .border(
+ width = 1.dp,
+ color = MaterialTheme.colorScheme.onBackground.copy(0.2f),
+ shape = RoundedCornerShape(24.dp)
+ )
+ .navigationBarsPadding()
+ ) {
+ IconButton(
+ onClick = { dropDownExpanded = true }
+ ) {
+ AnimatedContent(
+ targetState = !dropDownExpanded
+ ) {
+ Icon(
+ painter = if (it) painterResource(R.drawable.sort_rounded) else rememberVectorPainter(
+ Icons.Rounded.Close
+ ),
+ contentDescription = null
+ )
+ }
+ }
+ IconButton(
+ onClick = onDeleteHistory
+ ) {
+ Icon(
+ painter = painterResource(R.drawable.trash_rounded),
+ contentDescription = null
+ )
+ }
+
+ DropdownMenu(
+ expanded = dropDownExpanded,
+ onDismissRequest = { dropDownExpanded = false },
+ modifier = Modifier
+ .background(MaterialTheme.colorScheme.surface),
+ shape = RoundedCornerShape(24.dp)
+ ) {
+ sorting.forEach {
+ DropdownMenuItem(
+ text = { CuteText(stringResource(it)) },
+ onClick = { sortASC = it == R.string.descending },
+ modifier = Modifier
+ .padding(5.dp)
+ .clip(RoundedCornerShape(12.dp))
+ .thenIf((!sortASC && it == R.string.ascending) || (sortASC && it == R.string.descending)) {
+ Modifier.background(
+ color = surfaceContainer,
+ shape = RoundedCornerShape(12.dp)
+ )
+ }
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sosauce/cutecalc/components/LongClickButton.kt b/app/src/main/java/com/sosauce/cutecalc/components/LongClickButton.kt
new file mode 100644
index 0000000..7f50d9c
--- /dev/null
+++ b/app/src/main/java/com/sosauce/cutecalc/components/LongClickButton.kt
@@ -0,0 +1,173 @@
+@file:OptIn(ExperimentalFoundationApi::class)
+
+package com.sosauce.cutecalc.components
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.combinedClickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.ButtonColors
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.ColorScheme
+import androidx.compose.material3.LocalAbsoluteTonalElevation
+import androidx.compose.material3.LocalContentColor
+import androidx.compose.material3.LocalTonalElevationEnabled
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.contentColorFor
+import androidx.compose.material3.minimumInteractiveComponentSize
+import androidx.compose.material3.surfaceColorAtElevation
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.NonRestartableComposable
+import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.RectangleShape
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.role
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import com.sosauce.cutecalc.utils.thenIf
+
+
+@Composable
+fun LongClickButton(
+ onClick: () -> Unit,
+ onLongClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ shape: Shape = ButtonDefaults.shape,
+ colors: ButtonColors = ButtonDefaults.buttonColors(),
+ border: BorderStroke? = null,
+ contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
+ interactionSource: MutableInteractionSource? = null,
+ content: @Composable RowScope.() -> Unit
+) {
+ @Suppress("NAME_SHADOWING")
+ val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
+
+ CustomSurface(
+ onClick = onClick,
+ onLongClick = onLongClick,
+ modifier = modifier.semantics { role = Role.Button },
+ enabled = enabled,
+ shape = shape,
+ color = colors.containerColor,
+ contentColor = colors.contentColor,
+ border = border,
+ interactionSource = interactionSource
+ ) {
+ Row(
+ Modifier
+ .defaultMinSize(
+ minWidth = ButtonDefaults.MinWidth,
+ minHeight = ButtonDefaults.MinHeight
+ )
+ .padding(contentPadding),
+ horizontalArrangement = Arrangement.Center,
+ verticalAlignment = Alignment.CenterVertically,
+ content = content
+ )
+ }
+}
+
+// The below code is just to create a long clickable button, thanks for all the "internal" Google :)
+@Composable
+@NonRestartableComposable
+private fun CustomSurface(
+ onClick: () -> Unit,
+ onLongClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ shape: Shape = RectangleShape,
+ color: Color = MaterialTheme.colorScheme.surface,
+ contentColor: Color = contentColorFor(color),
+ tonalElevation: Dp = 0.dp,
+ shadowElevation: Dp = 0.dp,
+ border: BorderStroke? = null,
+ interactionSource: MutableInteractionSource? = null,
+ content: @Composable () -> Unit
+) {
+ val absoluteElevation = LocalAbsoluteTonalElevation.current + tonalElevation
+ CompositionLocalProvider(
+ LocalContentColor provides contentColor,
+ LocalAbsoluteTonalElevation provides absoluteElevation
+ ) {
+ Box(
+ modifier =
+ modifier
+ .minimumInteractiveComponentSize()
+ .surface(
+ shape = shape,
+ backgroundColor =
+ surfaceColorAtElevation(color = color, elevation = absoluteElevation),
+ border = border,
+ shadowElevation = with(LocalDensity.current) { shadowElevation.toPx() }
+ )
+ .combinedClickable(
+ interactionSource = interactionSource,
+ indication = null,
+ enabled = enabled,
+ onClick = onClick,
+ onLongClick = onLongClick
+
+ ),
+ propagateMinConstraints = true
+ ) {
+ content()
+ }
+ }
+}
+
+@Stable
+private fun Modifier.surface(
+ shape: Shape,
+ backgroundColor: Color,
+ border: BorderStroke?,
+ shadowElevation: Float,
+) =
+
+ this
+ .thenIf(shadowElevation > 0f) {
+ Modifier.graphicsLayer(
+ shadowElevation = shadowElevation,
+ shape = shape,
+ clip = false
+ )
+ }
+ .then(if (border != null) Modifier.border(border, shape) else Modifier)
+ .background(color = backgroundColor, shape = shape)
+ .clip(shape)
+
+@Composable
+private fun surfaceColorAtElevation(color: Color, elevation: Dp): Color =
+ MaterialTheme.colorScheme.applyTonalElevation(color, elevation)
+
+
+@Composable
+@ReadOnlyComposable
+internal fun ColorScheme.applyTonalElevation(backgroundColor: Color, elevation: Dp): Color {
+ val tonalElevationEnabled = LocalTonalElevationEnabled.current
+ return if (backgroundColor == surface && tonalElevationEnabled) {
+ surfaceColorAtElevation(elevation)
+ } else {
+ backgroundColor
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sosauce/cutecalc/components/Switches.kt b/app/src/main/java/com/sosauce/cutecalc/components/Switches.kt
index 1937f86..d85d91f 100644
--- a/app/src/main/java/com/sosauce/cutecalc/components/Switches.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/components/Switches.kt
@@ -1,170 +1,164 @@
package com.sosauce.cutecalc.components
import androidx.compose.animation.AnimatedVisibility
-import androidx.compose.animation.fadeIn
-import androidx.compose.animation.fadeOut
-import androidx.compose.animation.slideInHorizontally
-import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.setValue
+import androidx.compose.runtime.MutableState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import com.sosauce.cutecalc.R
import com.sosauce.cutecalc.logic.rememberDecimal
import com.sosauce.cutecalc.logic.rememberFollowSys
+import com.sosauce.cutecalc.logic.rememberShowClearButton
import com.sosauce.cutecalc.logic.rememberUseAmoledMode
import com.sosauce.cutecalc.logic.rememberUseButtonsAnimation
import com.sosauce.cutecalc.logic.rememberUseDarkMode
import com.sosauce.cutecalc.logic.rememberUseHistory
import com.sosauce.cutecalc.logic.rememberUseSystemFont
import com.sosauce.cutecalc.logic.rememberVibration
-import com.sosauce.cutecalc.ui.theme.GlobalFont
-
+import kotlin.collections.component1
+import kotlin.collections.component2
+
+
+//@Composable
+//fun History() {
+// var enableHistory by rememberUseHistory()
+//
+// Column {
+// CuteText(
+// text = stringResource(R.string.history),
+// color = MaterialTheme.colorScheme.primary,
+// modifier = Modifier.padding(horizontal = 34.dp, vertical = 8.dp)
+// )
+//
+// SettingsCards(
+// checked = enableHistory,
+// onCheckedChange = { enableHistory = !enableHistory },
+// topDp = 24.dp,
+// bottomDp = 24.dp,
+// text = stringResource(R.string.use_history)
+// )
+// }
+//}
@Composable
-fun History() {
- var enableHistory by rememberUseHistory()
+fun UI() {
+ val settings = mapOf>(
+ R.string.buttons_anim to rememberUseButtonsAnimation(),
+ R.string.show_clear_button to rememberShowClearButton(),
+ R.string.use_sys_font to rememberUseSystemFont()
+ )
Column {
- Text(
- text = stringResource(R.string.history),
- fontFamily = GlobalFont,
+ CuteText(
+ text = "UI",
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(horizontal = 34.dp, vertical = 8.dp)
)
- SettingsCards(
- checked = enableHistory,
- onCheckedChange = { enableHistory = !enableHistory },
- topDp = 24.dp,
- bottomDp = 24.dp,
- text = stringResource(R.string.use_history)
- )
+ settings.onEachIndexed { index, (text, setting) ->
+ SettingsCards(
+ checked = setting.value,
+ onCheckedChange = { setting.value = !setting.value },
+ topDp = if (index == 0) 24.dp else 4.dp,
+ bottomDp = if (index == settings.size - 1) 24.dp else 4.dp,
+ text = stringResource(text),
+ optionalDescription = {
+ if (text == R.string.show_clear_button) {
+ CuteText(
+ text = stringResource(R.string.clear_button_desc),
+ color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.85f),
+ fontSize = 12.sp
+ )
+ }
+ }
+ )
+ }
}
}
@Composable
fun Misc() {
- var decimalSetting by rememberDecimal()
- var buttonVibrationSetting by rememberVibration()
- var useButtonsAnimation by rememberUseButtonsAnimation()
- var useSystemFont by rememberUseSystemFont()
-
+ val settings = mapOf>(
+ R.string.use_history to rememberUseHistory(),
+ R.string.decimal_formatting to rememberDecimal(),
+ R.string.haptic_feedback to rememberVibration(),
+ )
Column {
- Text(
+ CuteText(
text = stringResource(R.string.misc),
- fontFamily = GlobalFont,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(horizontal = 34.dp, vertical = 8.dp)
)
-
- SettingsCards(
- checked = decimalSetting,
- onCheckedChange = { decimalSetting = !decimalSetting },
- topDp = 24.dp,
- bottomDp = 4.dp,
- text = stringResource(R.string.decimal_formatting)
- )
- SettingsCards(
- checked = useSystemFont,
- onCheckedChange = { useSystemFont = !useSystemFont },
- topDp = 4.dp,
- bottomDp = 4.dp,
- text = stringResource(R.string.use_sys_font)
- )
- SettingsCards(
- checked = useButtonsAnimation,
- onCheckedChange = { useButtonsAnimation = !useButtonsAnimation },
- topDp = 4.dp,
- bottomDp = 4.dp,
- text = stringResource(R.string.buttons_anim)
- )
- SettingsCards(
- checked = buttonVibrationSetting,
- onCheckedChange = { buttonVibrationSetting = !buttonVibrationSetting },
- topDp = 4.dp,
- bottomDp = 24.dp,
- text = stringResource(R.string.haptic_feedback)
- )
+ settings.onEachIndexed { index, (text, setting) ->
+ SettingsCards(
+ checked = setting.value,
+ onCheckedChange = { setting.value = !setting.value },
+ topDp = if (index == 0) 24.dp else 4.dp,
+ bottomDp = if (index == settings.size - 1) 24.dp else 4.dp,
+ text = stringResource(text)
+ )
+ }
}
}
@Composable
fun ThemeManagement() {
- var darkMode by rememberUseDarkMode()
- var amoledMode by rememberUseAmoledMode()
- var followSys by rememberFollowSys()
+
+ val settings = mapOf>(
+ R.string.follow_sys to rememberFollowSys(),
+ R.string.dark_mode to rememberUseDarkMode(),
+ R.string.amoled_mode to rememberUseAmoledMode(),
+ )
+
Column {
- Text(
+ CuteText(
text = stringResource(R.string.theme),
- fontFamily = GlobalFont,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(horizontal = 34.dp, vertical = 8.dp)
)
- SettingsCards(
- checked = followSys,
- onCheckedChange = { followSys = !followSys },
- topDp = 24.dp,
- bottomDp = 4.dp,
- text = stringResource(R.string.follow_sys)
- )
- AnimatedVisibility(
- visible = !followSys,
- enter = slideInHorizontally() + fadeIn(),
- exit = slideOutHorizontally() + fadeOut()
- ) {
- SettingsCards(
- checked = darkMode,
- onCheckedChange = { darkMode = !darkMode },
- topDp = 4.dp,
- bottomDp = 4.dp,
- text = stringResource(R.string.dark_mode)
- )
+
+ settings.onEachIndexed { index, (text, setting) ->
+ AnimatedVisibility(
+ visible = text != R.string.dark_mode || !rememberFollowSys().value
+ ) {
+ SettingsCards(
+ checked = setting.value,
+ onCheckedChange = { setting.value = !setting.value },
+ topDp = if (index == 0) 24.dp else 4.dp,
+ bottomDp = if (index == settings.size - 1) 24.dp else 4.dp,
+ text = stringResource(text)
+ )
+ }
}
- SettingsCards(
- checked = amoledMode,
- onCheckedChange = { amoledMode = !amoledMode },
- topDp = 4.dp,
- bottomDp = 24.dp,
- text = stringResource(R.string.amoled_mode)
- )
}
}
@Composable
-private fun SettingsCards(
- hasInfoDialog: Boolean = false,
+fun SettingsCards(
checked: Boolean,
- onCheckedChange: () -> Unit,
- onClick: (() -> Unit)? = null,
topDp: Dp,
bottomDp: Dp,
- text: String
+ text: String,
+ onCheckedChange: () -> Unit,
+ optionalDescription: @Composable () -> Unit = {}
) {
Card(
colors = CardDefaults.cardColors(MaterialTheme.colorScheme.surfaceContainer),
modifier = Modifier
- .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 2.dp),
shape = RoundedCornerShape(
topStart = topDp,
@@ -178,22 +172,17 @@ private fun SettingsCards(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.padding(15.dp)
- .fillMaxWidth()
) {
- Row(verticalAlignment = Alignment.CenterVertically) {
- Text(
- text = text,
- fontFamily = GlobalFont
- )
- if (hasInfoDialog) {
- IconButton(
- onClick = { onClick?.invoke() }
- ) {
- Icon(
- imageVector = Icons.Outlined.Info,
- contentDescription = "Info Button"
- )
- }
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .weight(1f)
+ ) {
+ Column {
+ CuteText(
+ text = text
+ )
+ optionalDescription()
}
}
Switch(
diff --git a/app/src/main/java/com/sosauce/cutecalc/history/HistoryViewModel.kt b/app/src/main/java/com/sosauce/cutecalc/history/HistoryViewModel.kt
index 05606a4..369f5c0 100644
--- a/app/src/main/java/com/sosauce/cutecalc/history/HistoryViewModel.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/history/HistoryViewModel.kt
@@ -28,7 +28,7 @@ class HistoryViewModel(
is HistoryEvents.AddCalculation -> {
// Only save to history calculations that are not any kind of errors
- if (state.value.result.value.all { it.isDigit() || it == '.' || it == '-' || it == ','}) {
+ if (state.value.result.value.all { it.isDigit() || it == '.' || it == '-' || it == ',' }) {
val calculation = Calculation(
operation = state.value.operation.value,
result = state.value.result.value
diff --git a/app/src/main/java/com/sosauce/cutecalc/logic/CalculatorViewModel.kt b/app/src/main/java/com/sosauce/cutecalc/logic/CalculatorViewModel.kt
index 4d8a664..f72569b 100644
--- a/app/src/main/java/com/sosauce/cutecalc/logic/CalculatorViewModel.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/logic/CalculatorViewModel.kt
@@ -10,19 +10,18 @@ import androidx.compose.ui.text.input.getSelectedText
import androidx.compose.ui.text.input.getTextAfterSelection
import androidx.compose.ui.text.input.getTextBeforeSelection
import androidx.lifecycle.ViewModel
+import kotlin.text.all
class CalcViewModel : ViewModel() {
var displayText by mutableStateOf(TextFieldValue(""))
- private val processedText by derivedStateOf {
- displayText.text.replace("π", "PI")
- }
val preview by derivedStateOf {
- when (displayText) {
- TextFieldValue("") -> ""
- else -> "= ${Evaluator.eval(processedText)}"
- }
+ val evaluatedText = Evaluator.eval(displayText.text.replace("π", "PI"))
+
+ if (evaluatedText.all { it.isDigit() || it == '.' || it == '-' || it == ',' }) {
+ "= $evaluatedText"
+ } else ""
}
val parenthesis by derivedStateOf {
if (displayText.text.count { it == '(' } > displayText.text.count { it == ')' }) ")" else "("
diff --git a/app/src/main/java/com/sosauce/cutecalc/logic/Evaluator.kt b/app/src/main/java/com/sosauce/cutecalc/logic/Evaluator.kt
index 8fbd67f..b7b6e2e 100644
--- a/app/src/main/java/com/sosauce/cutecalc/logic/Evaluator.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/logic/Evaluator.kt
@@ -94,7 +94,7 @@ object Evaluator {
@JvmStatic
fun eval(formula: String): String = try {
- val result = KEVAL.eval(formula)
+ val result = KEVAL.eval(formula.calculateRelativePercentage())
if (result > Double.MAX_VALUE) {
throw ValueTooLargeException()
} else {
@@ -110,4 +110,23 @@ object Evaluator {
"Error"
}
+ fun String.calculateRelativePercentage(): String {
+ val regex = Regex("""(\d+(?:\.\d+)?)\s*([+\-*])\s*(\d+(?:\.\d+)?)%""")
+
+ return regex.replace(this) { match ->
+ val firstOperand = match.groupValues[1].toDouble()
+ val operator = match.groupValues[2]
+ val percentage = match.groupValues[3].toDouble()
+
+ when (operator) {
+ "+" -> "$firstOperand + ($firstOperand * $percentage / 100)"
+ "-" -> "$firstOperand - ($firstOperand * $percentage / 100)"
+ "*" -> "$firstOperand * ($percentage / 100)"
+ else -> "$firstOperand"
+ }
+
+ }
+ }
+
+
}
diff --git a/app/src/main/java/com/sosauce/cutecalc/logic/Settings.kt b/app/src/main/java/com/sosauce/cutecalc/logic/Settings.kt
index ecb0dbc..c0dd929 100644
--- a/app/src/main/java/com/sosauce/cutecalc/logic/Settings.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/logic/Settings.kt
@@ -20,6 +20,7 @@ data object PreferencesKeys {
val SORT_HISTORY_ASC = booleanPreferencesKey("sort_history_asc")
val USE_BUTTONS_ANIMATIONS = booleanPreferencesKey("use_buttons_animation")
val USE_SYSTEM_FONT = booleanPreferencesKey("use_system_font")
+ val SHOW_CLEAR_BUTTON = booleanPreferencesKey("show_clear_button")
}
@Composable
@@ -58,3 +59,7 @@ fun rememberUseButtonsAnimation() =
fun rememberUseSystemFont() =
rememberPreference(key = PreferencesKeys.USE_SYSTEM_FONT, defaultValue = false)
+@Composable
+fun rememberShowClearButton() =
+ rememberPreference(key = PreferencesKeys.SHOW_CLEAR_BUTTON, defaultValue = true)
+
diff --git a/app/src/main/java/com/sosauce/cutecalc/logic/navigation/Navigation.kt b/app/src/main/java/com/sosauce/cutecalc/logic/navigation/Navigation.kt
index 852794f..024d25d 100644
--- a/app/src/main/java/com/sosauce/cutecalc/logic/navigation/Navigation.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/logic/navigation/Navigation.kt
@@ -1,6 +1,7 @@
package com.sosauce.cutecalc.logic.navigation
import androidx.activity.compose.BackHandler
+import androidx.activity.compose.LocalActivity
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
@@ -10,10 +11,8 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
-import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
-import com.sosauce.cutecalc.MainActivity
import com.sosauce.cutecalc.history.HistoryViewModel
import com.sosauce.cutecalc.logic.CalcViewModel
import com.sosauce.cutecalc.screens.CalculatorUI
@@ -27,7 +26,7 @@ import com.sosauce.cutecalc.screens.SettingsScreen
fun Nav(historyViewModel: HistoryViewModel) {
- val activity = (LocalContext.current as MainActivity)
+ val activity = LocalActivity.current
var screenToDisplay by rememberSaveable { mutableStateOf(Screens.MAIN) }
val viewModel = viewModel()
val historyState by historyViewModel.state.collectAsStateWithLifecycle()
@@ -38,7 +37,7 @@ fun Nav(historyViewModel: HistoryViewModel) {
if (screenToDisplay != Screens.MAIN) {
screenToDisplay = Screens.MAIN
} else {
- activity.moveTaskToBack(true)
+ activity?.moveTaskToBack(true)
}
}
diff --git a/app/src/main/java/com/sosauce/cutecalc/screens/Calculator.kt b/app/src/main/java/com/sosauce/cutecalc/screens/Calculator.kt
index c7f008a..1d2e682 100644
--- a/app/src/main/java/com/sosauce/cutecalc/screens/Calculator.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/screens/Calculator.kt
@@ -1,8 +1,9 @@
+@file:OptIn(ExperimentalMaterial3Api::class)
+
package com.sosauce.cutecalc.screens
import android.annotation.SuppressLint
import android.content.res.Configuration
-import android.widget.EditText
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -15,9 +16,15 @@ import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.rounded.Settings
import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
+import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
@@ -28,17 +35,16 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.InterceptPlatformTextInput
import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import androidx.compose.ui.viewinterop.AndroidView
-import androidx.core.content.res.ResourcesCompat
-import com.sosauce.cutecalc.AppBar
import com.sosauce.cutecalc.R
import com.sosauce.cutecalc.components.CuteButton
import com.sosauce.cutecalc.components.CuteIconButton
+import com.sosauce.cutecalc.components.CuteText
import com.sosauce.cutecalc.history.HistoryEvents
import com.sosauce.cutecalc.history.HistoryState
import com.sosauce.cutecalc.history.HistoryViewModel
@@ -48,8 +54,11 @@ import com.sosauce.cutecalc.logic.Evaluator
import com.sosauce.cutecalc.logic.formatOrNot
import com.sosauce.cutecalc.logic.navigation.Screens
import com.sosauce.cutecalc.logic.rememberDecimal
+import com.sosauce.cutecalc.logic.rememberShowClearButton
import com.sosauce.cutecalc.logic.rememberUseHistory
+import com.sosauce.cutecalc.logic.rememberUseSystemFont
import com.sosauce.cutecalc.ui.theme.GlobalFont
+import kotlinx.coroutines.awaitCancellation
@SuppressLint("NewApi")
@@ -63,13 +72,19 @@ fun CalculatorUI(
val config = LocalConfiguration.current
val portraitMode by remember { mutableIntStateOf(config.orientation) }
val saveToHistory by rememberUseHistory()
+ val useSystemFont by rememberUseSystemFont()
+ val showClearButton by rememberShowClearButton()
val firstRow = listOf("!", "%", "√", "π")
- val secondRow = listOf("C", viewModel.parenthesis, "^", "/")
+ val secondRow = listOf(
+ if (showClearButton) "C" else "(",
+ if (showClearButton) viewModel.parenthesis else ")",
+ "^",
+ "/"
+ )
val thirdRow = listOf("7", "8", "9", "×")
val fourthRow = listOf("4", "5", "6", "-")
val fifthRow = listOf("1", "2", "3", "+")
val sixthRow = listOf("0", ".")
- val textColor = MaterialTheme.colorScheme.onBackground
val decimalSetting by rememberDecimal()
@@ -84,9 +99,24 @@ fun CalculatorUI(
Scaffold(
topBar = {
- AppBar(
- showBackArrow = false,
- onNavigate = { onNavigate(it) }
+ TopAppBar(
+ title = {},
+ actions = {
+ IconButton(onClick = { onNavigate(Screens.HISTORY) }) {
+ Icon(
+ painter = painterResource(R.drawable.history_rounded),
+ contentDescription = stringResource(R.string.history),
+ tint = MaterialTheme.colorScheme.onBackground
+ )
+ }
+ IconButton(onClick = { onNavigate(Screens.SETTINGS) }) {
+ Icon(
+ imageVector = Icons.Rounded.Settings,
+ contentDescription = stringResource(R.string.settings),
+ tint = MaterialTheme.colorScheme.onBackground
+ )
+ }
+ }
)
}
) { pv ->
@@ -111,25 +141,10 @@ fun CalculatorUI(
.align(Alignment.End)
.horizontalScroll(rememberScrollState())
) {
- AndroidView(
- factory = { context ->
- EditText(context).apply {
- isFocusable = false
- isFocusableInTouchMode = false
- isSingleLine = true
- showSoftInputOnFocus = false
- textSize = 32f
- maxLines = 1
- background = null
- setTextColor(textColor.copy(0.7f).hashCode())
- setTypeface(ResourcesCompat.getFont(context, R.font.nunito))
- }
- },
- update = { view ->
- view.setText(formatOrNot(viewModel.preview, decimalSetting))
- // Added decimal points and comma need to be taken account for !
- view.setSelection(formatOrNot(viewModel.preview, decimalSetting).length)
- }
+ CuteText(
+ text = formatOrNot(viewModel.preview, decimalSetting),
+ fontSize = 32.sp,
+ color = MaterialTheme.colorScheme.onBackground.copy(0.85f)
)
}
Row(
@@ -138,17 +153,23 @@ fun CalculatorUI(
) {
DisableSoftKeyboard {
BasicTextField(
- value = TextFieldValue(formatOrNot(viewModel.displayText.text, decimalSetting)),
+ value = viewModel.displayText.copy(
+ text = formatOrNot(
+ viewModel.displayText.text,
+ decimalSetting
+ )
+ ), // Use copy function to keep the correct range, or else the cursor will just stick to the start everytime
onValueChange = { viewModel.displayText = it },
singleLine = true,
textStyle = TextStyle(
textAlign = TextAlign.End,
color = MaterialTheme.colorScheme.onBackground,
fontSize = 53.sp,
- fontFamily = GlobalFont
+ fontFamily = if (!useSystemFont) GlobalFont else null
),
cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground),
)
+
}
}
Row(
@@ -290,6 +311,9 @@ fun CalculatorUI(
.weight(1f),
onClick = {
viewModel.handleAction(CalcAction.Backspace)
+ },
+ onLongClick = {
+ viewModel.handleAction(CalcAction.ResetField)
}
)
CuteButton(
@@ -324,11 +348,18 @@ fun CalculatorUI(
// https://stackoverflow.com/a/78720287
@OptIn(ExperimentalComposeUiApi::class)
@Composable
-fun DisableSoftKeyboard(content: @Composable () -> Unit) {
+fun DisableSoftKeyboard(
+ disable: Boolean = true,
+ content: @Composable () -> Unit,
+) {
InterceptPlatformTextInput(
interceptor = { request, nextHandler ->
- nextHandler.startInputMethod(request)
+ if (!disable) {
+ nextHandler.startInputMethod(request)
+ } else {
+ awaitCancellation()
+ }
},
- content = content
+ content = content,
)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/sosauce/cutecalc/screens/HistoryScreen.kt b/app/src/main/java/com/sosauce/cutecalc/screens/HistoryScreen.kt
index e94fc24..a8650ad 100644
--- a/app/src/main/java/com/sosauce/cutecalc/screens/HistoryScreen.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/screens/HistoryScreen.kt
@@ -2,6 +2,7 @@ package com.sosauce.cutecalc.screens
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -9,19 +10,18 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
-import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Scaffold
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
@@ -34,8 +34,10 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import com.sosauce.cutecalc.AppBar
import com.sosauce.cutecalc.R
+import com.sosauce.cutecalc.components.CuteNavigationButton
+import com.sosauce.cutecalc.components.CuteText
+import com.sosauce.cutecalc.components.HistoryActionButtons
import com.sosauce.cutecalc.history.Calculation
import com.sosauce.cutecalc.history.HistoryEvents
import com.sosauce.cutecalc.history.HistoryState
@@ -44,7 +46,7 @@ import com.sosauce.cutecalc.logic.navigation.Screens
import com.sosauce.cutecalc.logic.rememberDecimal
import com.sosauce.cutecalc.logic.rememberSortHistoryASC
import com.sosauce.cutecalc.logic.rememberUseHistory
-import com.sosauce.cutecalc.ui.theme.GlobalFont
+import com.sosauce.cutecalc.utils.thenIf
@Composable
fun HistoryScreen(
@@ -64,33 +66,11 @@ fun HistoryScreen(
}
}
- Scaffold(
- topBar = {
- AppBar(
- showBackArrow = true,
- showSortButton = true,
- onNavigate = onNavigate,
- title = {
- Text(
- text = stringResource(R.string.history),
- fontFamily = GlobalFont
- )
- }
- )
- },
- floatingActionButton = {
- if (isHistoryEnable) {
- FloatingActionButton(
- onClick = { onEvents(HistoryEvents.DeleteAllCalculation(state.calculation)) }
- ) {
- Icon(
- painter = painterResource(R.drawable.trash_rounded),
- contentDescription = null
- )
- }
- }
- }
- ) { values ->
+ LaunchedEffect(Unit) {
+ println("history size: ${sortedCalculations.size}")
+ }
+
+ Box(Modifier.fillMaxSize()) {
if (!isHistoryEnable) {
Column(
modifier = Modifier
@@ -98,26 +78,16 @@ fun HistoryScreen(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
- Text(
- text = stringResource(R.string.history_not_enabled),
- fontFamily = GlobalFont
- )
+ CuteText(stringResource(R.string.history_not_enabled))
Spacer(Modifier.height(10.dp))
Button(
onClick = { isHistoryEnable = !isHistoryEnable }
) {
- Text(
- text = stringResource(R.string.enable_history),
- fontFamily = GlobalFont
- )
+ CuteText(stringResource(R.string.enable_history))
}
}
} else {
- LazyColumn(
- modifier = Modifier
- .fillMaxSize()
- .padding(values)
- ) {
+ LazyColumn {
itemsIndexed(
items = sortedCalculations,
key = { _, item -> item.id }
@@ -127,11 +97,17 @@ fun HistoryScreen(
onEvents = onEvents,
topDp = if (index == 0) 24.dp else 4.dp,
bottomDp = if (index == state.calculation.size - 1) 24.dp else 4.dp,
- modifier = Modifier.animateItem()
+ modifier = Modifier
+ .animateItem()
+ .thenIf(index == 0) { Modifier.statusBarsPadding() }
)
}
}
}
+
+ CuteNavigationButton { onNavigate(it) }
+ HistoryActionButtons { onEvents(HistoryEvents.DeleteAllCalculation(state.calculation)) }
+
}
}
@@ -172,18 +148,16 @@ private fun CalculationItem(
.weight(1f),
horizontalAlignment = Alignment.Start
) {
- Text(
+ CuteText(
text = formatOrNot(calculation.operation, decimalSetting),
fontSize = 20.sp,
- modifier = Modifier.basicMarquee(),
- fontFamily = GlobalFont
+ modifier = Modifier.basicMarquee()
)
- Text(
+ CuteText(
text = "= ${formatOrNot(calculation.result, decimalSetting)}",
fontSize = 22.sp,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f),
- modifier = Modifier.basicMarquee(),
- fontFamily = GlobalFont
+ modifier = Modifier.basicMarquee()
)
}
IconButton(
diff --git a/app/src/main/java/com/sosauce/cutecalc/screens/LandscapeLayout.kt b/app/src/main/java/com/sosauce/cutecalc/screens/LandscapeLayout.kt
index 3b8a793..00ac283 100644
--- a/app/src/main/java/com/sosauce/cutecalc/screens/LandscapeLayout.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/screens/LandscapeLayout.kt
@@ -21,9 +21,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -71,7 +71,12 @@ fun LandscapeLayout(
) {
DisableSoftKeyboard {
BasicTextField(
- value = TextFieldValue(formatOrNot(viewModel.displayText.text, decimalSetting)),
+ value = viewModel.displayText.copy(
+ text = formatOrNot(
+ viewModel.displayText.text,
+ decimalSetting
+ )
+ ),
onValueChange = { viewModel.displayText = it },
singleLine = true,
textStyle = TextStyle(
@@ -135,10 +140,11 @@ fun LandscapeLayout(
) {
CuteButton(
text = "",
- color = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.background),
+ color = ButtonDefaults.buttonColors(disabledContainerColor = Color.Transparent),
modifier = Modifier
.weight(0.15f),
- onClick = {}
+ onClick = {},
+ enabled = false
)
CuteButton(
text = "9",
@@ -167,7 +173,6 @@ fun LandscapeLayout(
CuteButton(
text = "×",
color = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.secondaryContainer),
-
modifier = Modifier
.weight(0.15f),
onClick = {
@@ -252,6 +257,7 @@ fun LandscapeLayout(
modifier = Modifier
.weight(0.15f),
onClick = { viewModel.handleAction(CalcAction.Backspace) },
+ onLongClick = { viewModel.handleAction(CalcAction.ResetField) },
color = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.inversePrimary)
)
}
@@ -296,7 +302,6 @@ fun LandscapeLayout(
CuteButton(
text = "-",
color = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.secondaryContainer),
-
modifier = Modifier
.weight(0.15f),
onClick = {
diff --git a/app/src/main/java/com/sosauce/cutecalc/screens/SettingsScreen.kt b/app/src/main/java/com/sosauce/cutecalc/screens/SettingsScreen.kt
index e8771ca..d4a2c5f 100644
--- a/app/src/main/java/com/sosauce/cutecalc/screens/SettingsScreen.kt
+++ b/app/src/main/java/com/sosauce/cutecalc/screens/SettingsScreen.kt
@@ -1,56 +1,36 @@
package com.sosauce.cutecalc.screens
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
-import androidx.compose.material3.Scaffold
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.stringResource
-import com.sosauce.cutecalc.AppBar
-import com.sosauce.cutecalc.R
import com.sosauce.cutecalc.components.AboutCard
-import com.sosauce.cutecalc.components.History
+import com.sosauce.cutecalc.components.CuteNavigationButton
import com.sosauce.cutecalc.components.Misc
import com.sosauce.cutecalc.components.ThemeManagement
+import com.sosauce.cutecalc.components.UI
import com.sosauce.cutecalc.logic.navigation.Screens
-import com.sosauce.cutecalc.ui.theme.GlobalFont
@Composable
fun SettingsScreen(
onNavigate: (Screens) -> Unit
) {
-
- Scaffold(
- topBar = {
- AppBar(
- showBackArrow = true,
- onNavigate = onNavigate,
- title = {
- Text(
- text = stringResource(R.string.settings),
- fontFamily = GlobalFont
- )
- }
- )
- },
- ) { values ->
+ Box(Modifier.fillMaxSize()) {
Column(
modifier = Modifier
.fillMaxSize()
- .verticalScroll(rememberScrollState())
- .padding(values),
+ .verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
AboutCard()
ThemeManagement()
- History()
+ UI()
Misc()
}
+ CuteNavigationButton { onNavigate(it) }
}
-
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/backspace_rounded.xml b/app/src/main/res/drawable/backspace_rounded.xml
index 224741e..f909c4b 100644
--- a/app/src/main/res/drawable/backspace_rounded.xml
+++ b/app/src/main/res/drawable/backspace_rounded.xml
@@ -5,7 +5,7 @@
android:viewportHeight="960"
android:tint="@android:color/white"
android:autoMirrored="true">
-
+
diff --git a/app/src/main/res/drawable/history_rounded.xml b/app/src/main/res/drawable/history_rounded.xml
index dd93132..8dd36aa 100644
--- a/app/src/main/res/drawable/history_rounded.xml
+++ b/app/src/main/res/drawable/history_rounded.xml
@@ -4,7 +4,7 @@
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="@android:color/white">
-
+
diff --git a/app/src/main/res/drawable/sort_rounded.xml b/app/src/main/res/drawable/sort_rounded.xml
index 3975ce1..4b8c1f1 100644
--- a/app/src/main/res/drawable/sort_rounded.xml
+++ b/app/src/main/res/drawable/sort_rounded.xml
@@ -5,7 +5,7 @@
android:viewportHeight="960"
android:tint="@android:color/white"
android:autoMirrored="true">
-
+
diff --git a/app/src/main/res/drawable/trash_rounded.xml b/app/src/main/res/drawable/trash_rounded.xml
index 32eb5e2..75d0564 100644
--- a/app/src/main/res/drawable/trash_rounded.xml
+++ b/app/src/main/res/drawable/trash_rounded.xml
@@ -4,7 +4,7 @@
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="@android:color/white">
-
+
diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml
index 2286e8d..afd5abb 100644
--- a/app/src/main/res/values-fr-rFR/strings.xml
+++ b/app/src/main/res/values-fr-rFR/strings.xml
@@ -8,6 +8,7 @@
Mettre à jour
CuteCalc par sosauce
Suivre le système
+ Utiliser la police système
Animation des buttons
Historique
Utiliser l\'historique
@@ -17,4 +18,7 @@
Vibrations
Ascendant
Descendant
+ Format décimal
+ Afficher le button effacer
+ Vous pouvez toujours rester appuyer sur le button d\'effacement arrière pour effacer le champs de calcul.
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b8580ee..ba86a60 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -19,4 +19,6 @@
Ascending
Descending
Decimal formatting
+ Show clear button
+ You can still long press the backspace button to clear the input field.
\ No newline at end of file