diff --git a/CHANGELOG.md b/CHANGELOG.md index 340edf6..c12edbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## Next +## 4.8.0 + +- chore: change screenshots debouncing approach to throttling ([#131](https://github.com/PostHog/posthog-flutter/pull/131)) + - Added `throttleDelay` config and deprecated `debouncerDelay` config. + ## 4.7.1 - chore: do not send repeated snapshots ([#126](https://github.com/PostHog/posthog-flutter/pull/126)) diff --git a/example/.gitignore b/example/.gitignore index 01236d0..d954fb9 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 205daa9..a346b11 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -24,7 +24,8 @@ if (flutterVersionName == null) { android { namespace "com.example.flutter" - compileSdkVersion flutter.compileSdkVersion + // use flutter.compileSdkVersion once https://github.com/flutter/flutter/issues/153893 is fixed + compileSdkVersion 34 ndkVersion flutter.ndkVersion compileOptions { diff --git a/example/lib/main.dart b/example/lib/main.dart index bbfbfd4..c96f7c0 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -14,8 +14,7 @@ Future main() async { config.sessionReplay = true; config.sessionReplayConfig.maskAllTexts = false; config.sessionReplayConfig.maskAllImages = false; - config.sessionReplayConfig.debouncerDelay = - const Duration(milliseconds: 1000); + config.sessionReplayConfig.throttleDelay = const Duration(milliseconds: 1000); config.flushAt = 1; await Posthog().setup(config); diff --git a/lib/src/posthog.dart b/lib/src/posthog.dart index 44f56b6..8829fec 100644 --- a/lib/src/posthog.dart +++ b/lib/src/posthog.dart @@ -1,3 +1,5 @@ +import 'package:meta/meta.dart'; + import 'posthog_config.dart'; import 'posthog_flutter_platform_interface.dart'; import 'posthog_observer.dart'; @@ -25,10 +27,12 @@ class Posthog { return _posthog.setup(config); } + @internal PostHogConfig? get config => _config; /// Returns the current screen name (or route name) /// Only returns a value if [PosthogObserver] is used + @internal String? get currentScreen => _currentScreen; Future identify({ diff --git a/lib/src/posthog_config.dart b/lib/src/posthog_config.dart index 4b6e88b..7f3a875 100644 --- a/lib/src/posthog_config.dart +++ b/lib/src/posthog_config.dart @@ -1,3 +1,5 @@ +import 'package:meta/meta.dart'; + enum PostHogPersonProfiles { never, always, identifiedOnly } enum PostHogDataMode { wifi, cellular, any } @@ -20,11 +22,13 @@ class PostHogConfig { /// Requires Record user sessions to be enabled in the PostHog Project Settings. /// Experimental support. /// Defaults to false. + @experimental var sessionReplay = false; /// Configurations for Session replay. /// [sessionReplay] has to be enabled for this to take effect. /// Experimental support + @experimental var sessionReplayConfig = PostHogSessionReplayConfig(); /// iOS only @@ -60,24 +64,39 @@ class PostHogSessionReplayConfig { /// Enable masking of all text and text input fields. /// Experimental support. /// Default: true. + @experimental var maskAllTexts = true; /// Enable masking of all images. /// Experimental support. /// Default: true. + @experimental var maskAllImages = true; + /// The value assigned to this var will be forwarded to [throttleDelay] + /// + /// Debouncer delay used to reduce the number of snapshots captured and reduce performance impact. + /// This is used for capturing the view as a screenshot. + /// The lower the number, the more snapshots will be captured but higher the performance impact. + /// Defaults to 1s. + @Deprecated('Deprecated in favor of [throttleDelay] from v4.8.0.') + set debouncerDelay(Duration debouncerDelay) { + throttleDelay = debouncerDelay; + } + /// Debouncer delay used to reduce the number of snapshots captured and reduce performance impact. /// This is used for capturing the view as a screenshot. /// The lower the number, the more snapshots will be captured but higher the performance impact. + /// Experimental support. /// Defaults to 1s. - var debouncerDelay = const Duration(seconds: 1); + @experimental + var throttleDelay = const Duration(seconds: 1); Map toMap() { return { 'maskAllImages': maskAllImages, 'maskAllTexts': maskAllTexts, - 'debouncerDelayMs': debouncerDelay.inMilliseconds, + 'throttleDelayMs': throttleDelay.inMilliseconds, }; } } diff --git a/lib/src/posthog_widget_widget.dart b/lib/src/posthog_widget_widget.dart index 68c5feb..8fc1a1a 100644 --- a/lib/src/posthog_widget_widget.dart +++ b/lib/src/posthog_widget_widget.dart @@ -23,8 +23,9 @@ class PostHogWidgetState extends State { ScreenshotCapturer? _screenshotCapturer; NativeCommunicator? _nativeCommunicator; - Timer? _debounceTimer; - Duration _debounceDuration = const Duration(milliseconds: 1000); + Timer? _throttleTimer; + bool _isThrottling = false; + Duration _throttleDuration = const Duration(milliseconds: 1000); @override void initState() { @@ -35,7 +36,7 @@ class PostHogWidgetState extends State { return; } - _debounceDuration = config.sessionReplayConfig.debouncerDelay; + _throttleDuration = config.sessionReplayConfig.throttleDelay; _screenshotCapturer = ScreenshotCapturer(config); _nativeCommunicator = NativeCommunicator(); @@ -46,10 +47,21 @@ class PostHogWidgetState extends State { // This works as onRootViewsChangedListeners void _onChangeDetected() { - _debounceTimer?.cancel(); + if (_isThrottling) { + // If throttling is active, ignore this call + return; + } + + // Start throttling + _isThrottling = true; + + // Execute the snapshot generation + _generateSnapshot(); - _debounceTimer = Timer(_debounceDuration, () { - _generateSnapshot(); + _throttleTimer?.cancel(); + // Reset throttling after the duration + _throttleTimer = Timer(_throttleDuration, () { + _isThrottling = false; }); } @@ -91,8 +103,8 @@ class PostHogWidgetState extends State { @override void dispose() { - _debounceTimer?.cancel(); - _debounceTimer = null; + _throttleTimer?.cancel(); + _throttleTimer = null; _changeDetector?.stop(); _changeDetector = null; _screenshotCapturer = null; diff --git a/pubspec.yaml b/pubspec.yaml index 94ae8f0..35be734 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,9 +16,11 @@ dependencies: flutter_web_plugins: sdk: flutter plugin_platform_interface: ^2.0.2 + # plugin_platform_interface depends on meta anyway + meta: ^1.3.0 dev_dependencies: - flutter_lints: ^3.0.0 + flutter_lints: ^5.0.0 flutter_test: sdk: flutter