diff --git a/screen/features/build.gradle.kts b/screen/features/build.gradle.kts index a81ae1964..3d1894585 100644 --- a/screen/features/build.gradle.kts +++ b/screen/features/build.gradle.kts @@ -12,4 +12,6 @@ dependencies { implementation(projects.shared.ui.core) implementation(projects.shared.ui.core) implementation(projects.shared.ui.navigation) + implementation(projects.temp.legacyCode) + implementation(projects.temp.oldDesign) } \ No newline at end of file diff --git a/screen/features/src/main/java/com/ivy/features/FeaturesScreen.kt b/screen/features/src/main/java/com/ivy/features/FeaturesScreen.kt index 774775006..7afb66bf7 100644 --- a/screen/features/src/main/java/com/ivy/features/FeaturesScreen.kt +++ b/screen/features/src/main/java/com/ivy/features/FeaturesScreen.kt @@ -20,17 +20,20 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import com.ivy.design.l0_system.UI +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel +import com.ivy.design.l0_system.style import com.ivy.navigation.navigation import com.ivy.navigation.screenScopedViewModel +import com.ivy.wallet.ui.theme.Gray +import com.ivy.wallet.ui.theme.components.IvySwitch import kotlinx.collections.immutable.ImmutableList @Composable @@ -104,8 +107,8 @@ private fun Title( @Composable private fun Content( - features: ImmutableList, - onToggleFeature: (Int) -> Unit, + features: ImmutableList, + onToggleFeature: (String) -> Unit, modifier: Modifier = Modifier, ) { LazyColumn( @@ -117,18 +120,25 @@ private fun Content( verticalArrangement = Arrangement.spacedBy(8.dp) ) { itemsIndexed(features) { index, item -> - FeatureRow( - feature = item, - onToggleClick = { onToggleFeature(index) } - ) + when (item) { + is FeatureHeader -> { + FeatureSectionDivider(text = item.name) + } + + is FeatureItem -> { + FeatureRow( + feature = item, + onToggleClick = { onToggleFeature(item.key) } + ) + } + } } } } -@OptIn(ExperimentalMaterial3Api::class) @Composable private fun FeatureRow( - feature: FeatureUi, + feature: FeatureItem, onToggleClick: () -> Unit, modifier: Modifier = Modifier, ) { @@ -155,7 +165,26 @@ private fun FeatureRow( } } Spacer(modifier = Modifier.width(8.dp)) - Switch(checked = feature.enabled, onCheckedChange = { onToggleClick() }) + IvySwitch(enabled = feature.enabled, onEnabledChange = { onToggleClick() }) } } } + +@Composable +private fun FeatureSectionDivider( + text: String, + color: Color = Gray +) { + Column { + Spacer(Modifier.height(32.dp)) + + Text( + modifier = Modifier.padding(start = 32.dp), + text = text, + style = UI.typo.b2.style( + color = color, + fontWeight = FontWeight.Bold + ) + ) + } +} diff --git a/screen/features/src/main/java/com/ivy/features/FeaturesUiEvent.kt b/screen/features/src/main/java/com/ivy/features/FeaturesUiEvent.kt index 74d700607..61af85dfa 100644 --- a/screen/features/src/main/java/com/ivy/features/FeaturesUiEvent.kt +++ b/screen/features/src/main/java/com/ivy/features/FeaturesUiEvent.kt @@ -1,5 +1,5 @@ package com.ivy.features sealed interface FeaturesUiEvent { - data class ToggleFeature(val index: Int) : FeaturesUiEvent + data class ToggleFeature(val key: String) : FeaturesUiEvent } diff --git a/screen/features/src/main/java/com/ivy/features/FeaturesUiState.kt b/screen/features/src/main/java/com/ivy/features/FeaturesUiState.kt index ee51b979d..01888f0e1 100644 --- a/screen/features/src/main/java/com/ivy/features/FeaturesUiState.kt +++ b/screen/features/src/main/java/com/ivy/features/FeaturesUiState.kt @@ -3,11 +3,16 @@ package com.ivy.features import kotlinx.collections.immutable.ImmutableList data class FeaturesUiState( - val features: ImmutableList, + val features: ImmutableList, ) -data class FeatureUi( +data class FeatureItem( + val key: String, val name: String, val enabled: Boolean, val description: String?, -) +) : Feature + +data class FeatureHeader(val name: String) : Feature + +interface Feature diff --git a/screen/features/src/main/java/com/ivy/features/FeaturesViewModel.kt b/screen/features/src/main/java/com/ivy/features/FeaturesViewModel.kt index 923e14c1d..316734b3a 100644 --- a/screen/features/src/main/java/com/ivy/features/FeaturesViewModel.kt +++ b/screen/features/src/main/java/com/ivy/features/FeaturesViewModel.kt @@ -31,14 +31,26 @@ class FeaturesViewModel @Inject constructor( } @Composable - fun getFeatures(): ImmutableList { - val allFeatures = features.allFeatures.map { - FeatureUi( - name = it.name ?: it.key, - description = it.description, - enabled = it.asEnabledState() - ) + fun getFeatures(): ImmutableList { + val groups = + features.allFeatures.distinctBy { it.group }.map { it.group?.name ?: "" }.sorted() + val allFeatures: MutableList = mutableListOf() + groups.forEach { group -> + allFeatures.add(FeatureHeader(name = group.toLowerCase().capitalize())) + val featuresByGroup: List = features + .allFeatures + .filter { it.group?.name == group } + .map { + FeatureItem( + key = it.key, + name = it.name ?: it.key, + description = it.description, + enabled = it.asEnabledState() + ) + } + allFeatures.addAll(featuresByGroup) } + return allFeatures.toImmutableList() } @@ -50,8 +62,8 @@ class FeaturesViewModel @Inject constructor( private fun toggleFeature(event: FeaturesUiEvent.ToggleFeature) { viewModelScope.launch { - val feature = features.allFeatures[event.index] - val enabled = feature.enabledFlow(context).first() ?: false + val feature = features.allFeatures.find { feature -> feature.key == event.key } + val enabled = feature!!.enabledFlow(context).first() ?: false feature.set(context, !enabled) } } diff --git a/shared/domain/src/main/java/com/ivy/domain/features/BoolFeature.kt b/shared/domain/src/main/java/com/ivy/domain/features/BoolFeature.kt index f12e7a86d..2f3907c38 100644 --- a/shared/domain/src/main/java/com/ivy/domain/features/BoolFeature.kt +++ b/shared/domain/src/main/java/com/ivy/domain/features/BoolFeature.kt @@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.map @Immutable class BoolFeature( val key: String, + val group: FeatureGroup? = null, val name: String? = null, val description: String? = null, private val defaultValue: Boolean = false diff --git a/shared/domain/src/main/java/com/ivy/domain/features/FeatureGroup.kt b/shared/domain/src/main/java/com/ivy/domain/features/FeatureGroup.kt new file mode 100644 index 000000000..cfef85621 --- /dev/null +++ b/shared/domain/src/main/java/com/ivy/domain/features/FeatureGroup.kt @@ -0,0 +1,5 @@ +package com.ivy.domain.features + +enum class FeatureGroup { + CATEGORY, ACCOUNT, OTHER +} \ No newline at end of file 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 a946c8a23..4cec178c4 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 @@ -8,6 +8,7 @@ class IvyFeatures @Inject constructor() : Features { override val sortCategoriesAlphabetically = BoolFeature( key = "sort_categories_alphabetically", + group = FeatureGroup.OTHER, name = "Sort Categories Alphabetically", description = "Sort income and expenses" + " categories alphabetically" @@ -15,18 +16,21 @@ class IvyFeatures @Inject constructor() : Features { override val compactAccountsMode = BoolFeature( key = "compact_account_ui", + group = FeatureGroup.ACCOUNT, name = "Compact account UI", description = "Enables more compact and dense UI for the \"Accounts\" tab" ) override val compactCategoriesMode = BoolFeature( key = "compact_categories_ui", + group = FeatureGroup.CATEGORY, name = "Compact category UI", description = "Activates a more streamlined and space-efficient interface for the \"Categories\" Screen" ) override val showTitleSuggestions = BoolFeature( key = "show_title_suggestions", + group = FeatureGroup.OTHER, name = "Show previous title suggestions", description = "Enables display of previous transaction titles when editing or creating a new transaction", defaultValue = true @@ -34,6 +38,7 @@ class IvyFeatures @Inject constructor() : Features { override val showCategorySearchBar = BoolFeature( key = "search_categories", + group = FeatureGroup.CATEGORY, name = "Search categories", description = "Show search bar in category screen", defaultValue = true @@ -41,6 +46,7 @@ class IvyFeatures @Inject constructor() : Features { override val hideTotalBalance = BoolFeature( key = "hide_total_balance", + group = FeatureGroup.ACCOUNT, name = "Hide total balance", description = "Enable hide the total balance from the accounts tab", defaultValue = false