Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 3 additions & 3 deletions iosApp/iosApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\nif [ -z \"$JAVA_HOME\" ] || [ ! -d \"$JAVA_HOME\" ]; then\n export JAVA_HOME=$(/usr/libexec/java_home -v 21 2>/dev/null || /usr/libexec/java_home 2>/dev/null)\nfi\ncd \"$SRCROOT/..\"\n./gradlew :sample:embedAndSignAppleFrameworkForXcode\n";
shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\nif [ -z \"$JAVA_HOME\" ] || [ ! -d \"$JAVA_HOME\" ]; then\n export JAVA_HOME=$(/usr/libexec/java_home -v 21 2>/dev/null || /usr/libexec/java_home 2>/dev/null)\nfi\ncd \"$SRCROOT/..\"\n./gradlew :sample:shared:embedAndSignAppleFrameworkForXcode\n";
};
/* End PBXShellScriptBuildPhase section */

Expand Down Expand Up @@ -300,7 +300,7 @@
ENABLE_PREVIEWS = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../sample/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)",
"$(SRCROOT)/../sample/shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iosApp/Info.plist;
Expand Down Expand Up @@ -333,7 +333,7 @@
ENABLE_PREVIEWS = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../sample/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)",
"$(SRCROOT)/../sample/shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iosApp/Info.plist;
Expand Down
2 changes: 1 addition & 1 deletion sample/android-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ android {
}

dependencies {
implementation(project(":sample"))
implementation(project(":sample:shared"))
implementation(project(":featured-debug-ui"))
implementation(project(":featured-platform"))
implementation(libs.androidx.activity.compose)
Expand Down
33 changes: 33 additions & 0 deletions sample/desktop/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import org.jetbrains.compose.desktop.application.dsl.TargetFormat

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
}

kotlin {
jvmToolchain(21)
jvm()

sourceSets {
jvmMain.dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.kotlinx.coroutinesSwing)
implementation(project(":sample:shared"))
}
}
}

compose.desktop {
application {
mainClass = "dev.androidbroadcast.featured.MainDesktop"

nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "dev.androidbroadcast.featured"
// Matches versionName in :sample:android-app
packageVersion = "1.0.0"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fun main() {
onCloseRequest = ::exitApplication,
title = "Featured",
) {
FeaturedSample(configValues = configValues)
SampleApp(configValues = configValues)
}
}
}
18 changes: 0 additions & 18 deletions sample/build.gradle.kts → sample/shared/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
Expand Down Expand Up @@ -54,22 +53,5 @@ kotlin {
implementation(project(":core"))
implementation(project(":featured-registry"))
}

jvmMain.dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.kotlinx.coroutinesSwing)
}
}
}

compose.desktop {
application {
mainClass = "dev.androidbroadcast.featured.MainDesktop"

nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "dev.androidbroadcast.featured"
packageVersion = "1.0.0"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,8 @@ import kotlinx.coroutines.launch
public class SampleViewModel(
private val configValues: ConfigValues,
) : ViewModel() {
// --- @LocalFlag: main_button_red ---

public val flagActive: StateFlow<Boolean> =
configValues
.observe(SampleFeatureFlags.mainButtonRed)
.map { it.value }
.stateIn(
initialValue = SampleFeatureFlags.mainButtonRed.defaultValue,
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5_000L),
)
configValues.asStateFlow(SampleFeatureFlags.mainButtonRed, viewModelScope)

public val mainButtonColor: StateFlow<MainButtonColor> =
flagActive
Expand All @@ -39,53 +30,26 @@ public class SampleViewModel(
}
}

// --- @LocalFlag: new_feature_section_enabled (isEnabled guard pattern) ---

/**
* Controls visibility of the "New Feature" section.
* Demonstrates the [ConfigParam.isEnabled] guard pattern for entry-point gating.
*/
public val newFeatureSectionEnabled: StateFlow<Boolean> =
configValues
.observe(SampleFeatureFlags.newFeatureSectionEnabled)
.map { it.value }
.stateIn(
initialValue = SampleFeatureFlags.newFeatureSectionEnabled.defaultValue,
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5_000L),
)

// --- @RemoteFlag: promo_banner_enabled ---
configValues.asStateFlow(SampleFeatureFlags.newFeatureSectionEnabled, viewModelScope)

/**
* Whether the promotional banner should be shown.
* In production this would be driven by Firebase Remote Config.
*/
public val promoBannerEnabled: StateFlow<Boolean> =
configValues
.observe(SampleFeatureFlags.promoBannerEnabled)
.map { it.value }
.stateIn(
initialValue = SampleFeatureFlags.promoBannerEnabled.defaultValue,
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5_000L),
)

// --- @RemoteFlag: checkout_variant ---
configValues.asStateFlow(SampleFeatureFlags.promoBannerEnabled, viewModelScope)

/**
* The active checkout variant, driven remotely.
* Demonstrates multivariate enum flags resolved from a remote provider.
*/
public val checkoutVariant: StateFlow<CheckoutVariant> =
configValues
.observe(SampleFeatureFlags.checkoutVariant)
.map { it.value }
.stateIn(
initialValue = SampleFeatureFlags.checkoutVariant.defaultValue,
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5_000L),
)
configValues.asStateFlow(SampleFeatureFlags.checkoutVariant, viewModelScope)

public sealed interface MainButtonColor {
public data object Red : MainButtonColor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ import platform.UIKit.UIViewController
public fun MainViewController(): UIViewController {
val configValues = ConfigValues(localProvider = InMemoryConfigValueProvider())
return ComposeUIViewController {
FeaturedSample(configValues = configValues)
SampleApp(configValues = configValues)
}
}
3 changes: 2 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ plugins {
}

include(":featured-gradle-plugin")
include(":sample")
include(":sample:shared")
include(":sample:android-app")
include(":sample:desktop")
include(":core")
include(":featured-compose")
include(":featured-registry")
Expand Down
Loading