From aa4243c5c3ed7f7b62cb46049116ec3dd8fbaf26 Mon Sep 17 00:00:00 2001 From: kirich1409 Date: Mon, 18 May 2026 11:38:45 +0300 Subject: [PATCH 1/2] Register enum converter for CheckoutVariant in sample The sample observes an enum-typed flag (CheckoutVariant) via DataStoreConfigValueProvider, but never registered a TypeConverter for the enum. DataStore preferences only support primitive keys, so observation crashed with IllegalArgumentException on launch. Register enumConverter() on the provider before building ConfigValues. Co-Authored-By: Claude Opus 4.7 --- sample/android-app/build.gradle.kts | 1 + .../androidbroadcast/featured/sample/MainActivity.kt | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sample/android-app/build.gradle.kts b/sample/android-app/build.gradle.kts index dc3e224..3f4c463 100644 --- a/sample/android-app/build.gradle.kts +++ b/sample/android-app/build.gradle.kts @@ -48,6 +48,7 @@ dependencies { implementation(project(":sample:shared")) implementation(project(":featured-debug-ui")) implementation(project(":featured-platform")) + implementation(project(":providers:datastore")) implementation(libs.androidx.activity.compose) implementation(libs.androidx.appcompat) } diff --git a/sample/android-app/src/main/kotlin/dev/androidbroadcast/featured/sample/MainActivity.kt b/sample/android-app/src/main/kotlin/dev/androidbroadcast/featured/sample/MainActivity.kt index e9f0813..aa9b964 100644 --- a/sample/android-app/src/main/kotlin/dev/androidbroadcast/featured/sample/MainActivity.kt +++ b/sample/android-app/src/main/kotlin/dev/androidbroadcast/featured/sample/MainActivity.kt @@ -9,9 +9,13 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import dev.androidbroadcast.featured.CheckoutVariant import dev.androidbroadcast.featured.ConfigValues import dev.androidbroadcast.featured.SampleApp +import dev.androidbroadcast.featured.datastore.DataStoreConfigValueProvider +import dev.androidbroadcast.featured.datastore.registerConverter import dev.androidbroadcast.featured.debugui.FeatureFlagsDebugScreen +import dev.androidbroadcast.featured.enumConverter import dev.androidbroadcast.featured.platform.defaultLocalProvider class MainActivity : ComponentActivity() { @@ -19,7 +23,12 @@ class MainActivity : ComponentActivity() { // In production, move to Application or a DI singleton to avoid // recreating (and re-opening) the DataStore file on every rotation. private val configValues by lazy { - ConfigValues(localProvider = defaultLocalProvider(applicationContext)) + val localProvider = defaultLocalProvider(applicationContext) + // DataStore only handles primitives natively; register a converter so that the + // enum-typed checkoutVariant flag can be persisted and observed without throwing. + (localProvider as? DataStoreConfigValueProvider) + ?.registerConverter(enumConverter()) + ConfigValues(localProvider = localProvider) } override fun onCreate(savedInstanceState: Bundle?) { From e01b3326ec131cc718138cce2f05755e110fb6bc Mon Sep 17 00:00:00 2001 From: kirich1409 Date: Mon, 18 May 2026 11:51:18 +0300 Subject: [PATCH 2/2] Register sample flags and fix status-bar overlap Register every flag in SampleFeatureFlags with FlagRegistry on Application start so the Debug UI renders the list instead of the empty state. Apply statusBarsPadding() to the home-screen top row so the "Debug flags" button is reachable under enableEdgeToEdge. Co-Authored-By: Claude Opus 4.7 --- .../featured/sample/MainActivity.kt | 4 ++++ .../androidbroadcast/featured/FeaturedSample.kt | 2 ++ .../dev/androidbroadcast/featured/SampleApp.kt | 16 ++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/sample/android-app/src/main/kotlin/dev/androidbroadcast/featured/sample/MainActivity.kt b/sample/android-app/src/main/kotlin/dev/androidbroadcast/featured/sample/MainActivity.kt index aa9b964..7156e6b 100644 --- a/sample/android-app/src/main/kotlin/dev/androidbroadcast/featured/sample/MainActivity.kt +++ b/sample/android-app/src/main/kotlin/dev/androidbroadcast/featured/sample/MainActivity.kt @@ -17,12 +17,16 @@ import dev.androidbroadcast.featured.datastore.registerConverter import dev.androidbroadcast.featured.debugui.FeatureFlagsDebugScreen import dev.androidbroadcast.featured.enumConverter import dev.androidbroadcast.featured.platform.defaultLocalProvider +import dev.androidbroadcast.featured.registerSampleFlags class MainActivity : ComponentActivity() { // ConfigValues is held at Activity scope for this sample. // In production, move to Application or a DI singleton to avoid // recreating (and re-opening) the DataStore file on every rotation. private val configValues by lazy { + // Populate FlagRegistry so FeatureFlagsDebugScreen can discover all flags via FlagRegistry.all(). + registerSampleFlags() + val localProvider = defaultLocalProvider(applicationContext) // DataStore only handles primitives natively; register a converter so that the // enum-typed checkoutVariant flag can be persisted and observed without throwing. diff --git a/sample/shared/src/commonMain/kotlin/dev/androidbroadcast/featured/FeaturedSample.kt b/sample/shared/src/commonMain/kotlin/dev/androidbroadcast/featured/FeaturedSample.kt index 18399bb..d54e52d 100644 --- a/sample/shared/src/commonMain/kotlin/dev/androidbroadcast/featured/FeaturedSample.kt +++ b/sample/shared/src/commonMain/kotlin/dev/androidbroadcast/featured/FeaturedSample.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card @@ -51,6 +52,7 @@ public fun FeaturedSample( Column( modifier = modifier + .statusBarsPadding() .padding(16.dp) .fillMaxSize(), verticalArrangement = Arrangement.spacedBy(16.dp), diff --git a/sample/shared/src/commonMain/kotlin/dev/androidbroadcast/featured/SampleApp.kt b/sample/shared/src/commonMain/kotlin/dev/androidbroadcast/featured/SampleApp.kt index 56a9cc0..a91be4c 100644 --- a/sample/shared/src/commonMain/kotlin/dev/androidbroadcast/featured/SampleApp.kt +++ b/sample/shared/src/commonMain/kotlin/dev/androidbroadcast/featured/SampleApp.kt @@ -4,6 +4,22 @@ package dev.androidbroadcast.featured import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import dev.androidbroadcast.featured.registry.FlagRegistry + +/** + * Registers all [SampleFeatureFlags] with [FlagRegistry] so that [FeatureFlagsDebugScreen] + * can discover them via [FlagRegistry.all]. Call once on application start before opening + * the debug UI. Duplicate calls are safe — the registry ignores already-registered params. + */ +public fun registerSampleFlags() { + listOf( + SampleFeatureFlags.mainButtonRed, + SampleFeatureFlags.newFeatureSectionEnabled, + SampleFeatureFlags.newCheckout, + SampleFeatureFlags.promoBannerEnabled, + SampleFeatureFlags.checkoutVariant, + ).forEach(FlagRegistry::register) +} /** * Root composable for the sample application.