Skip to content

Commit d7d4e6a

Browse files
author
Matthew Hoare
committed
init web support
- can track event without crashing
1 parent faaa3a3 commit d7d4e6a

File tree

20 files changed

+390
-18
lines changed

20 files changed

+390
-18
lines changed

analysis_options.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
include: package:flutter_lints/flutter.yaml
2+
3+
# Additional information about this file can be found at
4+
# https://dart.dev/guides/language/analysis-options
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.mixpanel.mixpanel_flutter
2+
3+
import androidx.annotation.NonNull
4+
5+
import io.flutter.embedding.engine.plugins.FlutterPlugin
6+
import io.flutter.plugin.common.MethodCall
7+
import io.flutter.plugin.common.MethodChannel
8+
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
9+
import io.flutter.plugin.common.MethodChannel.Result
10+
11+
/** MixpanelFlutterPlugin */
12+
class MixpanelFlutterPlugin: FlutterPlugin, MethodCallHandler {
13+
/// The MethodChannel that will the communication between Flutter and native Android
14+
///
15+
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
16+
/// when the Flutter Engine is detached from the Activity
17+
private lateinit var channel : MethodChannel
18+
19+
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
20+
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "mixpanel_flutter")
21+
channel.setMethodCallHandler(this)
22+
}
23+
24+
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
25+
if (call.method == "getPlatformVersion") {
26+
result.success("Android ${android.os.Build.VERSION.RELEASE}")
27+
} else {
28+
result.notImplemented()
29+
}
30+
}
31+
32+
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
33+
channel.setMethodCallHandler(null)
34+
}
35+
}

example/analysis_options.yaml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# This file configures the analyzer, which statically analyzes Dart code to
2+
# check for errors, warnings, and lints.
3+
#
4+
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5+
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6+
# invoked from the command line by running `flutter analyze`.
7+
8+
# The following line activates a set of recommended lints for Flutter apps,
9+
# packages, and plugins designed to encourage good coding practices.
10+
include: package:flutter_lints/flutter.yaml
11+
12+
linter:
13+
# The lint rules applied to this project can be customized in the
14+
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
15+
# included above or to enable additional rules. A list of all available lints
16+
# and their documentation is published at
17+
# https://dart-lang.github.io/linter/lints/index.html.
18+
#
19+
# Instead of disabling a lint rule for the entire project in the
20+
# section below, it can also be suppressed for a single line of code
21+
# or a specific dart file by using the `// ignore: name_of_lint` and
22+
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
23+
# producing the lint.
24+
rules:
25+
# avoid_print: false # Uncomment to disable the `avoid_print` rule
26+
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27+
28+
# Additional information about this file can be found at
29+
# https://dart.dev/guides/language/analysis-options
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.mixpanel.mixpanel_flutter_example
2+
3+
import io.flutter.embedding.android.FlutterActivity
4+
5+
class MainActivity: FlutterActivity() {
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Modify this file to customize your launch splash screen -->
3+
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+
<item android:drawable="?android:colorBackground" />
5+
6+
<!-- You can insert your own image assets here -->
7+
<!-- <item>
8+
<bitmap
9+
android:gravity="center"
10+
android:src="@mipmap/launch_image" />
11+
</item> -->
12+
</layer-list>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
4+
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
5+
<!-- Show a splash screen on the activity. Automatically removed when
6+
Flutter draws its first frame -->
7+
<item name="android:windowBackground">@drawable/launch_background</item>
8+
</style>
9+
<!-- Theme applied to the Android Window as soon as the process has started.
10+
This theme determines the color of the Android Window while your
11+
Flutter UI initializes, as well as behind your Flutter UI while its
12+
running.
13+
14+
This Theme is only used starting with V2 of Flutter's Android embedding. -->
15+
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
16+
<item name="android:windowBackground">?android:colorBackground</item>
17+
</style>
18+
</resources>

example/lib/analytics.dart

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'package:mixpanel_flutter/mixpanel_flutter.dart';
22

33
class MixpanelManager {
4-
54
static Mixpanel? _instance;
65

76
static Future<Mixpanel> init() async {
@@ -11,5 +10,4 @@ class MixpanelManager {
1110
}
1211
return _instance!;
1312
}
14-
15-
}
13+
}

example/pubspec.lock

