Skip to content
This repository has been archived by the owner on Nov 5, 2024. It is now read-only.

[FEATURE] Advanced features grouping #3563

Merged
merged 3 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions screen/features/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ dependencies {
implementation(projects.shared.ui.core)
implementation(projects.shared.ui.core)
implementation(projects.shared.ui.navigation)
implementation(projects.temp.legacyCode)
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
implementation(projects.temp.oldDesign)
}
51 changes: 40 additions & 11 deletions screen/features/src/main/java/com/ivy/features/FeaturesScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -104,8 +107,8 @@ private fun Title(

@Composable
private fun Content(
features: ImmutableList<FeatureUi>,
onToggleFeature: (Int) -> Unit,
features: ImmutableList<Feature>,
onToggleFeature: (String) -> Unit,
modifier: Modifier = Modifier,
) {
LazyColumn(
Expand All @@ -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,
) {
Expand All @@ -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
)
)
}
}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ package com.ivy.features
import kotlinx.collections.immutable.ImmutableList

data class FeaturesUiState(
val features: ImmutableList<FeatureUi>,
val features: ImmutableList<Feature>,
)

data class FeatureUi(
data class FeatureItem(
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
val key: String,
val name: String,
val enabled: Boolean,
val description: String?,
)
) : Feature

data class FeatureHeader(val name: String) : Feature
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved

interface Feature
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,26 @@ class FeaturesViewModel @Inject constructor(
}

@Composable
fun getFeatures(): ImmutableList<FeatureUi> {
val allFeatures = features.allFeatures.map {
FeatureUi(
name = it.name ?: it.key,
description = it.description,
enabled = it.asEnabledState()
)
fun getFeatures(): ImmutableList<Feature> {
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
val groups =
features.allFeatures.distinctBy { it.group }.map { it.group?.name ?: "" }.sorted()
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
val allFeatures: MutableList<Feature> = mutableListOf()
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
groups.forEach { group ->
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
allFeatures.add(FeatureHeader(name = group.toLowerCase().capitalize()))
val featuresByGroup: List<Feature> = 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()
}

Expand All @@ -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
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
feature.set(context, !enabled)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.ivy.domain.features

enum class FeatureGroup {
CATEGORY, ACCOUNT, OTHER
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,45 @@ 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"
)

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
)

override val showCategorySearchBar = BoolFeature(
key = "search_categories",
group = FeatureGroup.CATEGORY,
name = "Search categories",
description = "Show search bar in category screen",
defaultValue = true
)

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
Expand Down