diff --git a/shared/domain/src/main/java/com/ivy/domain/di/IvyCoreBindingsModule.kt b/shared/domain/src/main/java/com/ivy/domain/di/IvyCoreBindingsModule.kt index fc873d1ce3..a933b30584 100644 --- a/shared/domain/src/main/java/com/ivy/domain/di/IvyCoreBindingsModule.kt +++ b/shared/domain/src/main/java/com/ivy/domain/di/IvyCoreBindingsModule.kt @@ -4,6 +4,7 @@ import com.ivy.domain.features.Features import com.ivy.domain.features.IvyFeatures import dagger.Binds import dagger.Module +import dagger.hilt.EntryPoint import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent @@ -13,3 +14,9 @@ interface IvyCoreBindingsModule { @Binds fun bindFeatures(features: IvyFeatures): Features } + +@EntryPoint +@InstallIn(SingletonComponent::class) +interface FeaturesEntryPoint { + fun getFeatures(): Features +} diff --git a/shared/domain/src/main/java/com/ivy/domain/features/Features.kt b/shared/domain/src/main/java/com/ivy/domain/features/Features.kt index eeb8a27ada..231f752c1c 100644 --- a/shared/domain/src/main/java/com/ivy/domain/features/Features.kt +++ b/shared/domain/src/main/java/com/ivy/domain/features/Features.kt @@ -8,6 +8,7 @@ interface Features { val showCategorySearchBar: BoolFeature val hideTotalBalance: BoolFeature val showDecimalNumber: BoolFeature + val standardKeypadLayout: BoolFeature val allFeatures: List } diff --git a/shared/domain/src/main/java/com/ivy/domain/features/IvyFeatures.kt b/shared/domain/src/main/java/com/ivy/domain/features/IvyFeatures.kt index b422e296cd..c6cb55b1e4 100644 --- a/shared/domain/src/main/java/com/ivy/domain/features/IvyFeatures.kt +++ b/shared/domain/src/main/java/com/ivy/domain/features/IvyFeatures.kt @@ -59,6 +59,14 @@ class IvyFeatures @Inject constructor() : Features { defaultValue = true ) + override val standardKeypadLayout = BoolFeature( + key = "enable_standard_keypad_layout", + group = FeatureGroup.Other, + name = "Standard keypad layout", + description = "Enable standard phone keypad layout instead of numeric calculator layout", + defaultValue = false + ) + override val allFeatures: List get() = listOf( sortCategoriesAscending, @@ -67,6 +75,7 @@ class IvyFeatures @Inject constructor() : Features { showTitleSuggestions, showCategorySearchBar, hideTotalBalance, + standardKeypadLayout /* will be uncommented when this functionality * will be available across the application in up-coming PRs showDecimalNumber diff --git a/temp/legacy-code/src/main/java/com/ivy/legacy/legacy/ui/theme/modal/edit/AmountModal.kt b/temp/legacy-code/src/main/java/com/ivy/legacy/legacy/ui/theme/modal/edit/AmountModal.kt index bdbfc5951e..07115b5a8f 100644 --- a/temp/legacy-code/src/main/java/com/ivy/legacy/legacy/ui/theme/modal/edit/AmountModal.kt +++ b/temp/legacy-code/src/main/java/com/ivy/legacy/legacy/ui/theme/modal/edit/AmountModal.kt @@ -27,6 +27,7 @@ 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.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource @@ -39,6 +40,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.ivy.design.l0_system.UI import com.ivy.design.l0_system.style +import com.ivy.domain.di.FeaturesEntryPoint import com.ivy.legacy.IvyWalletPreview import com.ivy.legacy.utils.amountToDouble import com.ivy.legacy.utils.amountToDoubleOrNull @@ -54,6 +56,7 @@ import com.ivy.wallet.ui.theme.components.IvyIcon import com.ivy.wallet.ui.theme.modal.IvyModal import com.ivy.wallet.ui.theme.modal.ModalPositiveButton import com.ivy.wallet.ui.theme.modal.modalPreviewActionRowHeight +import dagger.hilt.android.EntryPointAccessors import java.util.UUID import kotlin.math.truncate @@ -224,8 +227,7 @@ fun AmountInput( amount: String, decimalCountMax: Int = 2, setAmount: (String) -> Unit, - - ) { +) { var firstInput by remember { mutableStateOf(true) } AmountKeyboard( @@ -317,6 +319,38 @@ fun AmountKeyboard( FourthRowExtra: (@Composable RowScope.() -> Unit)? = null, onBackspace: () -> Unit, ) { + /** + * Retrieve `features` via EntryPointAccessors. `isStandardLayout` is stable and + * only changes via settings, so there isn't unnecessary recompositions. + * `isStandardLayout` doesn't change while the keyboard is shown. + * `AmountKeyboard` is self-contained, making it easy to reuse without passing parameters. + * Layout changes are rare, so recomposition has minimal impact on performance. + **/ + + val context = LocalContext.current + val features = remember { + EntryPointAccessors.fromApplication( + context.applicationContext, + FeaturesEntryPoint::class.java + ).getFeatures() + } + val isStandardLayout = features.standardKeypadLayout.asEnabledState() + + // Decide the order of the numbers based on the keypad layout + val countButtonValues = if (isStandardLayout) { + listOf( + listOf("1", "2", "3"), + listOf("4", "5", "6"), + listOf("7", "8", "9"), + ) + } else { // Calculator like numeric keypad layout + listOf( + listOf("7", "8", "9"), + listOf("4", "5", "6"), + listOf("1", "2", "3"), + ) + } + if (ZeroRow != null) { Row( modifier = Modifier @@ -331,97 +365,33 @@ fun AmountKeyboard( Spacer(Modifier.height(8.dp)) } - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = horizontalPadding), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly - - ) { - CircleNumberButton( - forCalculator = forCalculator, - value = "7", - onNumberPressed = onNumberPressed - ) - - CircleNumberButton( - forCalculator = forCalculator, - value = "8", - onNumberPressed = onNumberPressed - ) - - CircleNumberButton( - forCalculator = forCalculator, - value = "9", - onNumberPressed = onNumberPressed - ) - - FirstRowExtra?.invoke(this) - } - - Spacer(Modifier.height(8.dp)) - - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = horizontalPadding), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly - ) { - CircleNumberButton( - forCalculator = forCalculator, - value = "4", - onNumberPressed = onNumberPressed - ) - - CircleNumberButton( - forCalculator = forCalculator, - value = "5", - onNumberPressed = onNumberPressed - ) - - CircleNumberButton( - forCalculator = forCalculator, - value = "6", - onNumberPressed = onNumberPressed - ) - - SecondRowExtra?.invoke(this) - } - - Spacer(Modifier.height(8.dp)) - - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = horizontalPadding), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly - ) { - CircleNumberButton( - forCalculator = forCalculator, - value = "1", - onNumberPressed = onNumberPressed - ) - - CircleNumberButton( - forCalculator = forCalculator, - value = "2", - onNumberPressed = onNumberPressed - ) + // Loop through the rows to create CircleNumberButtons + countButtonValues.forEachIndexed { rowIndex, rowNumbers -> + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = horizontalPadding), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly + ) { + rowNumbers.forEach { num -> + CircleNumberButton( + forCalculator = forCalculator, + value = num, + onNumberPressed = onNumberPressed + ) + } - CircleNumberButton( - forCalculator = forCalculator, - value = "3", - onNumberPressed = onNumberPressed - ) + when (rowIndex) { + 0 -> FirstRowExtra?.invoke(this) + 1 -> SecondRowExtra?.invoke(this) + 2 -> ThirdRowExtra?.invoke(this) + } + } - ThirdRowExtra?.invoke(this) + Spacer(Modifier.height(8.dp)) } - Spacer(Modifier.height(8.dp)) - Row( modifier = Modifier .fillMaxWidth()