+18-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ packages:
77
name: async
88
url: "https://pub.dartlang.org"
99
source: hosted
10-
version: "2.5.0"
10+
version: "2.8.1"
1111
boolean_selector:
1212
dependency: transitive
1313
description:
@@ -28,7 +28,7 @@ packages:
2828
name: charcode
2929
url: "https://pub.dartlang.org"
3030
source: hosted
31-
version: "1.2.0"
31+
version: "1.3.1"
3232
clock:
3333
dependency: transitive
3434
description:
@@ -67,6 +67,18 @@ packages:
6767
description: flutter
6868
source: sdk
6969
version: "0.0.0"
70+
flutter_web_plugins:
71+
dependency: transitive
72+
description: flutter
73+
source: sdk
74+
version: "0.0.0"
75+
js:
76+
dependency: transitive
77+
description:
78+
name: js
79+
url: "https://pub.dartlang.org"
80+
source: hosted
81+
version: "0.6.3"
7082
matcher:
7183
dependency: transitive
7284
description:
@@ -80,14 +92,14 @@ packages:
8092
name: meta
8193
url: "https://pub.dartlang.org"
8294
source: hosted
83-
version: "1.3.0"
95+
version: "1.7.0"
8496
mixpanel_flutter:
8597
dependency: "direct main"
8698
description:
8799
path: ".."
88100
relative: true
89101
source: path
90-
version: "1.1.0"
102+
version: "1.3.1"
91103
path:
92104
dependency: transitive
93105
description:
@@ -106,7 +118,7 @@ packages:
106118
name: source_span
107119
url: "https://pub.dartlang.org"
108120
source: hosted
109-
version: "1.8.0"
121+
version: "1.8.1"
110122
stack_trace:
111123
dependency: transitive
112124
description:
@@ -141,7 +153,7 @@ packages:
141153
name: test_api
142154
url: "https://pub.dartlang.org"
143155
source: hosted
144-
version: "0.2.19"
156+
version: "0.4.2"
145157
typed_data:
146158
dependency: transitive
147159
description:

example/test/widget_test.dart

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// This is a basic Flutter widget test.
2+
//
3+
// To perform an interaction with a widget in your test, use the WidgetTester
4+
// utility that Flutter provides. For example, you can send tap and scroll
5+
// gestures. You can also use WidgetTester to find child widgets in the widget
6+
// tree, read text, and verify that the values of widget properties are correct.
7+
8+
import 'package:flutter/material.dart';
9+
import 'package:flutter_test/flutter_test.dart';
10+
11+
import 'package:mixpanel_flutter_example/main.dart';
12+
13+
void main() {
14+
testWidgets('Verify Platform version', (WidgetTester tester) async {
15+
// Build our app and trigger a frame.
16+
await tester.pumpWidget(const MyApp());
17+
18+
// Verify that platform version is retrieved.
19+
expect(
20+
find.byWidgetPredicate(
21+
(Widget widget) => widget is Text &&
22+
widget.data!.startsWith('Running on:'),
23+
),
24+
findsOneWidget,
25+
);
26+
});
27+
}

example/web/favicon.png

917 Bytes
Loading

example/web/icons/Icon-192.png

5.17 KB
Loading

example/web/icons/Icon-512.png

8.06 KB
Loading
5.46 KB
Loading
20.5 KB
Loading

