Flex keyboards:

- Switched to FlowRow
- Calculating keypad button sizes only once
- Improved responsive design
- Overall decreased GPU usage by 10-20%
- Returned a bug with wide delete button (very sad)

closes: #131
This commit is contained in:
Sad Ellie 2023-11-21 17:34:02 +03:00
parent 9610b5bc38
commit 1def59bca5
10 changed files with 654 additions and 533 deletions

View File

@ -78,6 +78,7 @@ internal fun Project.configureKotlinAndroid(
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api", "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi", "-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
"-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi",
"-opt-in=androidx.compose.ui.unit.ExperimentalUnitApi", "-opt-in=androidx.compose.ui.unit.ExperimentalUnitApi",
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
) )

View File

@ -33,7 +33,6 @@ import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import com.sadellie.unitto.core.ui.isPortrait
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Composable @Composable
@ -83,7 +82,7 @@ fun KeyboardButtonLight(
modifier: Modifier, modifier: Modifier,
icon: ImageVector, icon: ImageVector,
allowVibration: Boolean, allowVibration: Boolean,
contentHeight: Float = if (isPortrait()) 0.578f else 0.793f, contentHeight: Float,
onLongClick: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null,
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
@ -104,7 +103,7 @@ fun KeyboardButtonFilled(
modifier: Modifier, modifier: Modifier,
icon: ImageVector, icon: ImageVector,
allowVibration: Boolean, allowVibration: Boolean,
contentHeight: Float = if (isPortrait()) 0.578f else 0.793f, contentHeight: Float,
onLongClick: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null,
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
@ -125,7 +124,7 @@ fun KeyboardButtonAdditional(
modifier: Modifier, modifier: Modifier,
icon: ImageVector, icon: ImageVector,
allowVibration: Boolean, allowVibration: Boolean,
contentHeight: Float = 0.906f, contentHeight: Float,
onLongClick: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null,
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
@ -146,7 +145,7 @@ fun KeyboardButtonTertiary(
modifier: Modifier, modifier: Modifier,
icon: ImageVector, icon: ImageVector,
allowVibration: Boolean, allowVibration: Boolean,
contentHeight: Float = if (isPortrait()) 0.578f else 0.793f, contentHeight: Float,
onLongClick: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null,
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
@ -161,3 +160,18 @@ fun KeyboardButtonTertiary(
allowVibration = allowVibration, allowVibration = allowVibration,
) )
} }
/**
* Mostly for main button in portrait mode. Changes icon size inside.
*/
const val KeyboardButtonContentHeightTall = 0.578f
/**
* Mostly for main button in landscape mode. Changes icon size inside.
*/
const val KeyboardButtonContentHeightShort = 0.793f
/**
* Mostly for additional buttons. Changes icon size inside.
*/
const val KeyboardButtonContentHeightWide = 0.906f

View File

@ -0,0 +1,63 @@
/*
* Unitto is a unit converter for Android
* Copyright (c) 2023 Elshan Agaev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sadellie.unitto.core.ui.common
import androidx.annotation.IntRange
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.FlowRowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
/**
* Keypad layout for buttons. Uses [FlowRow].
*
* @param modifier [Modifier] that will be applied to [FlowRow].
* @param rows Amount of rows. Vertical size.
* @param columns Amount of columns. Horizontal size.
* @param verticalPadding Percentage. How much space of button height is gonna be a padding.
* @param horizontalPadding Percentage. How much space of button width is gonna be a padding.
* @param content Content, usually some buttons. Use `width` and `height` in [fillMaxWidth]
* and [fillMaxHeight] to build a [Modifier]. Passed [Composable]s are equally distributed, occupy
* entire height and width.
*/
@Composable
fun KeypadFlow(
modifier: Modifier,
rows: Int,
columns: Int,
@IntRange(0, 100) verticalPadding: Int = 10,
@IntRange(0, 100) horizontalPadding: Int = 10,
content: @Composable FlowRowScope.(width: Float, height: Float) -> Unit
) {
val height: Float = remember { (1f - verticalPadding / 100f) / rows }
val width: Float = remember { (1f - horizontalPadding / 100f) / columns }
FlowRow(
modifier = modifier,
maxItemsInEachRow = columns,
horizontalArrangement = Arrangement.SpaceAround,
verticalArrangement = Arrangement.SpaceAround
) {
content(width, height)
}
}

View File

@ -18,21 +18,26 @@
package com.sadellie.unitto.feature.calculator package com.sadellie.unitto.feature.calculator
import androidx.compose.foundation.layout.Arrangement import android.content.res.Configuration
import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import com.sadellie.unitto.core.base.Token import com.sadellie.unitto.core.base.Token
import com.sadellie.unitto.core.ui.common.KeyboardButtonAdditional 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.KeyboardButtonContentHeightWide
import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled
import com.sadellie.unitto.core.ui.common.KeyboardButtonLight import com.sadellie.unitto.core.ui.common.KeyboardButtonLight
import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary
import com.sadellie.unitto.core.ui.common.KeypadFlow
import com.sadellie.unitto.core.ui.common.key.UnittoIcons 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.Backspace
import com.sadellie.unitto.core.ui.common.key.unittoicons.Clear import com.sadellie.unitto.core.ui.common.key.unittoicons.Clear
@ -61,7 +66,6 @@ import com.sadellie.unitto.core.ui.common.key.unittoicons.Unary
import com.sadellie.unitto.core.ui.common.key.unittoicons.Up import com.sadellie.unitto.core.ui.common.key.unittoicons.Up
import io.github.sadellie.evaluatto.RPNCalculation import io.github.sadellie.evaluatto.RPNCalculation
@OptIn(ExperimentalLayoutApi::class)
@Composable @Composable
internal fun RPNCalculatorKeyboard( internal fun RPNCalculatorKeyboard(
modifier: Modifier, modifier: Modifier,
@ -73,69 +77,151 @@ internal fun RPNCalculatorKeyboard(
) { ) {
val fractionalIcon = remember(fractional) { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma } val fractionalIcon = remember(fractional) { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma }
val columns = 4 if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT) {
val mainButtonRows = 5f RPNCalculatorKeyboardPortrait(
val additionalButtonRows = 1f modifier = modifier,
val additionalButtonRowFactor = 0.7f // How much smaller are the additional buttons than the main buttons fractionalIcon = fractionalIcon,
val additionalButtonIconHeight = 0.65f middleZero = middleZero,
val fillFactor = 0.92f allowVibration = allowVibration,
onCalculationClick = onCalculationClick,
onInputEditClick = onInputEditClick
)
} else {
RPNCalculatorKeyboardLandscape(
modifier = modifier,
fractionalIcon = fractionalIcon,
middleZero = middleZero,
allowVibration = allowVibration,
onCalculationClick = onCalculationClick,
onInputEditClick = onInputEditClick
)
}
}
val rows = remember { mainButtonRows + additionalButtonRows * additionalButtonRowFactor } @Composable
val height = remember { fillFactor / rows } private fun RPNCalculatorKeyboardPortrait(
val width = remember { fillFactor / columns } modifier: Modifier,
fractionalIcon: ImageVector,
FlowRow( middleZero: Boolean,
maxItemsInEachRow = columns, allowVibration: Boolean,
modifier = modifier, onCalculationClick: (RPNCalculation) -> Unit,
horizontalArrangement = Arrangement.SpaceAround, onInputEditClick: (RPNInputEdit) -> Unit,
verticalArrangement = Arrangement.SpaceAround ) {
Column(
modifier = modifier
) { ) {
val aModifier = Modifier KeypadFlow(
.fillMaxHeight(height * additionalButtonRowFactor) modifier = Modifier.fillMaxHeight(0.1f).fillMaxWidth(),
.fillMaxWidth(width) rows = 1,
columns = 4
) { width, height ->
val aModifier = Modifier
.fillMaxHeight(height)
.fillMaxWidth(width)
KeyboardButtonAdditional(aModifier, UnittoIcons.Swap, allowVibration, KeyboardButtonContentHeightWide) { onCalculationClick(RPNCalculation.Swap) }
KeyboardButtonAdditional(aModifier, UnittoIcons.Up, allowVibration, KeyboardButtonContentHeightWide) { onCalculationClick(RPNCalculation.RotateUp) }
KeyboardButtonAdditional(aModifier, UnittoIcons.Down, allowVibration, KeyboardButtonContentHeightWide) { onCalculationClick(RPNCalculation.RotateDown) }
KeyboardButtonAdditional(aModifier, UnittoIcons.Pop, allowVibration, KeyboardButtonContentHeightWide) { onCalculationClick(RPNCalculation.Pop) }
}
KeypadFlow(
modifier = Modifier.weight(1f).fillMaxSize(),
rows = 5,
columns = 4
) { width, height ->
val bModifier = Modifier
.fillMaxHeight(height)
.fillMaxWidth(width)
KeyboardButtonTertiary(bModifier, UnittoIcons.Clear, allowVibration, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Clear) }
KeyboardButtonFilled(bModifier, UnittoIcons.Unary, allowVibration, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Negate) }
KeyboardButtonFilled(bModifier, UnittoIcons.Percent, allowVibration, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Percent) }
KeyboardButtonFilled(bModifier, UnittoIcons.Divide, allowVibration, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Divide) }
KeyboardButtonLight(bModifier, UnittoIcons.Key7, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._7)) }
KeyboardButtonLight(bModifier, UnittoIcons.Key8, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._8)) }
KeyboardButtonLight(bModifier, UnittoIcons.Key9, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._9)) }
KeyboardButtonFilled(bModifier, UnittoIcons.Multiply, allowVibration, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Multiply) }
KeyboardButtonLight(bModifier, UnittoIcons.Key4, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._4)) }
KeyboardButtonLight(bModifier, UnittoIcons.Key5, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._5)) }
KeyboardButtonLight(bModifier, UnittoIcons.Key6, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._6)) }
KeyboardButtonFilled(bModifier, UnittoIcons.Minus, allowVibration, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Minus) }
KeyboardButtonLight(bModifier, UnittoIcons.Key1, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._1)) }
KeyboardButtonLight(bModifier, UnittoIcons.Key2, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._2)) }
KeyboardButtonLight(bModifier, UnittoIcons.Key3, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._3)) }
KeyboardButtonFilled(bModifier, UnittoIcons.Plus, allowVibration, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Plus) }
if (middleZero) {
KeyboardButtonLight(bModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Dot) }
KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) }
} else {
KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) }
KeyboardButtonLight(bModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Dot) }
}
KeyboardButtonLight(bModifier, UnittoIcons.Backspace, allowVibration, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Delete) }
KeyboardButtonFilled(bModifier, UnittoIcons.Enter, allowVibration, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Enter) }
}
}
}
@Composable
private fun RPNCalculatorKeyboardLandscape(
modifier: Modifier,
fractionalIcon: ImageVector,
middleZero: Boolean,
allowVibration: Boolean,
onCalculationClick: (RPNCalculation) -> Unit,
onInputEditClick: (RPNInputEdit) -> Unit,
) {
KeypadFlow(
modifier = modifier,
rows = 4,
columns = 6
) { width, height ->
val bModifier = Modifier val bModifier = Modifier
.fillMaxHeight(height) .fillMaxHeight(height)
.fillMaxWidth(width) .fillMaxWidth(width)
KeyboardButtonAdditional(modifier = aModifier, icon = UnittoIcons.Swap, allowVibration = allowVibration, contentHeight = additionalButtonIconHeight) { onCalculationClick(RPNCalculation.Swap) } KeyboardButtonAdditional(bModifier, UnittoIcons.Swap, allowVibration, KeyboardButtonContentHeightWide) { onCalculationClick(RPNCalculation.Swap) }
KeyboardButtonAdditional(modifier = aModifier, icon = UnittoIcons.Up, allowVibration = allowVibration, contentHeight = additionalButtonIconHeight) { onCalculationClick(RPNCalculation.RotateUp) } KeyboardButtonLight(bModifier, UnittoIcons.Key7, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._7)) }
KeyboardButtonAdditional(modifier = aModifier, icon = UnittoIcons.Down, allowVibration = allowVibration, contentHeight = additionalButtonIconHeight) { onCalculationClick(RPNCalculation.RotateDown) } KeyboardButtonLight(bModifier, UnittoIcons.Key8, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._8)) }
KeyboardButtonAdditional(modifier = aModifier, icon = UnittoIcons.Pop, allowVibration = allowVibration, contentHeight = additionalButtonIconHeight) { onCalculationClick(RPNCalculation.Pop) } KeyboardButtonLight(bModifier, UnittoIcons.Key9, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._9)) }
KeyboardButtonTertiary(bModifier, UnittoIcons.Clear, allowVibration, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Clear) }
KeyboardButtonFilled(bModifier, UnittoIcons.Unary, allowVibration, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Negate) }
KeyboardButtonTertiary(modifier = bModifier, icon = UnittoIcons.Clear, allowVibration = allowVibration) { onCalculationClick(RPNCalculation.Clear) } KeyboardButtonAdditional(bModifier, UnittoIcons.Up, allowVibration, KeyboardButtonContentHeightWide) { onCalculationClick(RPNCalculation.RotateUp) }
KeyboardButtonFilled(modifier = bModifier, icon = UnittoIcons.Unary, allowVibration = allowVibration) { onCalculationClick(RPNCalculation.Negate) } KeyboardButtonLight(bModifier, UnittoIcons.Key4, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._4)) }
KeyboardButtonFilled(modifier = bModifier, icon = UnittoIcons.Percent, allowVibration = allowVibration) { onCalculationClick(RPNCalculation.Percent) } KeyboardButtonLight(bModifier, UnittoIcons.Key5, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._5)) }
KeyboardButtonFilled(modifier = bModifier, icon = UnittoIcons.Divide, allowVibration = allowVibration) { onCalculationClick(RPNCalculation.Divide) } KeyboardButtonLight(bModifier, UnittoIcons.Key6, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._6)) }
KeyboardButtonFilled(bModifier, UnittoIcons.Multiply, allowVibration, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Multiply) }
KeyboardButtonFilled(bModifier, UnittoIcons.Divide, allowVibration, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Divide) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key7, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._7)) } KeyboardButtonAdditional(bModifier, UnittoIcons.Down, allowVibration, KeyboardButtonContentHeightWide) { onCalculationClick(RPNCalculation.RotateDown) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key8, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._8)) } KeyboardButtonLight(bModifier, UnittoIcons.Key1, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._1)) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key9, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._9)) } KeyboardButtonLight(bModifier, UnittoIcons.Key2, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._2)) }
KeyboardButtonFilled(modifier = bModifier, icon = UnittoIcons.Multiply, allowVibration = allowVibration) { onCalculationClick(RPNCalculation.Multiply) } KeyboardButtonLight(bModifier, UnittoIcons.Key3, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._3)) }
KeyboardButtonFilled(bModifier, UnittoIcons.Plus, allowVibration, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Plus) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key4, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._4)) } KeyboardButtonFilled(bModifier, UnittoIcons.Minus, allowVibration, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Minus) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key5, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._5)) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key6, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._6)) }
KeyboardButtonFilled(modifier = bModifier, icon = UnittoIcons.Minus, allowVibration = allowVibration) { onCalculationClick(RPNCalculation.Minus) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key1, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._1)) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key2, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._2)) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key3, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._3)) }
KeyboardButtonFilled(modifier = bModifier, icon = UnittoIcons.Plus, allowVibration = allowVibration) { onCalculationClick(RPNCalculation.Plus) }
KeyboardButtonAdditional(bModifier, UnittoIcons.Pop, allowVibration, KeyboardButtonContentHeightWide) { onCalculationClick(RPNCalculation.Pop) }
if (middleZero) { if (middleZero) {
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key0, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) } KeyboardButtonLight(bModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Dot) }
KeyboardButtonLight(modifier = bModifier, icon = fractionalIcon, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Dot) } KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) }
} else { } else {
KeyboardButtonLight(modifier = bModifier, icon = fractionalIcon, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Dot) } KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Key0, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) } KeyboardButtonLight(bModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Dot) }
} }
KeyboardButtonLight(modifier = bModifier, icon = UnittoIcons.Backspace, allowVibration = allowVibration) { onInputEditClick(RPNInputEdit.Delete) } KeyboardButtonLight(bModifier, UnittoIcons.Backspace, allowVibration, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Delete) }
KeyboardButtonFilled(modifier = bModifier, icon = UnittoIcons.Enter, allowVibration = allowVibration) { onCalculationClick(RPNCalculation.Enter) } KeyboardButtonFilled(bModifier, UnittoIcons.Percent, allowVibration, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Percent) }
KeyboardButtonFilled(bModifier, UnittoIcons.Enter, allowVibration, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Enter) }
} }
} }
@Preview @Preview(device = "spec:parent=pixel_5,orientation=portrait")
@Preview(device = "spec:parent=pixel_5,orientation=landscape")
@Composable @Composable
private fun PreviewKeyboard() { private fun PreviewKeyboard() {
RPNCalculatorKeyboard( RPNCalculatorKeyboard(

View File

@ -19,20 +19,23 @@
package com.sadellie.unitto.feature.calculator.components package com.sadellie.unitto.feature.calculator.components
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExpandMore import androidx.compose.material.icons.filled.ExpandMore
@ -41,7 +44,6 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -49,15 +51,20 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import com.sadellie.unitto.core.base.Token import com.sadellie.unitto.core.base.Token
import com.sadellie.unitto.core.ui.common.ColumnWithConstraints import com.sadellie.unitto.core.ui.common.ColumnWithConstraints
import com.sadellie.unitto.core.ui.common.KeyboardButtonAdditional 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.KeyboardButtonContentHeightWide
import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled
import com.sadellie.unitto.core.ui.common.KeyboardButtonLight import com.sadellie.unitto.core.ui.common.KeyboardButtonLight
import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary
import com.sadellie.unitto.core.ui.common.RowWithConstraints import com.sadellie.unitto.core.ui.common.KeypadFlow
import com.sadellie.unitto.core.ui.common.key.UnittoIcons 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.AcTan
import com.sadellie.unitto.core.ui.common.key.unittoicons.ArCos import com.sadellie.unitto.core.ui.common.key.unittoicons.ArCos
@ -117,11 +124,15 @@ internal fun CalculatorKeyboard(
toggleAngleMode: () -> Unit, toggleAngleMode: () -> Unit,
evaluate: () -> Unit evaluate: () -> Unit
) { ) {
val fractionalIcon = remember(fractional) { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma }
val angleIcon = remember(radianMode) { if (radianMode) UnittoIcons.Rad else UnittoIcons.Deg }
var invMode: Boolean by remember { mutableStateOf(false) }
if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT) { if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT) {
PortraitKeyboard( PortraitKeyboard(
modifier = modifier, modifier = modifier,
radianMode = radianMode, angleIcon = angleIcon,
fractional = fractional, fractionalIcon = fractionalIcon,
allowVibration = allowVibration, allowVibration = allowVibration,
middleZero = middleZero, middleZero = middleZero,
addSymbol = addSymbol, addSymbol = addSymbol,
@ -131,12 +142,14 @@ internal fun CalculatorKeyboard(
evaluate = evaluate, evaluate = evaluate,
acButton = acButton, acButton = acButton,
addBracket = addBracket, addBracket = addBracket,
invMode = invMode,
toggleInvMode = { invMode = !invMode },
) )
} else { } else {
LandscapeKeyboard( LandscapeKeyboard(
modifier = modifier, modifier = modifier,
radianMode = radianMode, angleIcon = angleIcon,
fractional = fractional, fractionalIcon = fractionalIcon,
allowVibration = allowVibration, allowVibration = allowVibration,
middleZero = middleZero, middleZero = middleZero,
addSymbol = addSymbol, addSymbol = addSymbol,
@ -146,6 +159,8 @@ internal fun CalculatorKeyboard(
evaluate = evaluate, evaluate = evaluate,
acButton = acButton, acButton = acButton,
addBracket = addBracket, addBracket = addBracket,
invMode = invMode,
toggleInvMode = { invMode = !invMode },
) )
} }
} }
@ -153,8 +168,8 @@ internal fun CalculatorKeyboard(
@Composable @Composable
private fun PortraitKeyboard( private fun PortraitKeyboard(
modifier: Modifier, modifier: Modifier,
radianMode: Boolean, angleIcon: ImageVector,
fractional: String, fractionalIcon: ImageVector,
allowVibration: Boolean, allowVibration: Boolean,
middleZero: Boolean, middleZero: Boolean,
addSymbol: (String) -> Unit, addSymbol: (String) -> Unit,
@ -164,10 +179,10 @@ private fun PortraitKeyboard(
evaluate: () -> Unit, evaluate: () -> Unit,
acButton: Boolean, acButton: Boolean,
addBracket: () -> Unit, addBracket: () -> Unit,
invMode: Boolean,
toggleInvMode: () -> Unit,
) { ) {
val fractionalIcon = remember { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma }
var showAdditional: Boolean by remember { mutableStateOf(false) } var showAdditional: Boolean by remember { mutableStateOf(false) }
var invMode: Boolean by remember { mutableStateOf(false) }
val expandRotation: Float by animateFloatAsState( val expandRotation: Float by animateFloatAsState(
targetValue = if (showAdditional) 180f else 0f, targetValue = if (showAdditional) 180f else 0f,
animationSpec = tween(easing = FastOutSlowInEasing), animationSpec = tween(easing = FastOutSlowInEasing),
@ -175,60 +190,67 @@ private fun PortraitKeyboard(
) )
ColumnWithConstraints( ColumnWithConstraints(
modifier = modifier modifier = modifier,
) { constraints -> ) { constraints ->
val mainButtonHorizontalPadding by remember(constraints.maxHeight) { val spacerHeight = remember { constraints.maxHeight * 0.025f }
derivedStateOf { constraints.maxHeight * 0.007f } val additionalButtonHeight = remember { constraints.maxHeight * 0.09f }
}
val additionalButtonHeight = remember {
constraints.maxHeight * 0.09f
}
val spacerHeight = remember {
constraints.maxHeight * 0.025f
}
val additionalRowSpacedBy = remember {
constraints.maxWidth * 0.03f
}
val weightModifier = Modifier.weight(1f)
val mainButtonModifier = Modifier
.fillMaxSize()
.weight(1f)
.padding(mainButtonHorizontalPadding)
val additionalButtonModifier = Modifier
.weight(1f)
.height(additionalButtonHeight)
Spacer(modifier = Modifier.height(spacerHeight)) Spacer(modifier = Modifier.height(spacerHeight))
Row( Row(
modifier = Modifier, modifier = Modifier
horizontalArrangement = Arrangement.spacedBy(additionalRowSpacedBy) .fillMaxWidth(),
horizontalArrangement = Arrangement.Start
) { ) {
// Additional buttons Crossfade(
Crossfade(invMode, weightModifier, label = "Additional button") { targetState = invMode,
if (it) { modifier = Modifier
AdditionalButtonsPortraitInverse( .fillMaxWidth()
modifier = additionalButtonModifier, .weight(1f)
allowVibration = allowVibration, ) { inverse ->
addSymbol = addSymbol, if (inverse) {
AdditionalPortrait(
showAdditional = showAdditional, showAdditional = showAdditional,
radianMode = radianMode, buttonHeight = additionalButtonHeight,
toggleAngleMode = toggleAngleMode, content1 = { buttonModifier ->
toggleInvMode = { invMode = !invMode } KeyboardButtonAdditional(buttonModifier, UnittoIcons.Modulo, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Operator.modulo) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Pi, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Const.pi) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.PowerWide, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Operator.power) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Factorial, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Operator.factorial) }
},
content2 = { buttonModifier ->
KeyboardButtonAdditional(buttonModifier, angleIcon, allowVibration, KeyboardButtonContentHeightWide) { toggleAngleMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.ArSin, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.arsinBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.ArCos, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.arcosBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.AcTan, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.actanBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Inv, allowVibration, KeyboardButtonContentHeightWide) { toggleInvMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.E, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Const.e) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Ex, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.expBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Power10, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Digit._1 + Token.Digit._0 + Token.Operator.power) }
}
) )
} else { } else {
AdditionalButtonsPortrait( AdditionalPortrait(
modifier = additionalButtonModifier,
allowVibration = allowVibration,
addSymbol = addSymbol,
showAdditional = showAdditional, showAdditional = showAdditional,
radianMode = radianMode, buttonHeight = additionalButtonHeight,
toggleAngleMode = toggleAngleMode, content1 = { buttonModifier ->
toggleInvMode = { invMode = !invMode } KeyboardButtonAdditional(buttonModifier, UnittoIcons.RootWide, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Operator.sqrt) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Pi, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Const.pi) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.PowerWide, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Operator.power) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Factorial, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Operator.factorial) }
},
content2 = { buttonModifier ->
KeyboardButtonAdditional(buttonModifier, angleIcon, allowVibration, KeyboardButtonContentHeightWide) { toggleAngleMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Sin, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.sinBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Cos, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.cosBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Tan, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.tanBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Inv, allowVibration, KeyboardButtonContentHeightWide) { toggleInvMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.E, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Const.e) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Ln, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.lnBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Log, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.logBracket) }
}
) )
} }
} }
@ -237,7 +259,6 @@ private fun PortraitKeyboard(
modifier = Modifier.size(additionalButtonHeight), modifier = Modifier.size(additionalButtonHeight),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
// Expand/Collapse
IconButton( IconButton(
onClick = { showAdditional = !showAdditional }, onClick = { showAdditional = !showAdditional },
colors = IconButtonDefaults.iconButtonColors(containerColor = MaterialTheme.colorScheme.inverseOnSurface) colors = IconButtonDefaults.iconButtonColors(containerColor = MaterialTheme.colorScheme.inverseOnSurface)
@ -249,118 +270,116 @@ private fun PortraitKeyboard(
Spacer(modifier = Modifier.height(spacerHeight)) Spacer(modifier = Modifier.height(spacerHeight))
Row(weightModifier) { KeypadFlow(
modifier = Modifier
.weight(1f)
.fillMaxSize(),
rows = 5,
columns = 4,
) { width, height ->
val mainButtonModifier = Modifier
.fillMaxWidth(width)
.fillMaxHeight(height)
if (acButton) { if (acButton) {
KeyboardButtonTertiary(mainButtonModifier, UnittoIcons.Clear, allowVibration) { clearSymbols() } KeyboardButtonTertiary(mainButtonModifier, UnittoIcons.Clear, allowVibration, KeyboardButtonContentHeightTall) { clearSymbols() }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Brackets, allowVibration) { addBracket() } KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Brackets, allowVibration, KeyboardButtonContentHeightTall) { addBracket() }
} else { } else {
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.LeftBracket, allowVibration) { addSymbol(Token.Operator.leftBracket) } KeyboardButtonFilled(mainButtonModifier, UnittoIcons.LeftBracket, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.leftBracket) }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.RightBracket, allowVibration) { addSymbol(Token.Operator.rightBracket) } KeyboardButtonFilled(mainButtonModifier, UnittoIcons.RightBracket, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.rightBracket) }
} }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Percent, allowVibration) { addSymbol(Token.Operator.percent) } KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Percent, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.percent) }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Divide, allowVibration) { addSymbol(Token.Operator.divide) } KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Divide, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.divide) }
}
Row(weightModifier) { KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key7, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._7) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key7, allowVibration) { addSymbol(Token.Digit._7) } KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key8, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._8) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key8, allowVibration) { addSymbol(Token.Digit._8) } KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key9, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._9) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key9, allowVibration) { addSymbol(Token.Digit._9) } KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Multiply, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.multiply) }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Multiply, allowVibration) { addSymbol(Token.Operator.multiply) }
} KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key4, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._4) }
Row(weightModifier) { KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key5, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._5) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key4, allowVibration) { addSymbol(Token.Digit._4) } KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key6, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._6) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key5, allowVibration) { addSymbol(Token.Digit._5) } KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Minus, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.minus) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key6, allowVibration) { addSymbol(Token.Digit._6) }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Minus, allowVibration) { addSymbol(Token.Operator.minus) } KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key1, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._1) }
} KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key2, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._2) }
Row(weightModifier) { KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key3, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._3) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key1, allowVibration) { addSymbol(Token.Digit._1) } KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Plus, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.plus) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key2, allowVibration) { addSymbol(Token.Digit._2) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key3, allowVibration) { addSymbol(Token.Digit._3) }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Plus, allowVibration) { addSymbol(Token.Operator.plus) }
}
Row(weightModifier) {
if (middleZero) { if (middleZero) {
KeyboardButtonLight(mainButtonModifier, fractionalIcon, allowVibration) { addSymbol(Token.Digit.dot) } KeyboardButtonLight(mainButtonModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit.dot) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key0, allowVibration) { addSymbol(Token.Digit._0) } KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._0) }
} else { } else {
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key0, allowVibration) { addSymbol(Token.Digit._0) } KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._0) }
KeyboardButtonLight(mainButtonModifier, fractionalIcon, allowVibration) { addSymbol(Token.Digit.dot) } KeyboardButtonLight(mainButtonModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit.dot) }
} }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Backspace, allowVibration, onLongClick = clearSymbols) { deleteSymbol() } KeyboardButtonLight(mainButtonModifier, UnittoIcons.Backspace, allowVibration, KeyboardButtonContentHeightTall, clearSymbols) { deleteSymbol() }
KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Equal, allowVibration) { evaluate() } KeyboardButtonFilled(mainButtonModifier, UnittoIcons.Equal, allowVibration, KeyboardButtonContentHeightTall) { evaluate() }
} }
Spacer(modifier = Modifier.height(spacerHeight)) Spacer(modifier = Modifier.height(spacerHeight))
} }
} }
/**
* Additional buttons.
*
* Width: 4 buttons
*
* Height: 3 buttons
*
* @param showAdditional When `true` reveals [content2] with animation.
* @param buttonHeight Button height in [Dp].
* @param content1 First row of buttons.
* @param content2 Second and third rows of buttons.
*/
@Composable @Composable
private fun AdditionalButtonsPortrait( private fun AdditionalPortrait(
modifier: Modifier,
allowVibration: Boolean,
addSymbol: (String) -> Unit,
showAdditional: Boolean, showAdditional: Boolean,
radianMode: Boolean, buttonHeight: Dp,
toggleAngleMode: () -> Unit, content1: @Composable (buttonModifier: Modifier) -> Unit,
toggleInvMode: () -> Unit content2: @Composable (buttonModifier: Modifier) -> Unit
) { ) {
Column { AnimatedContent(
Row { targetState = showAdditional,
KeyboardButtonAdditional(modifier, UnittoIcons.RootWide, allowVibration) { addSymbol(Token.Operator.sqrt) } modifier = Modifier,
KeyboardButtonAdditional(modifier, UnittoIcons.Pi, allowVibration) { addSymbol(Token.Const.pi) } transitionSpec = {
KeyboardButtonAdditional(modifier, UnittoIcons.PowerWide, allowVibration) { addSymbol(Token.Operator.power) } expandVertically(expandFrom = Alignment.Top) togetherWith
KeyboardButtonAdditional(modifier, UnittoIcons.Factorial, allowVibration) { addSymbol(Token.Operator.factorial) } shrinkVertically(shrinkTowards = Alignment.Top) using (SizeTransform())
} }
AnimatedVisibility(showAdditional) { ) { show ->
Column { if (show) {
Row { KeypadFlow(
KeyboardButtonAdditional(modifier, if (radianMode) UnittoIcons.Rad else UnittoIcons.Deg, allowVibration) { toggleAngleMode() } modifier = Modifier
KeyboardButtonAdditional(modifier, UnittoIcons.Sin, allowVibration) { addSymbol(Token.Func.sinBracket) } .height(buttonHeight * 3)
KeyboardButtonAdditional(modifier, UnittoIcons.Cos, allowVibration) { addSymbol(Token.Func.cosBracket) } .fillMaxWidth(),
KeyboardButtonAdditional(modifier, UnittoIcons.Tan, allowVibration) { addSymbol(Token.Func.tanBracket) } rows = 3,
} columns = 4,
Row { verticalPadding = 0,
KeyboardButtonAdditional(modifier, UnittoIcons.Inv, allowVibration) { toggleInvMode() } horizontalPadding = 0,
KeyboardButtonAdditional(modifier, UnittoIcons.E, allowVibration) { addSymbol(Token.Const.e) } ) { width, height ->
KeyboardButtonAdditional(modifier, UnittoIcons.Ln, allowVibration) { addSymbol(Token.Func.lnBracket) } val buttonModifier = Modifier
KeyboardButtonAdditional(modifier, UnittoIcons.Log, allowVibration) { addSymbol(Token.Func.logBracket) } .fillMaxWidth(width)
} .fillMaxHeight(height)
}
}
}
}
@Composable content1(buttonModifier)
private fun AdditionalButtonsPortraitInverse( content2(buttonModifier)
modifier: Modifier, }
allowVibration: Boolean, } else {
addSymbol: (String) -> Unit, KeypadFlow(
showAdditional: Boolean, modifier = Modifier
radianMode: Boolean, .height(buttonHeight * 1)
toggleAngleMode: () -> Unit, .fillMaxWidth(),
toggleInvMode: () -> Unit rows = 1,
) { columns = 4,
Column { verticalPadding = 0,
Row { horizontalPadding = 0,
KeyboardButtonAdditional(modifier, UnittoIcons.Modulo, allowVibration) { addSymbol(Token.Operator.modulo) } ) { width, height ->
KeyboardButtonAdditional(modifier, UnittoIcons.Pi, allowVibration) { addSymbol(Token.Const.pi) } val buttonModifier = Modifier
KeyboardButtonAdditional(modifier, UnittoIcons.PowerWide, allowVibration) { addSymbol(Token.Operator.power) } .fillMaxWidth(width)
KeyboardButtonAdditional(modifier, UnittoIcons.Factorial, allowVibration) { addSymbol(Token.Operator.factorial) } .fillMaxHeight(height)
}
AnimatedVisibility(showAdditional) { content1(buttonModifier)
Column {
Row {
KeyboardButtonAdditional(modifier, if (radianMode) UnittoIcons.Rad else UnittoIcons.Deg, allowVibration) { toggleAngleMode() }
KeyboardButtonAdditional(modifier, UnittoIcons.ArSin, allowVibration) { addSymbol(Token.Func.arsinBracket) }
KeyboardButtonAdditional(modifier, UnittoIcons.ArCos, allowVibration) { addSymbol(Token.Func.arcosBracket) }
KeyboardButtonAdditional(modifier, UnittoIcons.AcTan, allowVibration) { addSymbol(Token.Func.actanBracket) }
}
Row {
KeyboardButtonAdditional(modifier, UnittoIcons.Inv, allowVibration) { toggleInvMode() }
KeyboardButtonAdditional(modifier, UnittoIcons.E, allowVibration) { addSymbol(Token.Const.e) }
KeyboardButtonAdditional(modifier, UnittoIcons.Ex, allowVibration) { addSymbol(Token.Func.expBracket) }
KeyboardButtonAdditional(modifier, UnittoIcons.Power10, allowVibration) { addSymbol(Token.Digit._1 + Token.Digit._0 + Token.Operator.power) }
}
} }
} }
} }
@ -369,8 +388,8 @@ private fun AdditionalButtonsPortraitInverse(
@Composable @Composable
private fun LandscapeKeyboard( private fun LandscapeKeyboard(
modifier: Modifier, modifier: Modifier,
radianMode: Boolean, angleIcon: ImageVector,
fractional: String, fractionalIcon: ImageVector,
allowVibration: Boolean, allowVibration: Boolean,
middleZero: Boolean, middleZero: Boolean,
addSymbol: (String) -> Unit, addSymbol: (String) -> Unit,
@ -380,157 +399,131 @@ private fun LandscapeKeyboard(
evaluate: () -> Unit, evaluate: () -> Unit,
acButton: Boolean, acButton: Boolean,
addBracket: () -> Unit, addBracket: () -> Unit,
invMode: Boolean,
toggleInvMode: () -> Unit,
) { ) {
val fractionalIcon = remember { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma } Crossfade(
var invMode: Boolean by remember { mutableStateOf(false) } targetState = invMode,
modifier = modifier
) { inverse ->
if (inverse) {
KeypadFlow(
modifier = Modifier.fillMaxSize(),
rows = 4,
columns = 8
) { width, height ->
val buttonModifier = Modifier
.fillMaxWidth(width)
.fillMaxHeight(height)
RowWithConstraints(modifier) { constraints -> KeyboardButtonAdditional(buttonModifier, angleIcon, allowVibration, KeyboardButtonContentHeightShort) { toggleAngleMode() }
val buttonModifier = Modifier KeyboardButtonAdditional(buttonModifier, UnittoIcons.Modulo, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Operator.modulo) }
.fillMaxWidth() KeyboardButtonAdditional(buttonModifier, UnittoIcons.Pi, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Const.pi) }
.weight(1f) KeyboardButtonLight(buttonModifier, UnittoIcons.Key7, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._7) }
.padding(constraints.maxWidth * 0.005f, constraints.maxHeight * 0.02f) KeyboardButtonLight(buttonModifier, UnittoIcons.Key8, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._8) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key9, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._9) }
Crossfade(invMode, Modifier.weight(3f), label = "Additional button") { if (acButton) {
Row { KeyboardButtonTertiary(buttonModifier, UnittoIcons.Clear, allowVibration, KeyboardButtonContentHeightShort) { clearSymbols() }
if (it) { KeyboardButtonFilled(buttonModifier, UnittoIcons.Brackets, allowVibration, KeyboardButtonContentHeightShort) { addBracket() }
AdditionalButtonsLandscapeInverse(
modifier = Modifier.weight(1f),
buttonModifier = buttonModifier,
allowVibration = allowVibration,
radianMode = radianMode,
addSymbol = addSymbol,
toggleAngleMode = toggleAngleMode,
toggleInvMode = { invMode = !invMode }
)
} else { } else {
AdditionalButtonsLandscape( KeyboardButtonFilled(buttonModifier, UnittoIcons.LeftBracket, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.leftBracket) }
modifier = Modifier.weight(1f), KeyboardButtonFilled(buttonModifier, UnittoIcons.RightBracket, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.rightBracket) }
buttonModifier = buttonModifier,
allowVibration = allowVibration,
radianMode = radianMode,
addSymbol = addSymbol,
toggleAngleMode = toggleAngleMode,
toggleInvMode = { invMode = !invMode }
)
} }
}
}
Column(Modifier.weight(1f)) { KeyboardButtonAdditional(buttonModifier, UnittoIcons.Inv, allowVibration, KeyboardButtonContentHeightShort) { toggleInvMode() }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key7, allowVibration) { addSymbol(Token.Digit._7) } KeyboardButtonAdditional(buttonModifier, UnittoIcons.PowerWide, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.power) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key4, allowVibration) { addSymbol(Token.Digit._4) } KeyboardButtonAdditional(buttonModifier, UnittoIcons.Factorial, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.factorial) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key1, allowVibration) { addSymbol(Token.Digit._1) } KeyboardButtonLight(buttonModifier, UnittoIcons.Key4, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._4) }
if (middleZero) { KeyboardButtonLight(buttonModifier, UnittoIcons.Key5, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._5) }
KeyboardButtonLight(buttonModifier, fractionalIcon, allowVibration) { addSymbol(Token.Digit.dot) } KeyboardButtonLight(buttonModifier, UnittoIcons.Key6, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._6) }
} else { KeyboardButtonFilled(buttonModifier, UnittoIcons.Multiply, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.multiply) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key0, allowVibration) { addSymbol(Token.Digit._0) } KeyboardButtonFilled(buttonModifier, UnittoIcons.Divide, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.divide) }
}
}
Column(Modifier.weight(1f)) {
KeyboardButtonLight(buttonModifier, UnittoIcons.Key8, allowVibration) { addSymbol(Token.Digit._8) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key5, allowVibration) { addSymbol(Token.Digit._5) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key2, allowVibration) { addSymbol(Token.Digit._2) }
if (middleZero) {
KeyboardButtonLight(buttonModifier, UnittoIcons.Key0, allowVibration) { addSymbol(Token.Digit._0) }
} else {
KeyboardButtonLight(buttonModifier, fractionalIcon, allowVibration) { addSymbol(Token.Digit.dot) }
}
}
Column(Modifier.weight(1f)) {
KeyboardButtonLight(buttonModifier, UnittoIcons.Key9, allowVibration) { addSymbol(Token.Digit._9) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key6, allowVibration) { addSymbol(Token.Digit._6) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key3, allowVibration) { addSymbol(Token.Digit._3) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Backspace, allowVibration, onLongClick = clearSymbols) { deleteSymbol() }
}
Column(Modifier.weight(1f)) { KeyboardButtonAdditional(buttonModifier, UnittoIcons.ArSin, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.arsinBracket) }
if (acButton) { KeyboardButtonAdditional(buttonModifier, UnittoIcons.ArCos, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.arcosBracket) }
KeyboardButtonTertiary(buttonModifier, UnittoIcons.Clear, allowVibration) { clearSymbols() } KeyboardButtonAdditional(buttonModifier, UnittoIcons.AcTan, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.actanBracket) }
} else { KeyboardButtonLight(buttonModifier, UnittoIcons.Key1, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._1) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.LeftBracket, allowVibration) { addSymbol(Token.Operator.leftBracket) } KeyboardButtonLight(buttonModifier, UnittoIcons.Key2, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._2) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key3, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._3) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Minus, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.minus) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Percent, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.percent) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.E, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Const.e) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Ex, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Func.expBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Power10, allowVibration, KeyboardButtonContentHeightWide) { addSymbol(Token.Digit._1 + Token.Digit._0 + Token.Operator.power) }
if (middleZero) {
KeyboardButtonLight(buttonModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit.dot) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._0) }
} else {
KeyboardButtonLight(buttonModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._0) }
KeyboardButtonLight(buttonModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit.dot) }
}
KeyboardButtonLight(buttonModifier, UnittoIcons.Backspace, allowVibration, KeyboardButtonContentHeightShort, clearSymbols) { deleteSymbol() }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Plus, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.plus) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Equal, allowVibration, KeyboardButtonContentHeightShort) { evaluate() }
} }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Multiply, allowVibration) { addSymbol(Token.Operator.multiply) } } else {
KeyboardButtonFilled(buttonModifier, UnittoIcons.Minus, allowVibration) { addSymbol(Token.Operator.minus) } KeypadFlow(
KeyboardButtonFilled(buttonModifier, UnittoIcons.Plus, allowVibration) { addSymbol(Token.Operator.plus) } modifier = Modifier.fillMaxSize(),
} rows = 4,
Column(Modifier.weight(1f)) { columns = 8
if (acButton) { ) { width, height ->
KeyboardButtonFilled(buttonModifier, UnittoIcons.Brackets, allowVibration) { addBracket() } val buttonModifier = Modifier
} else { .fillMaxWidth(width)
KeyboardButtonFilled(buttonModifier, UnittoIcons.RightBracket, allowVibration) { addSymbol(Token.Operator.rightBracket) } .fillMaxHeight(height)
KeyboardButtonAdditional(buttonModifier, angleIcon, allowVibration, KeyboardButtonContentHeightShort) { toggleAngleMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.RootWide, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.sqrt) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Pi, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Const.pi) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key7, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._7) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key8, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._8) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key9, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._9) }
if (acButton) {
KeyboardButtonTertiary(buttonModifier, UnittoIcons.Clear, allowVibration, KeyboardButtonContentHeightShort) { clearSymbols() }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Brackets, allowVibration, KeyboardButtonContentHeightShort) { addBracket() }
} else {
KeyboardButtonFilled(buttonModifier, UnittoIcons.LeftBracket, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.leftBracket) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.RightBracket, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.rightBracket) }
}
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Inv, allowVibration, KeyboardButtonContentHeightShort) { toggleInvMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.PowerWide, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.power) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Factorial, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.factorial) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key4, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._4) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key5, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._5) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key6, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._6) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Multiply, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.multiply) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Divide, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.divide) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Sin, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Func.sinBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Cos, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Func.cosBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Tan, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Func.tanBracket) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key1, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._1) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key2, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._2) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key3, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._3) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Minus, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.minus) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Percent, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.percent) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.E, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Const.e) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Ln, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Func.lnBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Log, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Func.logBracket) }
if (middleZero) {
KeyboardButtonLight(buttonModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit.dot) }
KeyboardButtonLight(buttonModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._0) }
} else {
KeyboardButtonLight(buttonModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._0) }
KeyboardButtonLight(buttonModifier, fractionalIcon, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit.dot) }
}
KeyboardButtonLight(buttonModifier, UnittoIcons.Backspace, allowVibration, KeyboardButtonContentHeightShort, clearSymbols) { deleteSymbol() }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Plus, allowVibration, KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.plus) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Equal, allowVibration, KeyboardButtonContentHeightShort) { evaluate() }
} }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Divide, allowVibration) { addSymbol(Token.Operator.divide) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Percent, allowVibration) { addSymbol(Token.Operator.percent) }
KeyboardButtonFilled(buttonModifier, UnittoIcons.Equal, allowVibration) { evaluate() }
} }
} }
} }
@Composable @Preview(device = "spec:parent=pixel_5,orientation=portrait")
private fun AdditionalButtonsLandscape( @Preview(device = "spec:parent=pixel_5,orientation=landscape")
modifier: Modifier,
buttonModifier: Modifier,
allowVibration: Boolean,
radianMode: Boolean,
addSymbol: (String) -> Unit,
toggleAngleMode: () -> Unit,
toggleInvMode: () -> Unit
) {
Column(modifier) {
KeyboardButtonAdditional(buttonModifier, if (radianMode) UnittoIcons.Rad else UnittoIcons.Deg, allowVibration) { toggleAngleMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Inv, allowVibration) { toggleInvMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Sin, allowVibration) { addSymbol(Token.Func.sinBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.E, allowVibration) { addSymbol(Token.Const.e) }
}
Column(modifier) {
KeyboardButtonAdditional(buttonModifier, UnittoIcons.RootWide, allowVibration) { addSymbol(Token.Operator.sqrt) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.PowerWide, allowVibration) { addSymbol(Token.Operator.power) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Cos, allowVibration) { addSymbol(Token.Func.cosBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Ln, allowVibration) { addSymbol(Token.Func.lnBracket) }
}
Column(modifier) {
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Pi, allowVibration) { addSymbol(Token.Const.pi) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Factorial, allowVibration) { addSymbol(Token.Operator.factorial) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Tan, allowVibration) { addSymbol(Token.Func.tanBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Log, allowVibration) { addSymbol(Token.Func.logBracket) }
}
}
@Composable
private fun AdditionalButtonsLandscapeInverse(
modifier: Modifier,
buttonModifier: Modifier,
allowVibration: Boolean,
radianMode: Boolean,
addSymbol: (String) -> Unit,
toggleAngleMode: () -> Unit,
toggleInvMode: () -> Unit
) {
Column(modifier) {
KeyboardButtonAdditional(buttonModifier, if (radianMode) UnittoIcons.Rad else UnittoIcons.Deg, allowVibration) { toggleAngleMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Inv, allowVibration) { toggleInvMode() }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.ArSin, allowVibration) { addSymbol(Token.Func.arsinBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.E, allowVibration) { addSymbol(Token.Const.e) }
}
Column(modifier) {
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Modulo, allowVibration) { addSymbol(Token.Operator.modulo) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.PowerWide, allowVibration) { addSymbol(Token.Operator.power) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.ArCos, allowVibration) { addSymbol(Token.Func.arcosBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Ex, allowVibration) { addSymbol(Token.Func.expBracket) }
}
Column(modifier) {
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Pi, allowVibration) { addSymbol(Token.Const.pi) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Factorial, allowVibration) { addSymbol(Token.Operator.factorial) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.AcTan, allowVibration) { addSymbol(Token.Func.actanBracket) }
KeyboardButtonAdditional(buttonModifier, UnittoIcons.Power10, allowVibration) { addSymbol(Token.Digit._1 + Token.Digit._0 + Token.Operator.power) }
}
}
@Preview
@Composable @Composable
private fun PreviewCalculatorKeyboard() { private fun PreviewCalculatorKeyboard() {
CalculatorKeyboard( CalculatorKeyboard(

View File

@ -23,7 +23,6 @@ import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -112,7 +111,6 @@ internal fun ChipsRow(
} }
} }
@OptIn(ExperimentalLayoutApi::class)
@Composable @Composable
fun ChipsFlexRow( fun ChipsFlexRow(
items: List<UnitGroup> = ALL_UNIT_GROUPS, items: List<UnitGroup> = ALL_UNIT_GROUPS,

View File

@ -18,20 +18,20 @@
package com.sadellie.unitto.feature.converter.components package com.sadellie.unitto.feature.converter.components
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import com.sadellie.unitto.core.base.Token import com.sadellie.unitto.core.base.Token
import com.sadellie.unitto.core.ui.common.ColumnWithConstraints import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightShort
import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTall
import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled
import com.sadellie.unitto.core.ui.common.KeyboardButtonLight import com.sadellie.unitto.core.ui.common.KeyboardButtonLight
import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary
import com.sadellie.unitto.core.ui.common.KeypadFlow
import com.sadellie.unitto.core.ui.common.key.UnittoIcons 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.Backspace
import com.sadellie.unitto.core.ui.common.key.unittoicons.Brackets import com.sadellie.unitto.core.ui.common.key.unittoicons.Brackets
@ -63,6 +63,7 @@ import com.sadellie.unitto.core.ui.common.key.unittoicons.Power
import com.sadellie.unitto.core.ui.common.key.unittoicons.RightBracket import com.sadellie.unitto.core.ui.common.key.unittoicons.RightBracket
import com.sadellie.unitto.core.ui.common.key.unittoicons.Root import com.sadellie.unitto.core.ui.common.key.unittoicons.Root
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
import com.sadellie.unitto.core.ui.isPortrait
@Composable @Composable
internal fun DefaultKeyboard( internal fun DefaultKeyboard(
@ -76,59 +77,50 @@ internal fun DefaultKeyboard(
acButton: Boolean, acButton: Boolean,
addBracket: () -> Unit, addBracket: () -> Unit,
) { ) {
ColumnWithConstraints(modifier) { val fractionalIcon = remember { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma }
val fractionalIcon = remember { if (fractional == Token.Digit.dot) UnittoIcons.Dot else UnittoIcons.Comma } val contentHeight: Float = if (isPortrait()) KeyboardButtonContentHeightTall else KeyboardButtonContentHeightShort
val mainButtonHorizontalPadding by remember(it.maxWidth) {
derivedStateOf { it.maxWidth * 0.01f }
}
// Button modifier KeypadFlow(
val bModifier = Modifier modifier = modifier,
.fillMaxSize() rows = 5,
.weight(1f) columns = 4
.padding(mainButtonHorizontalPadding) ) { width, height ->
// Column modifier val bModifier = Modifier.fillMaxWidth(width).fillMaxHeight(height)
val cModifier = Modifier.weight(1f)
Row(cModifier) { if (acButton) {
if (acButton) { KeyboardButtonTertiary(bModifier, UnittoIcons.Clear, allowVibration, contentHeight) { clearInput() }
KeyboardButtonTertiary(bModifier, UnittoIcons.Clear, allowVibration) { clearInput() } KeyboardButtonFilled(bModifier, UnittoIcons.Brackets, allowVibration, contentHeight) { addBracket() }
KeyboardButtonFilled(bModifier, UnittoIcons.Brackets, allowVibration) { addBracket() } } else {
} else { KeyboardButtonFilled(bModifier, UnittoIcons.LeftBracket, allowVibration, contentHeight) { addDigit(Token.Operator.leftBracket) }
KeyboardButtonFilled(bModifier, UnittoIcons.LeftBracket, allowVibration) { addDigit(Token.Operator.leftBracket) } KeyboardButtonFilled(bModifier, UnittoIcons.RightBracket, allowVibration, contentHeight) { addDigit(Token.Operator.rightBracket) }
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) }
} }
Row(cModifier) { KeyboardButtonFilled(bModifier, UnittoIcons.Power, allowVibration, contentHeight) { addDigit(Token.Operator.power) }
KeyboardButtonLight(bModifier, UnittoIcons.Key7, allowVibration) { addDigit(Token.Digit._7) } KeyboardButtonFilled(bModifier, UnittoIcons.Root, allowVibration, contentHeight) { addDigit(Token.Operator.sqrt) }
KeyboardButtonLight(bModifier, UnittoIcons.Key8, allowVibration) { addDigit(Token.Digit._8) }
KeyboardButtonLight(bModifier, UnittoIcons.Key9, allowVibration) { addDigit(Token.Digit._9) } KeyboardButtonLight(bModifier, UnittoIcons.Key7, allowVibration, contentHeight) { addDigit(Token.Digit._7) }
KeyboardButtonFilled(bModifier, UnittoIcons.Divide, allowVibration) { addDigit(Token.Operator.divide) } KeyboardButtonLight(bModifier, UnittoIcons.Key8, allowVibration, contentHeight) { addDigit(Token.Digit._8) }
} KeyboardButtonLight(bModifier, UnittoIcons.Key9, allowVibration, contentHeight) { addDigit(Token.Digit._9) }
Row(cModifier) { KeyboardButtonFilled(bModifier, UnittoIcons.Divide, allowVibration, contentHeight) { addDigit(Token.Operator.divide) }
KeyboardButtonLight(bModifier, UnittoIcons.Key4, allowVibration) { addDigit(Token.Digit._4) }
KeyboardButtonLight(bModifier, UnittoIcons.Key5, allowVibration) { addDigit(Token.Digit._5) } KeyboardButtonLight(bModifier, UnittoIcons.Key4, allowVibration, contentHeight) { addDigit(Token.Digit._4) }
KeyboardButtonLight(bModifier, UnittoIcons.Key6, allowVibration) { addDigit(Token.Digit._6) } KeyboardButtonLight(bModifier, UnittoIcons.Key5, allowVibration, contentHeight) { addDigit(Token.Digit._5) }
KeyboardButtonFilled(bModifier, UnittoIcons.Multiply, allowVibration) { addDigit(Token.Operator.multiply) } KeyboardButtonLight(bModifier, UnittoIcons.Key6, allowVibration, contentHeight) { addDigit(Token.Digit._6) }
} KeyboardButtonFilled(bModifier, UnittoIcons.Multiply, allowVibration, contentHeight) { addDigit(Token.Operator.multiply) }
Row(cModifier) {
KeyboardButtonLight(bModifier, UnittoIcons.Key1, allowVibration) { addDigit(Token.Digit._1) } KeyboardButtonLight(bModifier, UnittoIcons.Key1, allowVibration, contentHeight) { addDigit(Token.Digit._1) }
KeyboardButtonLight(bModifier, UnittoIcons.Key2, allowVibration) { addDigit(Token.Digit._2) } KeyboardButtonLight(bModifier, UnittoIcons.Key2, allowVibration, contentHeight) { addDigit(Token.Digit._2) }
KeyboardButtonLight(bModifier, UnittoIcons.Key3, allowVibration) { addDigit(Token.Digit._3) } KeyboardButtonLight(bModifier, UnittoIcons.Key3, allowVibration, contentHeight) { addDigit(Token.Digit._3) }
KeyboardButtonFilled(bModifier, UnittoIcons.Minus, allowVibration) { addDigit(Token.Operator.minus) } KeyboardButtonFilled(bModifier, UnittoIcons.Minus, allowVibration, contentHeight) { addDigit(Token.Operator.minus) }
}
Row(cModifier) { if (middleZero) {
if (middleZero) { KeyboardButtonLight(bModifier, fractionalIcon, allowVibration, contentHeight) { addDigit(Token.Digit.dot) }
KeyboardButtonLight(bModifier, fractionalIcon, allowVibration) { addDigit(Token.Digit.dot) } KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration, contentHeight) { addDigit(Token.Digit._0) }
KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration) { addDigit(Token.Digit._0) } } else {
} else { KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration, contentHeight) { addDigit(Token.Digit._0) }
KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration) { addDigit(Token.Digit._0) } KeyboardButtonLight(bModifier, fractionalIcon, allowVibration, contentHeight) { addDigit(Token.Digit.dot) }
KeyboardButtonLight(bModifier, fractionalIcon, allowVibration) { addDigit(Token.Digit.dot) }
}
KeyboardButtonLight(bModifier, UnittoIcons.Backspace, allowVibration, onLongClick = clearInput) { deleteDigit() }
KeyboardButtonFilled(bModifier, UnittoIcons.Plus, allowVibration) { addDigit(Token.Operator.plus) }
} }
KeyboardButtonLight(bModifier, UnittoIcons.Backspace, allowVibration, contentHeight, onLongClick = clearInput) { deleteDigit() }
KeyboardButtonFilled(bModifier, UnittoIcons.Plus, allowVibration, contentHeight) { addDigit(Token.Operator.plus) }
} }
} }
@ -140,51 +132,38 @@ internal fun NumberBaseKeyboard(
deleteDigit: () -> Unit, deleteDigit: () -> Unit,
allowVibration: Boolean allowVibration: Boolean
) { ) {
ColumnWithConstraints(modifier) { val contentHeight: Float = if (isPortrait()) KeyboardButtonContentHeightTall else KeyboardButtonContentHeightShort
val mainButtonHorizontalPadding by remember(it.maxWidth) {
derivedStateOf { it.maxWidth * 0.01f }
}
// Button modifier KeypadFlow(
val bModifier = Modifier modifier = modifier,
.fillMaxSize() rows = 6,
.weight(1f) columns = 3
.padding(mainButtonHorizontalPadding) ) { width, height ->
// Column modifier val bModifier = Modifier.fillMaxWidth(width).fillMaxHeight(height)
val cModifier = Modifier.weight(1f)
Row(cModifier) { KeyboardButtonFilled(bModifier, UnittoIcons.KeyA, allowVibration, contentHeight) { addDigit(Token.Letter._A) }
KeyboardButtonFilled(bModifier, UnittoIcons.KeyA, allowVibration) { addDigit(Token.Letter._A) } KeyboardButtonFilled(bModifier, UnittoIcons.KeyB, allowVibration, contentHeight) { addDigit(Token.Letter._B) }
KeyboardButtonFilled(bModifier, UnittoIcons.KeyB, allowVibration) { addDigit(Token.Letter._B) } KeyboardButtonFilled(bModifier, UnittoIcons.KeyC, allowVibration, contentHeight) { addDigit(Token.Letter._C) }
KeyboardButtonFilled(bModifier, UnittoIcons.KeyC, allowVibration) { addDigit(Token.Letter._C) }
} KeyboardButtonFilled(bModifier, UnittoIcons.KeyD, allowVibration, contentHeight) { addDigit(Token.Letter._D) }
Row(cModifier) { KeyboardButtonFilled(bModifier, UnittoIcons.KeyE, allowVibration, contentHeight) { addDigit(Token.Letter._E) }
KeyboardButtonFilled(bModifier, UnittoIcons.KeyD, allowVibration) { addDigit(Token.Letter._D) } KeyboardButtonFilled(bModifier, UnittoIcons.KeyF, allowVibration, contentHeight) { addDigit(Token.Letter._F) }
KeyboardButtonFilled(bModifier, UnittoIcons.KeyE, allowVibration) { addDigit(Token.Letter._E) }
KeyboardButtonFilled(bModifier, UnittoIcons.KeyF, allowVibration) { addDigit(Token.Letter._F) } KeyboardButtonLight(bModifier, UnittoIcons.Key7, allowVibration, contentHeight) { addDigit(Token.Digit._7) }
} KeyboardButtonLight(bModifier, UnittoIcons.Key8, allowVibration, contentHeight) { addDigit(Token.Digit._8) }
Row(cModifier) { KeyboardButtonLight(bModifier, UnittoIcons.Key9, allowVibration, contentHeight) { addDigit(Token.Digit._9) }
KeyboardButtonLight(bModifier, UnittoIcons.Key7, allowVibration) { addDigit(Token.Digit._7) }
KeyboardButtonLight(bModifier, UnittoIcons.Key8, allowVibration) { addDigit(Token.Digit._8) } KeyboardButtonLight(bModifier, UnittoIcons.Key4, allowVibration, contentHeight) { addDigit(Token.Digit._4) }
KeyboardButtonLight(bModifier, UnittoIcons.Key9, allowVibration) { addDigit(Token.Digit._9) } KeyboardButtonLight(bModifier, UnittoIcons.Key5, allowVibration, contentHeight) { addDigit(Token.Digit._5) }
} KeyboardButtonLight(bModifier, UnittoIcons.Key6, allowVibration, contentHeight) { addDigit(Token.Digit._6) }
Row(cModifier) {
KeyboardButtonLight(bModifier, UnittoIcons.Key4, allowVibration) { addDigit(Token.Digit._4) } KeyboardButtonLight(bModifier, UnittoIcons.Key1, allowVibration, contentHeight) { addDigit(Token.Digit._1) }
KeyboardButtonLight(bModifier, UnittoIcons.Key5, allowVibration) { addDigit(Token.Digit._5) } KeyboardButtonLight(bModifier, UnittoIcons.Key2, allowVibration, contentHeight) { addDigit(Token.Digit._2) }
KeyboardButtonLight(bModifier, UnittoIcons.Key6, allowVibration) { addDigit(Token.Digit._6) } KeyboardButtonLight(bModifier, UnittoIcons.Key3, allowVibration, contentHeight) { addDigit(Token.Digit._3) }
}
Row(cModifier) { // TODO Should be a separate o use custom widthFillFactors and heightFillFactors
KeyboardButtonLight(bModifier, UnittoIcons.Key1, allowVibration) { addDigit(Token.Digit._1) } KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration, contentHeight) { addDigit(Token.Digit._0) }
KeyboardButtonLight(bModifier, UnittoIcons.Key2, allowVibration) { addDigit(Token.Digit._2) } KeyboardButtonLight(Modifier.fillMaxHeight(height).fillMaxWidth(width * 2), UnittoIcons.Backspace, allowVibration, contentHeight, clearInput) { deleteDigit() }
KeyboardButtonLight(bModifier, UnittoIcons.Key3, allowVibration) { addDigit(Token.Digit._3) }
}
Row(cModifier) {
KeyboardButtonLight(bModifier, UnittoIcons.Key0, allowVibration) { addDigit(Token.Digit._0) }
KeyboardButtonLight(
Modifier
.fillMaxSize()
.weight(2f)
.padding(mainButtonHorizontalPadding), UnittoIcons.Backspace, allowVibration, onLongClick = clearInput) { deleteDigit() }
}
} }
} }
@ -192,7 +171,7 @@ internal fun NumberBaseKeyboard(
@Composable @Composable
private fun PreviewConverterKeyboard() { private fun PreviewConverterKeyboard() {
DefaultKeyboard( DefaultKeyboard(
modifier = Modifier, modifier = Modifier.fillMaxSize(),
addDigit = {}, addDigit = {},
clearInput = {}, clearInput = {},
deleteDigit = {}, deleteDigit = {},
@ -208,7 +187,7 @@ private fun PreviewConverterKeyboard() {
@Composable @Composable
private fun PreviewConverterKeyboardNumberBase() { private fun PreviewConverterKeyboardNumberBase() {
NumberBaseKeyboard( NumberBaseKeyboard(
modifier = Modifier, modifier = Modifier.fillMaxSize(),
addDigit = {}, addDigit = {},
clearInput = {}, clearInput = {},
deleteDigit = {}, deleteDigit = {},

View File

@ -33,7 +33,6 @@ import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
@ -109,7 +108,6 @@ internal fun AddSubtractPage(
} }
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalLayoutApi::class)
@Composable @Composable
private fun AddSubtractView( private fun AddSubtractView(
uiState: AddSubtractState, uiState: AddSubtractState,

View File

@ -19,21 +19,23 @@
package com.sadellie.unitto.feature.datecalculator.components package com.sadellie.unitto.feature.datecalculator.components
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusManager import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp import androidx.compose.ui.tooling.preview.Preview
import com.sadellie.unitto.core.base.Token import com.sadellie.unitto.core.base.Token
import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTall
import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled
import com.sadellie.unitto.core.ui.common.KeyboardButtonLight import com.sadellie.unitto.core.ui.common.KeyboardButtonLight
import com.sadellie.unitto.core.ui.common.KeypadFlow
import com.sadellie.unitto.core.ui.common.key.UnittoIcons 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.Backspace
import com.sadellie.unitto.core.ui.common.key.unittoicons.Check import com.sadellie.unitto.core.ui.common.key.unittoicons.Check
@ -60,90 +62,79 @@ internal fun AddSubtractKeyboard(
imeAction: ImeAction, imeAction: ImeAction,
focusManager: FocusManager = LocalFocusManager.current focusManager: FocusManager = LocalFocusManager.current
) { ) {
Row(modifier) { Row(
val weightModifier = Modifier.weight(1f) modifier = modifier
val mainButtonModifier = Modifier ) {
.fillMaxSize() KeypadFlow(
.weight(1f) modifier = Modifier
.padding(4.dp) .fillMaxHeight()
val actionIconHeight = if (isPortrait()) 0.396f else 0.68f .weight(3f),
rows = 4,
columns = 3
) { width, height ->
val mainButtonModifier = Modifier
.fillMaxWidth(width)
.fillMaxHeight(height)
fun keyboardAction() { KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key7, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._7) }
when (imeAction) { KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key8, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._8) }
ImeAction.Next -> focusManager.moveFocus(FocusDirection.Next) KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key9, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._9) }
else -> onConfirm()
}
}
Column(weightModifier) { KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key4, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._4) }
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key7, allowVibration) { KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key5, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._5) }
addSymbol(Token.Digit._7) KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key6, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._6) }
}
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key4, allowVibration) { KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key1, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._1) }
addSymbol(Token.Digit._4 KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key2, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._2) }
) KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key3, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._3) }
}
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key1, allowVibration) { Spacer(mainButtonModifier)
addSymbol(Token.Digit._1) KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key0, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._0) }
}
Spacer(mainButtonModifier) Spacer(mainButtonModifier)
} }
Column(weightModifier) { KeypadFlow(
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key8, allowVibration) { modifier = Modifier
addSymbol(Token.Digit._8) .fillMaxHeight()
} .weight(1f),
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key5, allowVibration) { rows = 2,
addSymbol(Token.Digit._5) columns = 1,
} // In digits keypad there are 4 rows with verticalPadding set to 10
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key2, allowVibration) { // In this keypad we have 2 times less rows, we use 2 times smaller verticalPadding -> 5
addSymbol(Token.Digit._2) verticalPadding = 5
} ) { width, height ->
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key0, allowVibration) { val mainButtonModifier = Modifier
addSymbol(Token.Digit._0) .fillMaxWidth(width)
} .fillMaxHeight(height)
} val actionIconHeight = if (isPortrait()) 0.396f else 0.68f
Column(weightModifier) {
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key9, allowVibration) {
addSymbol(Token.Digit._9)
}
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key6, allowVibration) {
addSymbol(Token.Digit._6)
}
KeyboardButtonLight(mainButtonModifier, UnittoIcons.Key3, allowVibration) {
addSymbol(Token.Digit._3)
}
Spacer(mainButtonModifier)
}
Column(weightModifier) {
Crossfade( Crossfade(
targetState = imeAction, targetState = imeAction == ImeAction.Next,
modifier = mainButtonModifier, modifier = mainButtonModifier,
label = "Primary button animation" label = "Primary button animation"
) { ) { showNext ->
when (it) { if (showNext) {
ImeAction.Next -> KeyboardButtonFilled( KeyboardButtonFilled(Modifier.fillMaxSize(), UnittoIcons.Tab, allowVibration, actionIconHeight) { focusManager.moveFocus(FocusDirection.Next) }
Modifier.fillMaxSize(), } else {
UnittoIcons.Tab, KeyboardButtonFilled(Modifier.fillMaxSize(), UnittoIcons.Check, allowVibration, actionIconHeight) { onConfirm() }
allowVibration,
actionIconHeight
) { keyboardAction() }
else -> KeyboardButtonFilled(
Modifier.fillMaxSize(),
UnittoIcons.Check,
allowVibration,
actionIconHeight
) { keyboardAction() }
} }
} }
KeyboardButtonLight( KeyboardButtonLight(mainButtonModifier, UnittoIcons.Backspace, allowVibration, actionIconHeight) { deleteSymbol() }
mainButtonModifier,
UnittoIcons.Backspace,
allowVibration,
actionIconHeight
) { deleteSymbol() }
} }
} }
} }
@Preview
@Composable
fun PreviewAddSubtractKeyboardNew() {
AddSubtractKeyboard(
modifier = Modifier
.fillMaxSize(),
addSymbol = {},
deleteSymbol = {},
onConfirm = {},
allowVibration = true,
imeAction = ImeAction.Next
)
}

View File

@ -23,7 +23,6 @@ import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -61,7 +60,6 @@ internal fun DateDifferencePage(
} }
@Composable @Composable
@OptIn(ExperimentalLayoutApi::class)
private fun DateDifferenceView( private fun DateDifferenceView(
uiState: DifferenceUIState, uiState: DifferenceUIState,
setStartDate: (ZonedDateTime) -> Unit, setStartDate: (ZonedDateTime) -> Unit,