Skip to content

Conversation

laf-rge
Copy link

@laf-rge laf-rge commented Jun 5, 2025

💡 Motivation and Context

This change introduces an onFeatureFlags callback to the Posthog Flutter SDK. The primary motivation is to provide a reliable way for developers to know when feature flags have been loaded from the PostHog server, especially on the first application launch where flags might not be immediately available. This helps prevent race conditions and ensures that feature flag checks are made against up-to-date data.

This change addresses and closes issue #81.

The callback behaves as follows:

  • Web: Provides a list of active flag keys and a map of flag keys to their variant values.
  • Mobile (Android/iOS): Serves as a signal that the native PostHog SDK has finished loading feature flags. The flags and flagVariants parameters in the callback will be empty. Developers should use Posthog().getFeatureFlag('key') or Posthog().isFeatureEnabled('key') to retrieve specific flag values after this callback is invoked. This is because the native libraries do not have public methods for retrieving all features.

💚 How did you test it?

The changes were tested through several methods:

  • Unit Tests: Added new unit tests for the Dart PosthogFlutterIO implementation to cover callback registration, successful event handling (with and without data), error handling, and malformed data scenarios.
  • Example App: Ensured the example application in the repository compiles and builds successfully for both Android and iOS platforms after incorporating the native changes.
  • Real-world Project Integration: I tested this branch in a personal project that uses posthog-flutter. The dependency in pubspec.yaml was pointed to this forked version, and I confirmed that the onFeatureFlags callback fires correctly once the feature flags are available from the native SDKs.
  • Native Code Verification:
    • For Android, verified that channel.invokeMethod is called on the main UI thread and that it signals readiness without attempting to send all flag data (as the native Android SDK's callback doesn't provide it directly).
    • For iOS, confirmed that the plugin observes PostHogSDK.didReceiveFeatureFlags and, similar to Android, signals readiness without sending all flag data due to the absence of a public API in the native iOS SDK to fetch all flags and variants at once.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed. (Updated Dartdoc for onFeatureFlags and added an entry to CHANGELOG.md)
  • No breaking change or entry added to the changelog. (New non-breaking feature; changelog entry added under "Next")

@laf-rge laf-rge marked this pull request as ready for review June 5, 2025 17:28
@laf-rge laf-rge requested a review from marandaneto as a code owner June 5, 2025 17:28
@marandaneto marandaneto requested a review from ioannisj June 6, 2025 07:11
@marandaneto
Copy link
Member

@ioannisj would you like to review and test this one as part of owning a bit more of this SDK? happy to do a final review as well

Copy link
Contributor

@ioannisj ioannisj left a comment

Choose a reason for hiding this comment

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

Left a few comments — overall this looks good! My main concern is around using a shared callback across platforms, where some parameters are intentionally passed empty on mobile. Not ideal in terms from a dx perspective, but can't think of another alternative either

@marandaneto leaving the final review to you

@marandaneto
Copy link
Member

Oh I see this is similar to the Web implementation https://posthog.com/docs/libraries/js/features#ensuring-flags-are-loaded-before-usage hence the featureFlags, flagVariants and errorsLoading always empty.
Since the Mobile SDKs dont support this yet, I recommend removing them

@marandaneto
Copy link
Member

can we do this for the Web implementation as well?
https://github.com/PostHog/posthog-flutter/blob/main/lib/src/posthog_flutter_web_handler.dart

laf-rge and others added 6 commits June 6, 2025 07:53
Co-authored-by: Ioannis J <yiannis@posthog.com>
Android try-catch and arguments (Comments 1 & 5):
The Android native code in PosthogFlutterPlugin.kt now sends an empty map for the onFeatureFlagsCallback. The try-catch block remains to handle potential errors during the invokeMethod call itself but no longer sends different argument structures.
Callback signature/location and parameter handling (Comments 2, 7, 8):
The OnFeatureFlagsCallback is now defined in PostHogConfig and passed during Posthog().setup().
The Dart callback signature void Function(List<String> flags, Map<String, dynamic> flagVariants, {bool? errorsLoading}) is maintained.
For mobile (Android/iOS), this callback will be invoked with an empty list for flags, an empty map for flagVariants, and errorsLoading will be null (if the native call is successful) or true (if a Dart-side processing error occurs in _handleMethodCall). This aligns with the native SDKs not providing these details directly in their "flags loaded" callbacks.
For web, the callback will receive the actual flags, flagVariants from posthog-js, and errorsLoading will be false (as the JS callback firing implies success).
Dart redundant null check (Comment 3):
The redundant null check in lib/src/posthog_flutter_io.dart's _handleMethodCall has been removed.
Android dataMode (Comment 4):
The unused dataMode configuration has been removed from the Android setupPostHog method in PosthogFlutterPlugin.kt.
Android main thread invocation (Comment 6):
The mainHandler.post for channel.invokeMethod in Android is kept, as it's good practice for Flutter platform channel calls.
All relevant Dart files, the Android Kotlin plugin file, and their corresponding test files have been updated to reflect these changes.
@ioannisj
Copy link
Contributor

@laf-rge Apologies for the delay here! Still willing to work on this? If so, you can merge main for a final review?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants