Let the order of FeatureFlag follow the order they are declared in the code.

Using map.keys does not guarantee that the order is kept, so using List instead.
This commit is contained in:
Benoit Marty
2025-10-17 10:44:03 +02:00
committed by Benoit Marty
parent 42c775d740
commit 828ee38c09

View File

@@ -13,13 +13,13 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.runtime.snapshots.SnapshotStateList
import dev.zacsweers.metro.Inject
import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.features.preferences.impl.developer.tracing.toLogLevel
@@ -31,7 +31,6 @@ import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.core.meta.BuildType
@@ -61,12 +60,8 @@ class DeveloperSettingsPresenter(
@Composable
override fun present(): DeveloperSettingsState {
val rageshakeState = rageshakePresenter.present()
val features = remember {
mutableStateMapOf<String, Feature>()
}
val enabledFeatures = remember {
mutableStateMapOf<String, Boolean>()
mutableStateListOf<EnabledFeature>()
}
val cacheSize = remember {
mutableStateOf<AsyncData<String>>(AsyncData.Uninitialized)
@@ -105,11 +100,10 @@ class DeveloperSettingsPresenter(
}
}
.forEach { feature ->
features[feature.key] = feature
enabledFeatures[feature.key] = featureFlagService.isFeatureEnabled(feature)
enabledFeatures.add(EnabledFeature(feature, featureFlagService.isFeatureEnabled(feature)))
}
}
val featureUiModels = createUiModels(features, enabledFeatures)
val featureUiModels = createUiModels(enabledFeatures)
val coroutineScope = rememberCoroutineScope()
// Compute cache size each time the clear cache action value is changed
LaunchedEffect(clearCacheAction.value.isSuccess()) {
@@ -119,7 +113,6 @@ class DeveloperSettingsPresenter(
fun handleEvents(event: DeveloperSettingsEvents) {
when (event) {
is DeveloperSettingsEvents.UpdateEnabledFeature -> coroutineScope.updateEnabledFeature(
features,
enabledFeatures,
event.feature,
event.isEnabled,
@@ -172,19 +165,17 @@ class DeveloperSettingsPresenter(
@Composable
private fun createUiModels(
features: SnapshotStateMap<String, Feature>,
enabledFeatures: SnapshotStateMap<String, Boolean>
enabledFeatures: SnapshotStateList<EnabledFeature>,
): List<FeatureUiModel> {
return features.values.map { feature ->
key(feature.key) {
val isEnabled = enabledFeatures[feature.key].orFalse()
remember(feature, isEnabled) {
return enabledFeatures.map { enabledFeature ->
key(enabledFeature.feature.key) {
remember(enabledFeature) {
FeatureUiModel(
key = feature.key,
title = feature.title,
description = feature.description,
key = enabledFeature.feature.key,
title = enabledFeature.feature.title,
description = enabledFeature.feature.description,
icon = null,
isEnabled = isEnabled
isEnabled = enabledFeature.isEnabled
)
}
}
@@ -192,15 +183,15 @@ class DeveloperSettingsPresenter(
}
private fun CoroutineScope.updateEnabledFeature(
features: SnapshotStateMap<String, Feature>,
enabledFeatures: SnapshotStateMap<String, Boolean>,
enabledFeatures: SnapshotStateList<EnabledFeature>,
featureUiModel: FeatureUiModel,
enabled: Boolean,
@Suppress("UNUSED_PARAMETER") triggerClearCache: () -> Unit,
) = launch {
val feature = features[featureUiModel.key] ?: return@launch
val featureIndex = enabledFeatures.indexOfFirst { it.feature.key == featureUiModel.key }.takeIf { it != -1 } ?: return@launch
val feature = enabledFeatures[featureIndex].feature
if (featureFlagService.setFeatureEnabled(feature, enabled)) {
enabledFeatures[featureUiModel.key] = enabled
enabledFeatures[featureIndex] = enabledFeatures[featureIndex].copy(isEnabled = enabled)
}
}
@@ -225,3 +216,8 @@ private fun customElementCallUrlValidator(url: String?): Boolean {
if (parsedUrl.host.isNullOrBlank()) error("Missing host")
}.isSuccess
}
private data class EnabledFeature(
val feature: Feature,
val isEnabled: Boolean,
)