From f658397ca3e0682c7d9e399208744c7b7a193911 Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 22 May 2025 16:03:06 -0700 Subject: [PATCH 01/11] make onAttachedEngine ligtweight and lazily create MethodChannel --- .../MixpanelFlutterPlugin.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java index 9a60a91..0f0f253 100644 --- a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java +++ b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java @@ -31,6 +31,7 @@ public class MixpanelFlutterPlugin implements FlutterPlugin, MethodCallHandler { private MixpanelAPI mixpanel; private Context context; private JSONObject mixpanelProperties; + private FlutterPluginBinding flutterPluginBinding; private static final Map EMPTY_HASHMAP = new HashMap<>(); @@ -43,10 +44,9 @@ public MixpanelFlutterPlugin(Context context) { @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { - channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "mixpanel_flutter", - new StandardMethodCodec(new MixpanelMessageCodec())); - context = flutterPluginBinding.getApplicationContext(); - channel.setMethodCallHandler(this); + // Store references for lazy initialization to avoid ANR during plugin registration + this.flutterPluginBinding = flutterPluginBinding; + this.context = flutterPluginBinding.getApplicationContext(); } @Override @@ -181,6 +181,13 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { } private void handleInitialize(MethodCall call, Result result) { + // Lazy initialization of MethodChannel to avoid ANR + if (channel == null && flutterPluginBinding != null) { + channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "mixpanel_flutter", + new StandardMethodCodec(new MixpanelMessageCodec())); + channel.setMethodCallHandler(this); + } + final String token = call.argument("token"); if (token == null) { throw new RuntimeException("Your Mixpanel Token was not set"); @@ -519,6 +526,10 @@ private void handleGroupUnionProperty(MethodCall call, Result result) { @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - channel.setMethodCallHandler(null); + if (channel != null) { + channel.setMethodCallHandler(null); + channel = null; + } + flutterPluginBinding = null; } } From f7d6271c5e926befd2f57eef6b5f54df032b209a Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 22 May 2025 16:03:42 -0700 Subject: [PATCH 02/11] update gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d5e522a..56dee95 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ .pub/ .idea build/ -.cxx \ No newline at end of file +.cxx +CLAUDE.md \ No newline at end of file From a13c60f288b63da5bab7bbddd94fc89e31e3f8f7 Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 22 May 2025 16:07:49 -0700 Subject: [PATCH 03/11] update README with DeepWiki badge --- README.md | 66 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index b7b8d7d..f2f7ada 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,23 @@ - - -
Mixpanel Flutter SDK
- # Table of Contents + - [Introduction](#introduction) - [Quick Start Guide](#quick-start-guide) - - [Install Mixpanel](#1-install-mixpanel) - - [Initialize Mixpanel](#2-initialize-mixpanel) - - [Send Data](#3-send-data) - - [Check for Success](#4-check-for-success) + - [Install Mixpanel](#1-install-mixpanel) + - [Initialize Mixpanel](#2-initialize-mixpanel) + - [Send Data](#3-send-data) + - [Check for Success](#4-check-for-success) - [I want to know more!](#i-want-to-know-more) - # Introduction + Welcome to the official Mixpanel Flutter SDK. The Mixpanel Flutter SDK is an open-source project, and we'd love to see your contributions! We'd also love for you to come and work with us! Check out **[Jobs](https://mixpanel.com/jobs/#openings)** for details @@ -30,32 +27,47 @@ We'd also love for you to come and work with us! Check out **[Jobs](https://mixp Check out our **[official documentation](https://developer.mixpanel.com/docs/flutter)** for more in depth information on installing and using Mixpanel on Flutter. ## 1. Install Mixpanel + ### Prerequisites + - [Setup development environment for Flutter](https://flutter.dev/docs/get-started/install) + ### Steps -1. Depend on it \ -Add this to your package's pubspec.yaml file: + +1. Depend on it \ + Add this to your package's pubspec.yaml file: + ``` dependencies: mixpanel_flutter: ^1.x.x # set this to your desired version ``` + 2. Install it \ -You can install packages from the command line: + You can install packages from the command line: + ``` $ flutter pub get ``` + 3. Import it \ -Now in your Dart code, you can use: + Now in your Dart code, you can use: + ``` import 'package:mixpanel_flutter/mixpanel_flutter.dart'; ``` + #### Flutter Web Support -Please add the following snippet to your `web/index.html` inside `` in your Flutter project. + +Please add the following snippet to your `web/index.html` inside `` in your Flutter project. + ``` ``` + ## 2. Initialize Mixpanel + To start tracking with the SDK you must first initialize with your project token. To initialize the SDK, first add `import 'package:mixpanel_flutter/mixpanel_flutter.dart';` and call `Mixpanel.init(token, trackAutomaticEvents);` with your project token and automatic events setting as it's arguments. You can find your token in [project settings](https://mixpanel.com/settings/project). + ```dart import 'package:mixpanel_flutter/mixpanel_flutter.dart'; ... @@ -73,43 +85,49 @@ class _YourClassState extends State { } ... ``` + Once you've called this method once, you can access `mixpanel` throughout the rest of your application. ## 3. Send Data + Once you've initialized the SDK, Mixpanel will automatically collect common mobile events. You can enable/disable automatic collection through your project settings. With the `mixpanel` object created in [the last step](#2-initialize-mixpanel) a call to `track` is all you need to send additional events to Mixpanel. + ```dart // Track with event-name mixpanel.track('Sent Message'); // Track with event-name and property mixpanel.track('Plan Selected', properties: {'Plan': 'Premium'}); ``` + You're done! You've successfully integrated the Mixpanel Flutter SDK into your app. To stay up to speed on important SDK releases and updates, star or watch our repository on [Github](https://github.com/mixpanel/mixpanel-flutter). + ## 4. Check for Success -[Open up Events in Mixpanel](https://mixpanel.com/report/events) to view incoming events. + +[Open up Events in Mixpanel](https://mixpanel.com/report/events) to view incoming events. Once data hits our API, it generally takes ~60 seconds for it to be processed, stored, and queryable in your project. -👋 👋 Tell us about the Mixpanel developer experience! [https://www.mixpanel.com/devnps](https://www.mixpanel.com/devnps) 👍 👎 +👋 👋 Tell us about the Mixpanel developer experience! [https://www.mixpanel.com/devnps](https://www.mixpanel.com/devnps) 👍 👎 # FAQ **I want to stop tracking an event/event property in Mixpanel. Is that possible?** -Yes, in Lexicon, you can intercept and drop incoming events or properties. Mixpanel won’t store any new data for the event or property you select to drop. [See this article for more information](https://help.mixpanel.com/hc/en-us/articles/360001307806#dropping-events-and-properties). +Yes, in Lexicon, you can intercept and drop incoming events or properties. Mixpanel won’t store any new data for the event or property you select to drop. [See this article for more information](https://help.mixpanel.com/hc/en-us/articles/360001307806#dropping-events-and-properties). **I have a test user I would like to opt out of tracking. How do I do that?** -Mixpanel’s client-side tracking library contains the [optOutTracking()](https://mixpanel.github.io/mixpanel-flutter/mixpanel_flutter/Mixpanel/optOutTracking.html) method, which will set the user’s local opt-out state to “true” and will prevent data from being sent from a user’s device. More detailed instructions can be found in the section, [Opting users out of tracking](https://developer.mixpanel.com/docs/flutter#opting-users-out-of-tracking). +Mixpanel’s client-side tracking library contains the [optOutTracking()](https://mixpanel.github.io/mixpanel-flutter/mixpanel_flutter/Mixpanel/optOutTracking.html) method, which will set the user’s local opt-out state to “true” and will prevent data from being sent from a user’s device. More detailed instructions can be found in the section, [Opting users out of tracking](https://developer.mixpanel.com/docs/flutter#opting-users-out-of-tracking). **Why aren't my events showing up?** -First, make sure your test device has internet access. To preserve battery life and customer bandwidth, the Mixpanel library doesn't send the events you record immediately. Instead, it sends batches to the Mixpanel servers every 60 seconds while your application is running, as well as when the application transitions to the background. You can call [flush()](https://mixpanel.github.io/mixpanel-flutter/mixpanel_flutter/Mixpanel/flush.html) manually if you want to force a flush at a particular moment. +First, make sure your test device has internet access. To preserve battery life and customer bandwidth, the Mixpanel library doesn't send the events you record immediately. Instead, it sends batches to the Mixpanel servers every 60 seconds while your application is running, as well as when the application transitions to the background. You can call [flush()](https://mixpanel.github.io/mixpanel-flutter/mixpanel_flutter/Mixpanel/flush.html) manually if you want to force a flush at a particular moment. ``` mixpanel.flush(); ``` -If your events are still not showing up after 60 seconds, check if you have opted out of tracking. You can also enable Mixpanel debugging and logging, it allows you to see the debug output from the Mixpanel library. To enable it, call [setLoggingEnabled](https://mixpanel.github.io/mixpanel-flutter/mixpanel_flutter/Mixpanel/setLoggingEnabled.html) to true, then run your iOS project with Xcode or android project with Android Studio. The logs should be available in the console. +If your events are still not showing up after 60 seconds, check if you have opted out of tracking. You can also enable Mixpanel debugging and logging, it allows you to see the debug output from the Mixpanel library. To enable it, call [setLoggingEnabled](https://mixpanel.github.io/mixpanel-flutter/mixpanel_flutter/Mixpanel/setLoggingEnabled.html) to true, then run your iOS project with Xcode or android project with Android Studio. The logs should be available in the console. ``` mixpanel.setLoggingEnabled(true); @@ -121,12 +139,14 @@ No, Mixpanel does not use IDFA so it does not require user permission through th **If I use Mixpanel, how do I answer app privacy questions for the App Store?** -Please refer to our [Apple App Developer Privacy Guidance](https://mixpanel.com/legal/app-store-privacy-details/) +Please refer to our [Apple App Developer Privacy Guidance](https://mixpanel.com/legal/app-store-privacy-details/) # I want to know more! No worries, here are some links that you will find useful: -* **[Sample app](https://github.com/mixpanel/mixpanel-flutter/tree/main/example)** -* **[Full API Reference](https://developer.mixpanel.com/docs/flutter)** + +- **[Sample app](https://github.com/mixpanel/mixpanel-flutter/tree/main/example)** +- **[Full API Reference](https://developer.mixpanel.com/docs/flutter)** + [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/mixpanel/mixpanel-flutter) Have any questions? Reach out to Mixpanel [Support](https://help.mixpanel.com/hc/en-us/requests/new) to speak to someone smart, quickly. From ef62f9f5e90fabec219915727b02b43932944dba Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 22 May 2025 16:26:38 -0700 Subject: [PATCH 04/11] nullify context in onDetachedFromEngine --- .../com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java index 0f0f253..9225751 100644 --- a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java +++ b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java @@ -531,5 +531,6 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { channel = null; } flutterPluginBinding = null; + context = null; } } From 0ab2a880c3bff785ad638cb34d8a554119d99733 Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 22 May 2025 16:51:29 -0700 Subject: [PATCH 05/11] tweak README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f2f7ada..f7fc5b5 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,7 @@ No worries, here are some links that you will find useful: - **[Sample app](https://github.com/mixpanel/mixpanel-flutter/tree/main/example)** - **[Full API Reference](https://developer.mixpanel.com/docs/flutter)** - [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/mixpanel/mixpanel-flutter) + +[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/mixpanel/mixpanel-flutter) Have any questions? Reach out to Mixpanel [Support](https://help.mixpanel.com/hc/en-us/requests/new) to speak to someone smart, quickly. From e0b0409c01d48139ec4100af529d7a31b4ea370e Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 29 May 2025 16:03:31 -0700 Subject: [PATCH 06/11] use proper generic ArrayList<>() in MixpanelFlutterHelper.java --- .../com/mixpanel/mixpanel_flutter/MixpanelFlutterHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterHelper.java b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterHelper.java index 2ad628c..3a1fec2 100644 --- a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterHelper.java +++ b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterHelper.java @@ -33,7 +33,7 @@ static public Map toMap(JSONObject object) throws JSONException } static public List toList(JSONArray array) throws JSONException { - List list = new ArrayList(); + List list = new ArrayList<>(); for (int i = 0; i < array.length(); i++) { list.add(fromJson(array.get(i))); } From 6a17898b86476976b420dcd5f71d846208b460c3 Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 29 May 2025 16:17:13 -0700 Subject: [PATCH 07/11] extract methodchannel setup to helper --- .../mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java index 9225751..96079bd 100644 --- a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java +++ b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java @@ -180,13 +180,17 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { } } - private void handleInitialize(MethodCall call, Result result) { - // Lazy initialization of MethodChannel to avoid ANR + private void initializeMethodChannel() { if (channel == null && flutterPluginBinding != null) { channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "mixpanel_flutter", new StandardMethodCodec(new MixpanelMessageCodec())); channel.setMethodCallHandler(this); } + } + + private void handleInitialize(MethodCall call, Result result) { + // Lazy initialization of MethodChannel to avoid ANR + initializeMethodChannel(); final String token = call.argument("token"); if (token == null) { From b6dd2016fb19c791257a9babf4b7535402442f7e Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 29 May 2025 16:29:01 -0700 Subject: [PATCH 08/11] document and enhance safeJsify --- README.md | 2 +- lib/mixpanel_flutter_web.dart | 41 ++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f7fc5b5..1e2976b 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ mixpanel.track('Sent Message'); mixpanel.track('Plan Selected', properties: {'Plan': 'Premium'}); ``` -You're done! You've successfully integrated the Mixpanel Flutter SDK into your app. To stay up to speed on important SDK releases and updates, star or watch our repository on [Github](https://github.com/mixpanel/mixpanel-flutter). +You're done! You've successfully integrated the Mixpanel Flutter SDK into your app. To stay up to speed on important SDK releases and updates, star or watch our repository on [GitHub](https://github.com/mixpanel/mixpanel-flutter). ## 4. Check for Success diff --git a/lib/mixpanel_flutter_web.dart b/lib/mixpanel_flutter_web.dart index 73a4ddc..b22eeb7 100644 --- a/lib/mixpanel_flutter_web.dart +++ b/lib/mixpanel_flutter_web.dart @@ -5,8 +5,47 @@ import 'package:flutter/services.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:mixpanel_flutter/web/mixpanel_js_bindings.dart'; +/// Safely converts Dart values to JavaScript-compatible types for web interop. +/// +/// This function handles the conversion of various Dart types to their JavaScript +/// equivalents using the appropriate JS interop methods. +/// +/// **Accepted input types:** +/// - `JSAny` - Returned as-is to avoid double conversion +/// - `Map` - Converted using `.jsify()` to a JavaScript object +/// - `List` - Converted using `.jsify()` to a JavaScript array +/// - `DateTime` - Converted using `.jsify()` to a JavaScript Date object +/// - `bool` - Converted using `.toJS` to a JavaScript boolean +/// - `num` (int/double) - Converted using `.toJS` to a JavaScript number +/// - `String` - Converted using `.toJS` to a JavaScript string +/// - Any other type - Returned as-is without conversion +/// +/// **Return value:** +/// Returns a `JSAny?` which represents the JavaScript-compatible value. +/// The return type is nullable to handle cases where the input cannot be +/// converted or is already null. +/// +/// **Null handling:** +/// - If the input value is `null`, it is explicitly checked and returned immediately +/// - The function is null-safe and will not throw on null inputs +/// +/// **Example usage:** +/// ```dart +/// Convert a Map to JavaScript object +/// var jsObj = safeJsify({'key': 'value', 'count': 42}); +/// +/// Convert a List to JavaScript array +/// var jsArray = safeJsify([1, 2, 3, 'four']); +/// +/// Handles null gracefully +/// var jsNull = safeJsify(null); // Returns null +/// ``` JSAny? safeJsify(dynamic value) { - if (value is Map) { + if (value == null) { + return null; + } else if (value is JSAny) { + return value; + } else if (value is Map) { return value.jsify(); } else if (value is List) { return value.jsify(); From 27ec91050ce5c059ff8411d0fc9f92424db94173 Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 29 May 2025 16:35:38 -0700 Subject: [PATCH 09/11] ensure all JavaScript interop conversions go through the safeJsify function --- lib/mixpanel_flutter_web.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mixpanel_flutter_web.dart b/lib/mixpanel_flutter_web.dart index b22eeb7..373a31c 100644 --- a/lib/mixpanel_flutter_web.dart +++ b/lib/mixpanel_flutter_web.dart @@ -195,7 +195,7 @@ class MixpanelFlutterPlugin { Map args = call.arguments as Map; String token = args['token'] as String; dynamic config = args['config']; - init(token, safeJsify(config) ?? {}.jsify()); + init(token, safeJsify(config ?? {})); } void handleSetServerURL(MethodCall call) { @@ -348,7 +348,7 @@ class MixpanelFlutterPlugin { Map args = call.arguments as Map; dynamic properties = args['properties']; double amount = args['amount'] as double; - people_track_charge(amount, safeJsify(properties) ?? {}.jsify()); + people_track_charge(amount, safeJsify(properties ?? {})); } void handleClearCharge() { @@ -409,7 +409,7 @@ class MixpanelFlutterPlugin { String name = args['name'] as String; JSAny? value = safeJsify(args['value'] as dynamic); get_group(groupKey, safeJsify(groupID)) - .union(name, value is JSArray ? value : [].toJS); + .union(name, value is JSArray ? value : safeJsify([]) as JSArray); } bool handleHasOptedOutTracking() { From 052eb4c70afb014ede511b1af152f82217ccea6f Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 29 May 2025 16:46:51 -0700 Subject: [PATCH 10/11] copilot suggestions --- .../mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java | 2 ++ lib/mixpanel_flutter_web.dart | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java index 96079bd..ff214ad 100644 --- a/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java +++ b/android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterPlugin.java @@ -536,5 +536,7 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { } flutterPluginBinding = null; context = null; + mixpanel = null; + mixpanelProperties = null; } } diff --git a/lib/mixpanel_flutter_web.dart b/lib/mixpanel_flutter_web.dart index 373a31c..5d21433 100644 --- a/lib/mixpanel_flutter_web.dart +++ b/lib/mixpanel_flutter_web.dart @@ -18,7 +18,7 @@ import 'package:mixpanel_flutter/web/mixpanel_js_bindings.dart'; /// - `bool` - Converted using `.toJS` to a JavaScript boolean /// - `num` (int/double) - Converted using `.toJS` to a JavaScript number /// - `String` - Converted using `.toJS` to a JavaScript string -/// - Any other type - Returned as-is without conversion +/// - Any other type - Logs a warning and returns null to prevent JS interop issues /// /// **Return value:** /// Returns a `JSAny?` which represents the JavaScript-compatible value. @@ -58,7 +58,9 @@ JSAny? safeJsify(dynamic value) { } else if (value is String) { return value.toJS; } else { - return value; + print('[Mixpanel] Warning: Unsupported type for JS conversion: ${value.runtimeType}. ' + 'Value will be ignored. Supported types are: Map, List, DateTime, bool, num, String, JSAny, and null.'); + return null; } } @@ -409,7 +411,7 @@ class MixpanelFlutterPlugin { String name = args['name'] as String; JSAny? value = safeJsify(args['value'] as dynamic); get_group(groupKey, safeJsify(groupID)) - .union(name, value is JSArray ? value : safeJsify([]) as JSArray); + .union(name, value is JSArray ? value : [].toJS); } bool handleHasOptedOutTracking() { From 4d1fdcd40800c81eb2eaf563f9c0ea2cfd09336a Mon Sep 17 00:00:00 2001 From: Jared McFarland Date: Thu, 29 May 2025 16:50:01 -0700 Subject: [PATCH 11/11] use debugPrint instead of print --- lib/mixpanel_flutter_web.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/mixpanel_flutter_web.dart b/lib/mixpanel_flutter_web.dart index 5d21433..6fbace4 100644 --- a/lib/mixpanel_flutter_web.dart +++ b/lib/mixpanel_flutter_web.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:js_interop'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:mixpanel_flutter/web/mixpanel_js_bindings.dart'; @@ -58,8 +59,8 @@ JSAny? safeJsify(dynamic value) { } else if (value is String) { return value.toJS; } else { - print('[Mixpanel] Warning: Unsupported type for JS conversion: ${value.runtimeType}. ' - 'Value will be ignored. Supported types are: Map, List, DateTime, bool, num, String, JSAny, and null.'); + debugPrint('[Mixpanel] Warning: Unsupported type for JS conversion: ${value.runtimeType}. ' + 'Value will be ignored. Supported types are: Map, List, DateTime, bool, num, String, JSAny, and null.'); return null; } }