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
1 change: 1 addition & 0 deletions .changeset/android-v4-major.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
- **Breaking:** remove the deprecated `evaluationEnvironments` config option; use `evaluationContexts` instead
- **Breaking:** remove the deprecated `getFeatureFlagPayload()`; use `getFeatureFlagResult(key)?.payload` instead
- **Breaking:** remove the deprecated `PostHogSessionReplayConfig.debouncerDelayMs`; use `throttleDelayMs` instead
- **Breaking:** replace `PostHogOnFeatureFlags` with `PostHogFeatureFlagsCallback` in `PostHogConfig.onFeatureFlags` and `reloadFeatureFlags()`; it receives a `PostHogFeatureFlagsLoaded` with the enabled flags, their values, and `errorsLoading`
5 changes: 5 additions & 0 deletions .changeset/server-keep-on-feature-flags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'posthog-server': minor
---

Move `PostHogOnFeatureFlags` into `posthog-server`; its API is unchanged
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package com.posthog.android
import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.gson.GsonBuilder
import com.posthog.PostHogFeatureFlagsCallback
import com.posthog.PostHogInterface
import com.posthog.PostHogOnFeatureFlags
import com.posthog.internal.PostHogContext
import com.posthog.internal.PostHogDateProvider
import com.posthog.internal.PostHogDeviceDateProvider
Expand Down Expand Up @@ -67,7 +67,7 @@ internal class PostHogAndroidEventSnapshotsTest {
fun `batch request and enriched event shapes match snapshot`() {
val fixture = createFixture()
val flagsLoaded = CountDownLatch(1)
fixture.config.onFeatureFlags = PostHogOnFeatureFlags { flagsLoaded.countDown() }
fixture.config.onFeatureFlags = PostHogFeatureFlagsCallback { flagsLoaded.countDown() }
val sut = fixture.client

sut.capture(
Expand Down Expand Up @@ -115,7 +115,7 @@ internal class PostHogAndroidEventSnapshotsTest {
mapOf("industry" to "analytics"),
reloadFeatureFlags = false,
)
fixture.client.reloadFeatureFlags(PostHogOnFeatureFlags { loaded.countDown() })
fixture.client.reloadFeatureFlags(PostHogFeatureFlagsCallback { loaded.countDown() })

assertTrue(loaded.await(10, TimeUnit.SECONDS), "Feature flags request did not finish")
val request = fixture.server.takeRequests("/flags/?v=2").single()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.posthog.android.sample

import android.app.Application
import android.os.StrictMode
import com.posthog.PostHogOnFeatureFlags
import com.posthog.PostHogFeatureFlagsCallback
import com.posthog.android.PostHogAndroid
import com.posthog.android.PostHogAndroidConfig

Expand Down Expand Up @@ -39,7 +39,7 @@ class MyApp : Application() {
sessionReplay = true
preloadFeatureFlags = true
sendFeatureFlagEvent = false
onFeatureFlags = PostHogOnFeatureFlags { print("feature flags loaded") }
onFeatureFlags = PostHogFeatureFlagsCallback { print("feature flags loaded") }
addBeforeSend { event ->
if (event.event == "test_event") {
null
Expand Down
4 changes: 4 additions & 0 deletions posthog-server/api/posthog-server.api
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
public abstract interface class com/posthog/PostHogOnFeatureFlags {
public abstract fun loaded ()V
}

public final class com/posthog/server/PostHog : com/posthog/PostHogStateless, com/posthog/server/PostHogInterface {
public static final field Companion Lcom/posthog/server/PostHog$Companion;
public fun <init> ()V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,6 @@ public open class PostHogConfig constructor(
maxBatchSize = maxBatchSize,
flushIntervalSeconds = flushIntervalSeconds,
encryption = encryption,
onFeatureFlags = onFeatureFlags,
proxy = proxy,
remoteConfigProvider = { config, api, _, _, _, _ ->
PostHogFeatureFlags(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ internal class PostHogConfigTest {
assertEquals(30, coreConfig.maxBatchSize)
assertEquals(45, coreConfig.flushIntervalSeconds)
assertEquals(mockEncryption, coreConfig.encryption)
assertEquals(mockOnFeatureFlags, coreConfig.onFeatureFlags)
assertNull(coreConfig.onFeatureFlags)
}

@Test
Expand Down
41 changes: 24 additions & 17 deletions posthog/api/posthog.api
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public final class com/posthog/PostHog : com/posthog/PostHogStateless, com/posth
public fun optOut ()V
public fun register (Ljava/lang/String;Ljava/lang/Object;)V
public fun registerPushNotificationToken (Ljava/lang/String;Ljava/lang/String;)V
public fun reloadFeatureFlags (Lcom/posthog/PostHogOnFeatureFlags;)V
public fun reloadFeatureFlags (Lcom/posthog/PostHogFeatureFlagsCallback;)V
public fun reset ()V
public fun resetGroupPropertiesForFlags (Ljava/lang/String;Z)V
public fun resetPersonPropertiesForFlags (Z)V
Expand Down Expand Up @@ -101,7 +101,7 @@ public final class com/posthog/PostHog$Companion : com/posthog/PostHogInterface
public final fun overrideSharedInstance (Lcom/posthog/PostHogInterface;)V
public fun register (Ljava/lang/String;Ljava/lang/Object;)V
public fun registerPushNotificationToken (Ljava/lang/String;Ljava/lang/String;)V
public fun reloadFeatureFlags (Lcom/posthog/PostHogOnFeatureFlags;)V
public fun reloadFeatureFlags (Lcom/posthog/PostHogFeatureFlagsCallback;)V
public fun reset ()V
public fun resetGroupPropertiesForFlags (Ljava/lang/String;Z)V
public fun resetPersonPropertiesForFlags (Z)V
Expand Down Expand Up @@ -156,8 +156,8 @@ public class com/posthog/PostHogConfig {
public static final field DEFAULT_MAX_QUEUE_SIZE I
public static final field DEFAULT_US_ASSETS_HOST Ljava/lang/String;
public static final field DEFAULT_US_HOST Ljava/lang/String;
public fun <init> (Ljava/lang/String;Ljava/lang/String;ZZZIZLjava/util/List;ZZIIIIIILcom/posthog/PostHogEncryption;Lcom/posthog/PostHogOnFeatureFlags;ZLkotlin/jvm/functions/Function1;ZLcom/posthog/PersonProfiles;ZLjava/net/Proxy;Lcom/posthog/surveys/PostHogSurveysConfig;Lcom/posthog/logs/PostHogLogsConfig;Lkotlin/jvm/functions/Function6;Lkotlin/jvm/functions/Function5;Lcom/posthog/errortracking/PostHogErrorTrackingConfig;Ljava/lang/String;Lcom/posthog/PostHogBootstrapConfig;Lkotlin/jvm/functions/Function3;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;ZZZIZLjava/util/List;ZZIIIIIILcom/posthog/PostHogEncryption;Lcom/posthog/PostHogOnFeatureFlags;ZLkotlin/jvm/functions/Function1;ZLcom/posthog/PersonProfiles;ZLjava/net/Proxy;Lcom/posthog/surveys/PostHogSurveysConfig;Lcom/posthog/logs/PostHogLogsConfig;Lkotlin/jvm/functions/Function6;Lkotlin/jvm/functions/Function5;Lcom/posthog/errortracking/PostHogErrorTrackingConfig;Ljava/lang/String;Lcom/posthog/PostHogBootstrapConfig;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;ZZZIZLjava/util/List;ZZIIIIIILcom/posthog/PostHogEncryption;Lcom/posthog/PostHogFeatureFlagsCallback;ZLkotlin/jvm/functions/Function1;ZLcom/posthog/PersonProfiles;ZLjava/net/Proxy;Lcom/posthog/surveys/PostHogSurveysConfig;Lcom/posthog/logs/PostHogLogsConfig;Lkotlin/jvm/functions/Function6;Lkotlin/jvm/functions/Function5;Lcom/posthog/errortracking/PostHogErrorTrackingConfig;Ljava/lang/String;Lcom/posthog/PostHogBootstrapConfig;Lkotlin/jvm/functions/Function3;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;ZZZIZLjava/util/List;ZZIIIIIILcom/posthog/PostHogEncryption;Lcom/posthog/PostHogFeatureFlagsCallback;ZLkotlin/jvm/functions/Function1;ZLcom/posthog/PersonProfiles;ZLjava/net/Proxy;Lcom/posthog/surveys/PostHogSurveysConfig;Lcom/posthog/logs/PostHogLogsConfig;Lkotlin/jvm/functions/Function6;Lkotlin/jvm/functions/Function5;Lcom/posthog/errortracking/PostHogErrorTrackingConfig;Ljava/lang/String;Lcom/posthog/PostHogBootstrapConfig;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun addBeforeSend (Lcom/posthog/PostHogBeforeSend;)V
public final fun addIntegration (Lcom/posthog/PostHogIntegration;)V
public final fun getBeforeSendList ()Ljava/util/List;
Expand Down Expand Up @@ -186,7 +186,7 @@ public class com/posthog/PostHogConfig {
public final fun getMaxQueueSize ()I
public final fun getMaxRetries ()I
public final fun getNetworkStatus ()Lcom/posthog/internal/PostHogNetworkStatus;
public final fun getOnFeatureFlags ()Lcom/posthog/PostHogOnFeatureFlags;
public final fun getOnFeatureFlags ()Lcom/posthog/PostHogFeatureFlagsCallback;
public final fun getOptOut ()Z
public final fun getPersistOptOut ()Z
public final fun getPersonProfiles ()Lcom/posthog/PersonProfiles;
Expand Down Expand Up @@ -238,7 +238,7 @@ public class com/posthog/PostHogConfig {
public final fun setMaxQueueSize (I)V
public final fun setMaxRetries (I)V
public final fun setNetworkStatus (Lcom/posthog/internal/PostHogNetworkStatus;)V
public final fun setOnFeatureFlags (Lcom/posthog/PostHogOnFeatureFlags;)V
public final fun setOnFeatureFlags (Lcom/posthog/PostHogFeatureFlagsCallback;)V
public final fun setOptOut (Z)V
public final fun setPersistOptOut (Z)V
public final fun setPersonProfiles (Lcom/posthog/PersonProfiles;)V
Expand Down Expand Up @@ -346,6 +346,17 @@ public final class com/posthog/PostHogEventName$Companion {
public abstract interface annotation class com/posthog/PostHogExperimental : java/lang/annotation/Annotation {
}

public abstract interface class com/posthog/PostHogFeatureFlagsCallback {
public abstract fun loaded (Lcom/posthog/PostHogFeatureFlagsLoaded;)V
}

public final class com/posthog/PostHogFeatureFlagsLoaded {
public fun <init> (Ljava/util/Map;Z)V
public final fun getErrorsLoading ()Z
public final fun getFlags ()Ljava/util/List;
public final fun getVariants ()Ljava/util/Map;
}

public abstract interface class com/posthog/PostHogIntegration {
public fun install (Lcom/posthog/PostHogInterface;)V
public fun onChange ()V
Expand Down Expand Up @@ -398,8 +409,8 @@ public abstract interface class com/posthog/PostHogInterface : com/posthog/PostH
public abstract fun isSessionReplayActive ()Z
public abstract fun register (Ljava/lang/String;Ljava/lang/Object;)V
public abstract fun registerPushNotificationToken (Ljava/lang/String;Ljava/lang/String;)V
public abstract fun reloadFeatureFlags (Lcom/posthog/PostHogOnFeatureFlags;)V
public static synthetic fun reloadFeatureFlags$default (Lcom/posthog/PostHogInterface;Lcom/posthog/PostHogOnFeatureFlags;ILjava/lang/Object;)V
public abstract fun reloadFeatureFlags (Lcom/posthog/PostHogFeatureFlagsCallback;)V
public static synthetic fun reloadFeatureFlags$default (Lcom/posthog/PostHogInterface;Lcom/posthog/PostHogFeatureFlagsCallback;ILjava/lang/Object;)V
public abstract fun reset ()V
public abstract fun resetGroupPropertiesForFlags (Ljava/lang/String;Z)V
public static synthetic fun resetGroupPropertiesForFlags$default (Lcom/posthog/PostHogInterface;Ljava/lang/String;ZILjava/lang/Object;)V
Expand Down Expand Up @@ -433,7 +444,7 @@ public final class com/posthog/PostHogInterface$DefaultImpls {
public static synthetic fun getFeatureFlagResult$default (Lcom/posthog/PostHogInterface;Ljava/lang/String;Ljava/lang/Boolean;ILjava/lang/Object;)Lcom/posthog/FeatureFlagResult;
public static synthetic fun group$default (Lcom/posthog/PostHogInterface;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)V
public static synthetic fun isFeatureEnabled$default (Lcom/posthog/PostHogInterface;Ljava/lang/String;ZLjava/lang/Boolean;ILjava/lang/Object;)Z
public static synthetic fun reloadFeatureFlags$default (Lcom/posthog/PostHogInterface;Lcom/posthog/PostHogOnFeatureFlags;ILjava/lang/Object;)V
public static synthetic fun reloadFeatureFlags$default (Lcom/posthog/PostHogInterface;Lcom/posthog/PostHogFeatureFlagsCallback;ILjava/lang/Object;)V
public static synthetic fun resetGroupPropertiesForFlags$default (Lcom/posthog/PostHogInterface;Ljava/lang/String;ZILjava/lang/Object;)V
public static synthetic fun resetPersonPropertiesForFlags$default (Lcom/posthog/PostHogInterface;ZILjava/lang/Object;)V
public static synthetic fun screen$default (Lcom/posthog/PostHogInterface;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)V
Expand All @@ -455,10 +466,6 @@ public final class com/posthog/PostHogOkHttpInterceptor : okhttp3/Interceptor {
public fun intercept (Lokhttp3/Interceptor$Chain;)Lokhttp3/Response;
}

public abstract interface class com/posthog/PostHogOnFeatureFlags {
public abstract fun loaded ()V
}

public abstract interface class com/posthog/PostHogOptInReceiver {
public abstract fun onOptIn ()V
}
Expand Down Expand Up @@ -1062,10 +1069,10 @@ public final class com/posthog/internal/PostHogRemoteConfig : com/posthog/intern
public fun isMinimalFlagCalledEventsEnabled ()Z
public final fun isNativeCrashCaptureEnabled ()Z
public final fun isSessionReplayFlagActive ()Z
public final fun loadFeatureFlags (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lcom/posthog/PostHogOnFeatureFlags;Lcom/posthog/PostHogOnFeatureFlags;)V
public static synthetic fun loadFeatureFlags$default (Lcom/posthog/internal/PostHogRemoteConfig;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lcom/posthog/PostHogOnFeatureFlags;Lcom/posthog/PostHogOnFeatureFlags;ILjava/lang/Object;)V
public final fun loadRemoteConfig (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lcom/posthog/PostHogOnFeatureFlags;Lcom/posthog/PostHogOnFeatureFlags;)V
public static synthetic fun loadRemoteConfig$default (Lcom/posthog/internal/PostHogRemoteConfig;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lcom/posthog/PostHogOnFeatureFlags;Lcom/posthog/PostHogOnFeatureFlags;ILjava/lang/Object;)V
public final fun loadFeatureFlags (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function0;Lcom/posthog/PostHogFeatureFlagsCallback;)V
public static synthetic fun loadFeatureFlags$default (Lcom/posthog/internal/PostHogRemoteConfig;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function0;Lcom/posthog/PostHogFeatureFlagsCallback;ILjava/lang/Object;)V
public final fun loadRemoteConfig (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function0;Lcom/posthog/PostHogFeatureFlagsCallback;)V
public static synthetic fun loadRemoteConfig$default (Lcom/posthog/internal/PostHogRemoteConfig;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function0;Lcom/posthog/PostHogFeatureFlagsCallback;ILjava/lang/Object;)V
public final fun makeSamplingDecision (Ljava/lang/String;)Z
public final fun persistPushConfigCache ()V
public final fun resetGroupPropertiesForFlags (Ljava/lang/String;)V
Expand Down
32 changes: 18 additions & 14 deletions posthog/src/main/java/com/posthog/PostHog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ public class PostHog private constructor(
private var isPersonProcessingLoaded: Boolean = false

// this is called if the feature flags are loaded for the first time and recording isn't started yet
private val internalOnFeatureFlagsLoaded =
PostHogOnFeatureFlags {
private val internalOnFeatureFlagsLoaded: () -> Unit =
{
// under setupLock so a concurrent optOut can't uninstall replay between the check and the start
synchronized(setupLock) {
sessionReplayHandler?.let {
Expand Down Expand Up @@ -398,8 +398,8 @@ public class PostHog private constructor(
// Bootstrap already seeded the flags in RemoteConfig's init; fire the flags-loaded
// callbacks now so listeners aren't blocked on the first network response.
if (remoteConfig?.hasBootstrapFlags() == true) {
notifyFeatureFlagsCallback(internalOnFeatureFlagsLoaded)
notifyFeatureFlagsCallback(config.onFeatureFlags)
internalOnFeatureFlagsLoaded()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 · Restore exception isolation for the bootstrap internal callback

With bootstrap flags and session replay enabled, an exception from the replay handler now escapes internalOnFeatureFlagsLoaded() into setup's outer catch. This skips the user callback, initial config/flags request, and bootstrap identity reconciliation, leaving setup incomplete. The previous helper isolated this failure; catch and log the internal callback exception before continuing.

notifyFeatureFlagsCallback(config.onFeatureFlags, remoteConfig?.getFeatureFlags(), errorsLoading = false)
}
when {
config.remoteConfig ->
Expand Down Expand Up @@ -1922,18 +1922,22 @@ public class PostHog private constructor(
}

// Invokes the feature flags callback, swallowing exceptions like runOnFeatureFlagsCallbacks.
private fun notifyFeatureFlagsCallback(onFeatureFlags: PostHogOnFeatureFlags?) {
private fun notifyFeatureFlagsCallback(
onFeatureFlags: PostHogFeatureFlagsCallback?,
featureFlags: Map<String, Any>?,
errorsLoading: Boolean,
) {
try {
onFeatureFlags?.loaded()
onFeatureFlags?.loaded(PostHogFeatureFlagsLoaded(featureFlags ?: emptyMap(), errorsLoading))
} catch (e: Throwable) {
config?.logger?.log("Executing the feature flags callback failed: $e")
}
}

public override fun reloadFeatureFlags(onFeatureFlags: PostHogOnFeatureFlags?) {
public override fun reloadFeatureFlags(onFeatureFlags: PostHogFeatureFlagsCallback?) {
if (!isEnabled()) {
// Still invoke the callback so awaiting callers aren't left hanging.
notifyFeatureFlagsCallback(onFeatureFlags)
notifyFeatureFlagsCallback(onFeatureFlags, featureFlags = null, errorsLoading = true)
return
}
loadFeatureFlagsRequest(
Expand All @@ -1943,8 +1947,8 @@ public class PostHog private constructor(
}

private fun loadFeatureFlagsRequest(
internalOnFeatureFlags: PostHogOnFeatureFlags,
onFeatureFlags: PostHogOnFeatureFlags? = null,
internalOnFeatureFlags: () -> Unit,
onFeatureFlags: PostHogFeatureFlagsCallback? = null,
) {
@Suppress("UNCHECKED_CAST")
val groups = getPreferences().getValue(GROUPS) as? Map<String, String>
Expand All @@ -1959,7 +1963,7 @@ public class PostHog private constructor(
if (distinctId.isBlank()) {
config?.logger?.log("Feature flags not loaded, distinctId is invalid: $distinctId")
// Still invoke the callback so awaiting callers aren't left hanging.
notifyFeatureFlagsCallback(onFeatureFlags)
notifyFeatureFlagsCallback(onFeatureFlags, remoteConfig?.getFeatureFlags(), errorsLoading = true)
return
}

Expand All @@ -1973,8 +1977,8 @@ public class PostHog private constructor(
}

private fun loadRemoteConfigRequest(
internalOnFeatureFlags: PostHogOnFeatureFlags?,
onFeatureFlags: PostHogOnFeatureFlags?,
internalOnFeatureFlags: (() -> Unit)?,
onFeatureFlags: PostHogFeatureFlagsCallback?,
) {
@Suppress("UNCHECKED_CAST")
val groups = getPreferences().getValue(GROUPS) as? Map<String, String>
Expand Down Expand Up @@ -2712,7 +2716,7 @@ public class PostHog private constructor(
)
}

public override fun reloadFeatureFlags(onFeatureFlags: PostHogOnFeatureFlags?) {
public override fun reloadFeatureFlags(onFeatureFlags: PostHogFeatureFlagsCallback?) {
shared.reloadFeatureFlags(onFeatureFlags)
}

Expand Down
5 changes: 3 additions & 2 deletions posthog/src/main/java/com/posthog/PostHogConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,11 @@ public open class PostHogConfig(
*/
public var encryption: PostHogEncryption? = null,
/**
* Hook that is called when feature flags are loaded
* Hook that is called when feature flags are loaded, or loading them failed
* It receives a [PostHogFeatureFlagsLoaded]; see [PostHogFeatureFlagsCallback] for the thread it runs on
* Defaults to no callback
*/
public var onFeatureFlags: PostHogOnFeatureFlags? = null,
public var onFeatureFlags: PostHogFeatureFlagsCallback? = null,
/**
* Enable Recording of Session Replays for Android
* Requires Record user sessions to be enabled in the PostHog Project Settings
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.posthog

/**
* Callback invoked when a feature flags load finishes, whether it succeeded or failed.
*
* It's used by `PostHogConfig.onFeatureFlags` and `reloadFeatureFlags`. It runs on a background
* thread, or right away on the calling thread when no load is attempted (for example, the SDK is
* disabled). With bootstrapped flags, `PostHogConfig.onFeatureFlags` also runs once on the thread
* calling `setup()`, before the first load finishes. Hop to the main thread before touching UI.
*
* Example:
* ```kotlin
* config.onFeatureFlags = PostHogFeatureFlagsCallback { loaded ->
* if (!loaded.errorsLoading && "new-checkout" in loaded.flags) {
* // The flag is enabled
* }
* }
* ```
*/
public fun interface PostHogFeatureFlagsCallback {
/**
* Called when feature flags are loaded, or loading them failed.
*
* @param result the enabled flags, their values, and whether loading failed
*/
public fun loaded(result: PostHogFeatureFlagsLoaded)
}
Loading
Loading