example/web/index.html

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<!--
5+
If you are serving your web app in a path other than the root, change the
6+
href value below to reflect the base path you are serving from.
7+
8+
The path provided below has to start and end with a slash "/" in order for
9+
it to work correctly.
10+
11+
For more details:
12+
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
13+
14+
This is a placeholder for base href that will be replaced by the value of
15+
the `--base-href` argument provided to `flutter build`.
16+
-->
17+
<base href="$FLUTTER_BASE_HREF">
18+
19+
<meta charset="UTF-8">
20+
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
21+
<meta name="description" content="Demonstrates how to use the mixpanel_flutter plugin.">
22+
23+
<!-- iOS meta tags & icons -->
24+
<meta name="apple-mobile-web-app-capable" content="yes">
25+
<meta name="apple-mobile-web-app-status-bar-style" content="black">
26+
<meta name="apple-mobile-web-app-title" content="mixpanel_flutter_example">
27+
<link rel="apple-touch-icon" href="icons/Icon-192.png">
28+
29+
<title>mixpanel_flutter_example</title>
30+
<link rel="manifest" href="manifest.json">
31+
<script type="text/javascript">
32+
(function(f,b){if(!b.__SV){var e,g,i,h;window.mixpanel=b;b._i=[];b.init=function(e,f,c){function g(a,d){var b=d.split(".");2==b.length&&(a=a[b[0]],d=b[1]);a[d]=function(){a.push([d].concat(Array.prototype.slice.call(arguments,0)))}}var a=b;"undefined"!==typeof c?a=b[c]=[]:c="mixpanel";a.people=a.people||[];a.toString=function(a){var d="mixpanel";"mixpanel"!==c&&(d+="."+c);a||(d+=" (stub)");return d};a.people.toString=function(){return a.toString(1)+".people (stub)"};i="disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove".split(" ");
33+
for(h=0;h<i.length;h++)g(a,i[h]);var j="set set_once union unset remove delete".split(" ");a.get_group=function(){function b(c){d[c]=function(){call2_args=arguments;call2=[c].concat(Array.prototype.slice.call(call2_args,0));a.push([e,call2])}}for(var d={},e=["get_group"].concat(Array.prototype.slice.call(arguments,0)),c=0;c<j.length;c++)b(j[c]);return d};b._i.push([e,f,c])};b.__SV=1.2;e=f.createElement("script");e.type="text/javascript";e.async=!0;e.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?
34+
MIXPANEL_CUSTOM_LIB_URL:"file:"===f.location.protocol&&"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";g=f.getElementsByTagName("script")[0];g.parentNode.insertBefore(e,g)}})(document,window.mixpanel||[]);
35+
</script>
36+
</head>
37+
<body>
38+
<!-- This script installs service_worker.js to provide PWA functionality to
39+
application. For more information, see:
40+
https://developers.google.com/web/fundamentals/primers/service-workers -->
41+
<script>
42+
var serviceWorkerVersion = null;
43+
var scriptLoaded = false;
44+
function loadMainDartJs() {
45+
if (scriptLoaded) {
46+
return;
47+
}
48+
scriptLoaded = true;
49+
var scriptTag = document.createElement('script');
50+
scriptTag.src = 'main.dart.js';
51+
scriptTag.type = 'application/javascript';
52+
document.body.append(scriptTag);
53+
}
54+
55+
if ('serviceWorker' in navigator) {
56+
// Service workers are supported. Use them.
57+
window.addEventListener('load', function () {
58+
// Wait for registration to finish before dropping the <script> tag.
59+
// Otherwise, the browser will load the script multiple times,
60+
// potentially different versions.
61+
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
62+
navigator.serviceWorker.register(serviceWorkerUrl)
63+
.then((reg) => {
64+
function waitForActivation(serviceWorker) {
65+
serviceWorker.addEventListener('statechange', () => {
66+
if (serviceWorker.state == 'activated') {
67+
console.log('Installed new service worker.');
68+
loadMainDartJs();
69+
}
70+
});
71+
}
72+
if (!reg.active && (reg.installing || reg.waiting)) {
73+
// No active web worker and we have installed or are installing
74+
// one for the first time. Simply wait for it to activate.
75+
waitForActivation(reg.installing || reg.waiting);
76+
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
77+
// When the app updates the serviceWorkerVersion changes, so we
78+
// need to ask the service worker to update.
79+
console.log('New service worker available.');
80+
reg.update();
81+
waitForActivation(reg.installing);
82+
} else {
83+
// Existing service worker is still good.
84+
console.log('Loading app from service worker.');
85+
loadMainDartJs();
86+
}
87+
});
88+
89+
// If service worker doesn't succeed in a reasonable amount of time,
90+
// fallback to plaint <script> tag.
91+
setTimeout(() => {
92+
if (!scriptLoaded) {
93+
console.warn(
94+
'Failed to load app from service worker. Falling back to plain <script> tag.',
95+
);
96+
loadMainDartJs();
97+
}
98+
}, 4000);
99+
});
100+
} else {
101+
// Service workers not supported. Just drop the <script> tag.
102+
loadMainDartJs();
103+
}
104+
</script>
105+
</body>
106+
</html>

example/web/manifest.json

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "mixpanel_flutter_example",
3+
"short_name": "mixpanel_flutter_example",
4+
"start_url": ".",
5+
"display": "standalone",
6+
"background_color": "#0175C2",
7+
"theme_color": "#0175C2",
8+
"description": "Demonstrates how to use the mixpanel_flutter plugin.",
9+
"orientation": "portrait-primary",
10+
"prefer_related_applications": false,
11+
"icons": [
12+
{
13+
"src": "icons/Icon-192.png",
14+
"sizes": "192x192",
15+
"type": "image/png"
16+
},
17+
{
18+
"src": "icons/Icon-512.png",
19+
"sizes": "512x512",
20+
"type": "image/png"
21+
},
22+
{
23+
"src": "icons/Icon-maskable-192.png",
24+
"sizes": "192x192",
25+
"type": "image/png",
26+
"purpose": "maskable"
27+
},
28+
{
29+
"src": "icons/Icon-maskable-512.png",
30+
"sizes": "512x512",
31+
"type": "image/png",
32+
"purpose": "maskable"
33+
}
34+
]
35+
}

0 commit comments

Comments
 (0)