From 9d2f34a3e47e843b9cfebf7b116f709145c0afa2 Mon Sep 17 00:00:00 2001 From: Debkanchan Samadder Date: Fri, 7 Jul 2023 19:33:41 +0530 Subject: [PATCH 1/6] feat: Add singleton instance support --- packages/core/lib/analytics.dart | 30 +++++- packages/core/lib/analytics_web.dart | 2 +- packages/core/lib/client.dart | 95 ------------------- packages/core/lib/client_methods.dart | 11 +++ .../flush_policies/default_flush_policy.dart | 10 ++ packages/core/lib/screen_observer.dart | 48 ++++++++++ packages/core/test/analytics_test.dart | 4 +- .../core/test/utils/http_client_test.dart | 7 +- 8 files changed, 105 insertions(+), 102 deletions(-) delete mode 100644 packages/core/lib/client.dart create mode 100644 packages/core/lib/client_methods.dart create mode 100644 packages/core/lib/flush_policies/default_flush_policy.dart create mode 100644 packages/core/lib/screen_observer.dart diff --git a/packages/core/lib/analytics.dart b/packages/core/lib/analytics.dart index 98870b2..0e51700 100644 --- a/packages/core/lib/analytics.dart +++ b/packages/core/lib/analytics.dart @@ -2,15 +2,18 @@ library analytics; import 'dart:async'; -import 'package:analytics/client.dart'; +import 'package:analytics/client_methods.dart'; import 'package:analytics/errors.dart'; import 'package:analytics/event.dart'; +import 'package:analytics/flush_policies/default_flush_policy.dart'; import 'package:analytics/flush_policies/flush_policy.dart'; import 'package:analytics/flush_policies/flush_policy_executor.dart'; import 'package:analytics/logger.dart'; import 'package:analytics/native_context.dart'; import 'package:analytics/plugin.dart'; +import 'package:analytics/plugins/event_logger.dart'; import 'package:analytics/plugins/segment_destination.dart'; +import 'package:analytics/screen_observer.dart'; import 'package:analytics/state.dart'; import 'package:analytics/timeline.dart'; import 'package:analytics/utils/lifecycle/lifecycle.dart'; @@ -24,6 +27,8 @@ import 'package:analytics/plugins/inject_user_info.dart'; import 'package:analytics/plugins/inject_context.dart'; class Analytics with ClientMethods { + static late final Analytics instance; + static String version() => segmentVersion; static bool debug = false; @@ -53,7 +58,28 @@ class Analytics with ClientMethods { reportInternalError(exception, analytics: this); } - Analytics(Configuration config, this._store, + factory Analytics.init(Configuration configuration) { + debug = configuration.debug; + + if (configuration.flushPolicies == null) { + configuration = setFlushPolicies(configuration, defaultFlushPolicies); + } + + instance = Analytics.internal(configuration, storeFactory()); + + if (debug) { + instance.addPlugin(EventLogger()); + } + + instance.init(); + ScreenObserver().screenStream.listen((name) { + instance.screen(name); + }); + + return instance; + } + + Analytics.internal(Configuration config, this._store, {HTTPClient Function(Analytics)? httpClient}) : _state = StateManager(_store, System(true, false), config), _timeline = Timeline() { diff --git a/packages/core/lib/analytics_web.dart b/packages/core/lib/analytics_web.dart index 1bead17..2beb3a3 100644 --- a/packages/core/lib/analytics_web.dart +++ b/packages/core/lib/analytics_web.dart @@ -6,7 +6,7 @@ import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:analytics/analytics_platform_interface.dart'; -export 'package:analytics/client.dart'; +export 'package:analytics/client_methods.dart'; /// A web implementation of the AnalyticsPlatform of the Analytics plugin. class AnalyticsPlatformImpl extends AnalyticsPlatform { diff --git a/packages/core/lib/client.dart b/packages/core/lib/client.dart deleted file mode 100644 index ed2c333..0000000 --- a/packages/core/lib/client.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'dart:async'; - -import 'package:analytics/analytics.dart'; -import 'package:analytics/event.dart'; -import 'package:analytics/flush_policies/count_flush_policy.dart'; -import 'package:analytics/flush_policies/flush_policy.dart'; -import 'package:analytics/flush_policies/startup_flush_policy.dart'; -import 'package:analytics/flush_policies/timer_flush_policy.dart'; -import 'package:analytics/plugins/event_logger.dart'; -import 'package:analytics/state.dart'; -import 'package:analytics/utils/store/store.dart'; -import 'package:flutter/widgets.dart'; - -Analytics createClient(Configuration configuration) { - if (configuration.debug) { - Analytics.debug = true; - } - if (configuration.flushPolicies == null) { - configuration = setFlushPolicies(configuration, defaultFlushPolicies); - } - - final analytics = Analytics(configuration, storeFactory()); - - if (configuration.debug) { - analytics.addPlugin(EventLogger()); - } - - analytics.init(); - ScreenObserver().screenStream.listen((name) { - analytics.screen(name); - }); - - return analytics; -} - -mixin ClientMethods { - Future track(String event, {Map? properties}); - Future screen(String name, {Map? properties}); - Future identify({String? userId, UserTraits? userTraits}); - Future group(String groupId, {GroupTraits? groupTraits}); - Future alias(String newUserId); - Future flush(); - Future reset({bool? resetAnonymousId}); -} - -List defaultFlushPolicies = [ - StartupFlushPolicy(), - TimerFlushPolicy(20000), - CountFlushPolicy(30), -]; - -class ScreenObserver extends NavigatorObserver { - final StreamController screenStreamController = - StreamController.broadcast(); - - Stream get screenStream => screenStreamController.stream; - - static final ScreenObserver _singleton = ScreenObserver._internal(); - ScreenObserver._internal(); - factory ScreenObserver() { - return _singleton; - } - - @override - void didPop(Route route, Route? previousRoute) { - final name = route.settings.name; - if (name != null) { - screenStreamController.add(name); - } - } - - @override - void didPush(Route route, Route? previousRoute) { - final name = route.settings.name; - if (name != null) { - screenStreamController.add(name); - } - } - - @override - void didRemove(Route route, Route? previousRoute) { - final name = route.settings.name; - if (name != null) { - screenStreamController.add(name); - } - } - - @override - void didReplace({Route? newRoute, Route? oldRoute}) { - final name = newRoute?.settings.name; - if (name != null) { - screenStreamController.add(name); - } - } -} diff --git a/packages/core/lib/client_methods.dart b/packages/core/lib/client_methods.dart new file mode 100644 index 0000000..ff75d90 --- /dev/null +++ b/packages/core/lib/client_methods.dart @@ -0,0 +1,11 @@ +import 'package:analytics/event.dart'; + +mixin ClientMethods { + Future track(String event, {Map? properties}); + Future screen(String name, {Map? properties}); + Future identify({String? userId, UserTraits? userTraits}); + Future group(String groupId, {GroupTraits? groupTraits}); + Future alias(String newUserId); + Future flush(); + Future reset({bool? resetAnonymousId}); +} diff --git a/packages/core/lib/flush_policies/default_flush_policy.dart b/packages/core/lib/flush_policies/default_flush_policy.dart new file mode 100644 index 0000000..25a59eb --- /dev/null +++ b/packages/core/lib/flush_policies/default_flush_policy.dart @@ -0,0 +1,10 @@ +import 'package:analytics/flush_policies/count_flush_policy.dart'; +import 'package:analytics/flush_policies/flush_policy.dart'; +import 'package:analytics/flush_policies/startup_flush_policy.dart'; +import 'package:analytics/flush_policies/timer_flush_policy.dart'; + +List defaultFlushPolicies = [ + StartupFlushPolicy(), + TimerFlushPolicy(20000), + CountFlushPolicy(30), +]; diff --git a/packages/core/lib/screen_observer.dart b/packages/core/lib/screen_observer.dart new file mode 100644 index 0000000..44d7a12 --- /dev/null +++ b/packages/core/lib/screen_observer.dart @@ -0,0 +1,48 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; + +class ScreenObserver extends NavigatorObserver { + final StreamController screenStreamController = + StreamController.broadcast(); + + Stream get screenStream => screenStreamController.stream; + + static final ScreenObserver _singleton = ScreenObserver._internal(); + ScreenObserver._internal(); + factory ScreenObserver() { + return _singleton; + } + + @override + void didPop(Route route, Route? previousRoute) { + final name = route.settings.name; + if (name != null) { + screenStreamController.add(name); + } + } + + @override + void didPush(Route route, Route? previousRoute) { + final name = route.settings.name; + if (name != null) { + screenStreamController.add(name); + } + } + + @override + void didRemove(Route route, Route? previousRoute) { + final name = route.settings.name; + if (name != null) { + screenStreamController.add(name); + } + } + + @override + void didReplace({Route? newRoute, Route? oldRoute}) { + final name = newRoute?.settings.name; + if (name != null) { + screenStreamController.add(name); + } + } +} diff --git a/packages/core/test/analytics_test.dart b/packages/core/test/analytics_test.dart index d6db811..03d8949 100644 --- a/packages/core/test/analytics_test.dart +++ b/packages/core/test/analytics_test.dart @@ -25,7 +25,7 @@ void main() { when(httpClient.startBatchUpload(any, any)) .thenAnswer((_) => Future.value(true)); - Analytics analytics = Analytics( + Analytics analytics = Analytics.internal( Configuration("123", trackApplicationLifecycleEvents: false, appStateStream: () => Mocks.streamSubscription()), @@ -45,7 +45,7 @@ void main() { when(httpClient.startBatchUpload(any, any)) .thenAnswer((_) => Future.value(true)); - Analytics analytics = Analytics( + Analytics analytics = Analytics.internal( Configuration("123", trackApplicationLifecycleEvents: true, appStateStream: () => Mocks.streamSubscription()), diff --git a/packages/core/test/utils/http_client_test.dart b/packages/core/test/utils/http_client_test.dart index 3020289..fac1c8f 100644 --- a/packages/core/test/utils/http_client_test.dart +++ b/packages/core/test/utils/http_client_test.dart @@ -2,6 +2,7 @@ import 'package:analytics/analytics.dart'; import 'package:analytics/logger.dart'; import 'package:analytics/state.dart'; import 'package:analytics/utils/http_client.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart'; import 'package:mockito/mockito.dart'; @@ -12,6 +13,7 @@ import '../mocks/mocks.mocks.dart'; void main() { group("HTTP Client", () { setUp(() { + TestWidgetsFlutterBinding.ensureInitialized(); LogFactory.logger = Mocks.logTarget(); }); test("It logs on bad response for get Settings", () async { @@ -19,7 +21,8 @@ void main() { when(mockRequest.send()).thenAnswer( (_) => Future.value(StreamedResponse(const Stream.empty(), 300))); when(mockRequest.url).thenAnswer((_) => Uri.parse("http://segment.io")); - HTTPClient client = HTTPClient(Analytics( + HTTPClient client = HTTPClient( + Analytics.internal( Configuration("123", requestFactory: (_) => mockRequest), Mocks.store())); @@ -33,7 +36,7 @@ void main() { when(mockRequest.send()).thenAnswer( (_) => Future.value(StreamedResponse(const Stream.empty(), 300))); when(mockRequest.url).thenAnswer((_) => Uri.parse("http://segment.io")); - HTTPClient client = HTTPClient(Analytics( + HTTPClient client = HTTPClient(Analytics.internal( Configuration("123", requestFactory: (_) => mockRequest), Mocks.store())); From 6d439930e24720ccbb21ced8f6c54e1d8ecec3ed Mon Sep 17 00:00:00 2001 From: Debkanchan Samadder Date: Fri, 7 Jul 2023 19:34:11 +0530 Subject: [PATCH 2/6] fix: fix broken mocks --- packages/core/test/mocks/mocks.mocks.dart | 181 ++++++++++++---------- 1 file changed, 96 insertions(+), 85 deletions(-) diff --git a/packages/core/test/mocks/mocks.mocks.dart b/packages/core/test/mocks/mocks.mocks.dart index 175a9ef..d6a87bf 100644 --- a/packages/core/test/mocks/mocks.mocks.dart +++ b/packages/core/test/mocks/mocks.mocks.dart @@ -1,20 +1,21 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.2 from annotations // in analytics/test/mocks/mocks.dart. // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; +import 'dart:async' as _i4; import 'dart:convert' as _i2; -import 'dart:typed_data' as _i7; +import 'dart:typed_data' as _i6; -import 'package:analytics/event.dart' as _i9; -import 'package:analytics/logger.dart' as _i6; -import 'package:analytics/state.dart' as _i10; -import 'package:analytics/utils/http_client.dart' as _i8; -import 'package:analytics/utils/store/store.dart' as _i11; -import 'package:http/http.dart' as _i4; -import 'package:http/src/byte_stream.dart' as _i3; +import 'package:analytics/event.dart' as _i10; +import 'package:analytics/logger.dart' as _i5; +import 'package:analytics/state.dart' as _i11; +import 'package:analytics/utils/http_client.dart' as _i9; +import 'package:analytics/utils/store/store.dart' as _i12; +import 'package:http/http.dart' as _i3; +import 'package:http/src/byte_stream.dart' as _i7; import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i8; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -47,8 +48,9 @@ class _FakeUri_1 extends _i1.SmartFake implements Uri { ); } -class _FakeByteStream_2 extends _i1.SmartFake implements _i3.ByteStream { - _FakeByteStream_2( +class _FakeStreamedResponse_2 extends _i1.SmartFake + implements _i3.StreamedResponse { + _FakeStreamedResponse_2( Object parent, Invocation parentInvocation, ) : super( @@ -57,19 +59,8 @@ class _FakeByteStream_2 extends _i1.SmartFake implements _i3.ByteStream { ); } -class _FakeStreamedResponse_3 extends _i1.SmartFake - implements _i4.StreamedResponse { - _FakeStreamedResponse_3( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeFuture_4 extends _i1.SmartFake implements _i5.Future { - _FakeFuture_4( +class _FakeFuture_3 extends _i1.SmartFake implements _i4.Future { + _FakeFuture_3( Object parent, Invocation parentInvocation, ) : super( @@ -81,9 +72,9 @@ class _FakeFuture_4 extends _i1.SmartFake implements _i5.Future { /// A class which mocks [LogTarget]. /// /// See the documentation for Mockito's code generation for more information. -class MockLogTarget extends _i1.Mock implements _i6.LogTarget { +class MockLogTarget extends _i1.Mock implements _i5.LogTarget { @override - void parseLog(_i6.LogMessage? log) => super.noSuchMethod( + void parseLog(_i5.LogMessage? log) => super.noSuchMethod( Invocation.method( #parseLog, [log], @@ -95,7 +86,7 @@ class MockLogTarget extends _i1.Mock implements _i6.LogTarget { /// A class which mocks [Request]. /// /// See the documentation for Mockito's code generation for more information. -class MockRequest extends _i1.Mock implements _i4.Request { +class MockRequest extends _i1.Mock implements _i3.Request { @override int get contentLength => (super.noSuchMethod( Invocation.getter(#contentLength), @@ -131,11 +122,11 @@ class MockRequest extends _i1.Mock implements _i4.Request { returnValueForMissingStub: null, ); @override - _i7.Uint8List get bodyBytes => (super.noSuchMethod( + _i6.Uint8List get bodyBytes => (super.noSuchMethod( Invocation.getter(#bodyBytes), - returnValue: _i7.Uint8List(0), - returnValueForMissingStub: _i7.Uint8List(0), - ) as _i7.Uint8List); + returnValue: _i6.Uint8List(0), + returnValueForMissingStub: _i6.Uint8List(0), + ) as _i6.Uint8List); @override set bodyBytes(List? value) => super.noSuchMethod( Invocation.setter( @@ -245,34 +236,34 @@ class MockRequest extends _i1.Mock implements _i4.Request { returnValueForMissingStub: false, ) as bool); @override - _i3.ByteStream finalize() => (super.noSuchMethod( + _i7.ByteStream finalize() => (super.noSuchMethod( Invocation.method( #finalize, [], ), - returnValue: _FakeByteStream_2( + returnValue: _i8.dummyValue<_i7.ByteStream>( this, Invocation.method( #finalize, [], ), ), - returnValueForMissingStub: _FakeByteStream_2( + returnValueForMissingStub: _i8.dummyValue<_i7.ByteStream>( this, Invocation.method( #finalize, [], ), ), - ) as _i3.ByteStream); + ) as _i7.ByteStream); @override - _i5.Future<_i4.StreamedResponse> send() => (super.noSuchMethod( + _i4.Future<_i3.StreamedResponse> send() => (super.noSuchMethod( Invocation.method( #send, [], ), returnValue: - _i5.Future<_i4.StreamedResponse>.value(_FakeStreamedResponse_3( + _i4.Future<_i3.StreamedResponse>.value(_FakeStreamedResponse_2( this, Invocation.method( #send, @@ -280,21 +271,21 @@ class MockRequest extends _i1.Mock implements _i4.Request { ), )), returnValueForMissingStub: - _i5.Future<_i4.StreamedResponse>.value(_FakeStreamedResponse_3( + _i4.Future<_i3.StreamedResponse>.value(_FakeStreamedResponse_2( this, Invocation.method( #send, [], ), )), - ) as _i5.Future<_i4.StreamedResponse>); + ) as _i4.Future<_i3.StreamedResponse>); } /// A class which mocks [StreamSubscription]. /// /// See the documentation for Mockito's code generation for more information. class MockStreamSubscription extends _i1.Mock - implements _i5.StreamSubscription { + implements _i4.StreamSubscription { @override bool get isPaused => (super.noSuchMethod( Invocation.getter(#isPaused), @@ -302,14 +293,14 @@ class MockStreamSubscription extends _i1.Mock returnValueForMissingStub: false, ) as bool); @override - _i5.Future cancel() => (super.noSuchMethod( + _i4.Future cancel() => (super.noSuchMethod( Invocation.method( #cancel, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override void onData(void Function(T)? handleData) => super.noSuchMethod( Invocation.method( @@ -335,7 +326,7 @@ class MockStreamSubscription extends _i1.Mock returnValueForMissingStub: null, ); @override - void pause([_i5.Future? resumeSignal]) => super.noSuchMethod( + void pause([_i4.Future? resumeSignal]) => super.noSuchMethod( Invocation.method( #pause, [resumeSignal], @@ -351,36 +342,56 @@ class MockStreamSubscription extends _i1.Mock returnValueForMissingStub: null, ); @override - _i5.Future asFuture([E? futureValue]) => (super.noSuchMethod( + _i4.Future asFuture([E? futureValue]) => (super.noSuchMethod( Invocation.method( #asFuture, [futureValue], ), - returnValue: _FakeFuture_4( - this, - Invocation.method( - #asFuture, - [futureValue], - ), - ), - returnValueForMissingStub: _FakeFuture_4( - this, - Invocation.method( - #asFuture, - [futureValue], - ), - ), - ) as _i5.Future); + returnValue: _i8.ifNotNull( + _i8.dummyValueOrNull( + this, + Invocation.method( + #asFuture, + [futureValue], + ), + ), + (E v) => _i4.Future.value(v), + ) ?? + _FakeFuture_3( + this, + Invocation.method( + #asFuture, + [futureValue], + ), + ), + returnValueForMissingStub: _i8.ifNotNull( + _i8.dummyValueOrNull( + this, + Invocation.method( + #asFuture, + [futureValue], + ), + ), + (E v) => _i4.Future.value(v), + ) ?? + _FakeFuture_3( + this, + Invocation.method( + #asFuture, + [futureValue], + ), + ), + ) as _i4.Future); } /// A class which mocks [HTTPClient]. /// /// See the documentation for Mockito's code generation for more information. -class MockHTTPClient extends _i1.Mock implements _i8.HTTPClient { +class MockHTTPClient extends _i1.Mock implements _i9.HTTPClient { @override - _i5.Future startBatchUpload( + _i4.Future startBatchUpload( String? writeKey, - List<_i9.RawEvent>? batch, + List<_i10.RawEvent>? batch, ) => (super.noSuchMethod( Invocation.method( @@ -390,43 +401,43 @@ class MockHTTPClient extends _i1.Mock implements _i8.HTTPClient { batch, ], ), - returnValue: _i5.Future.value(false), - returnValueForMissingStub: _i5.Future.value(false), - ) as _i5.Future); + returnValue: _i4.Future.value(false), + returnValueForMissingStub: _i4.Future.value(false), + ) as _i4.Future); @override - _i5.Future<_i10.SegmentAPISettings?> settingsFor(String? writeKey) => + _i4.Future<_i11.SegmentAPISettings?> settingsFor(String? writeKey) => (super.noSuchMethod( Invocation.method( #settingsFor, [writeKey], ), - returnValue: _i5.Future<_i10.SegmentAPISettings?>.value(), - returnValueForMissingStub: _i5.Future<_i10.SegmentAPISettings?>.value(), - ) as _i5.Future<_i10.SegmentAPISettings?>); + returnValue: _i4.Future<_i11.SegmentAPISettings?>.value(), + returnValueForMissingStub: _i4.Future<_i11.SegmentAPISettings?>.value(), + ) as _i4.Future<_i11.SegmentAPISettings?>); } /// A class which mocks [Store]. /// /// See the documentation for Mockito's code generation for more information. -class MockStore extends _i1.Mock implements _i11.Store { +class MockStore extends _i1.Mock implements _i12.Store { @override - _i5.Future get ready => (super.noSuchMethod( + _i4.Future get ready => (super.noSuchMethod( Invocation.getter(#ready), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override - _i5.Future?> getPersisted(String? key) => + _i4.Future?> getPersisted(String? key) => (super.noSuchMethod( Invocation.method( #getPersisted, [key], ), - returnValue: _i5.Future?>.value(), - returnValueForMissingStub: _i5.Future?>.value(), - ) as _i5.Future?>); + returnValue: _i4.Future?>.value(), + returnValueForMissingStub: _i4.Future?>.value(), + ) as _i4.Future?>); @override - _i5.Future setPersisted( + _i4.Future setPersisted( String? key, Map? value, ) => @@ -438,9 +449,9 @@ class MockStore extends _i1.Mock implements _i11.Store { value, ], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); @override void dispose() => super.noSuchMethod( Invocation.method( From 1c6098fdd148c963861f1f38b1ff2865b38ddc78 Mon Sep 17 00:00:00 2001 From: Debkanchan Samadder Date: Fri, 7 Jul 2023 19:35:15 +0530 Subject: [PATCH 3/6] fix: fix dependency cycle in example --- example/pubspec.lock | 40 ++++++++++++++++++++-------------------- example/pubspec.yaml | 4 ++++ 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index bec47dc..4e3e5c6 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -41,10 +41,10 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" boolean_selector: dependency: transitive description: @@ -57,10 +57,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" clock: dependency: transitive description: @@ -73,10 +73,10 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" crypto: dependency: transitive description: @@ -86,7 +86,7 @@ packages: source: hosted version: "3.0.2" cupertino_icons: - dependency: "direct main" + dependency: "direct overridden" description: name: cupertino_icons sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be @@ -200,10 +200,10 @@ packages: dependency: transitive description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_parser: dependency: transitive description: @@ -216,10 +216,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -248,10 +248,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -264,18 +264,18 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" path: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: transitive description: @@ -405,10 +405,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" typed_data: dependency: transitive description: @@ -450,5 +450,5 @@ packages: source: hosted version: "1.0.0" sdks: - dart: ">=2.19.3 <3.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.0.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 9df217b..67377f4 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -31,6 +31,10 @@ dependencies: analytics_plugin_idfa: path: ../packages/plugins/plugin_idfa/ +dependency_overrides: + analytics: + path: ../packages/core/ + # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 From 20fdffe79f36e71986a59bdccc36bc22f571f0bc Mon Sep 17 00:00:00 2001 From: Debkanchan Samadder Date: Fri, 7 Jul 2023 19:37:56 +0530 Subject: [PATCH 4/6] chore: update example --- example/lib/main.dart | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 18489f6..ad9047b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,4 +1,6 @@ +import 'package:analytics/analytics.dart'; import 'package:analytics/event.dart'; +import 'package:analytics/screen_observer.dart'; import 'package:analytics/state.dart'; import 'package:analytics_example/config.dart'; import 'package:analytics_plugin_advertising_id/plugin_advertising_id.dart'; @@ -6,7 +8,6 @@ import 'package:analytics_plugin_idfa/plugin_idfa.dart'; import 'package:analytics_example/firebase_options.dart'; import 'package:flutter/material.dart'; import 'dart:async'; -import 'package:analytics/client.dart'; import 'package:analytics_plugin_firebase/plugin_firebase.dart' show FirebaseDestination; @@ -22,18 +23,18 @@ class MyApp extends MaterialApp { } class _MyAppState extends State { - final analytics = createClient(Configuration(writeKey, - debug: true, trackApplicationLifecycleEvents: false)); - @override void initState() { super.initState(); initPlatformState(); - analytics + Analytics.init(Configuration(writeKey, + debug: true, trackApplicationLifecycleEvents: false)); + + Analytics.instance .addPlugin(FirebaseDestination(DefaultFirebaseOptions.currentPlatform)); - analytics.addPlugin(PluginAdvertisingId()); - analytics.addPlugin(PluginIdfa()); + Analytics.instance.addPlugin(PluginAdvertisingId()); + Analytics.instance.addPlugin(PluginIdfa()); } // Platform messages are asynchronous, so we initialize in an async method. @@ -64,16 +65,16 @@ class _MyAppState extends State { ), TextButton( onPressed: () { - analytics + Analytics.instance .track("Test Event", properties: {"prop1": "value1"}); }, child: const Text('Track Product Viewed'), ), TextButton( onPressed: () { - analytics.track('Products Searched', + Analytics.instance.track('Products Searched', properties: {"query": 'blue roses'}); - analytics.track('Product List Viewed', properties: { + Analytics.instance.track('Product List Viewed', properties: { "list_id": 'hot_deals_1', "category": 'Deals', "products": [ @@ -97,13 +98,13 @@ class _MyAppState extends State { } ] }); - analytics.track('Promotion Viewed', properties: { + Analytics.instance.track('Promotion Viewed', properties: { "promotion_id": 'promo_1', "creative": 'top_banner_2', "name": '75% store-wide shoe sale', "position": 'home_banner_top' }); - analytics.track('Product Clicked', properties: { + Analytics.instance.track('Product Clicked', properties: { "product_id": '507f1f77bcf86cd799439011', "sku": 'G-32', "category": 'Games', @@ -117,7 +118,7 @@ class _MyAppState extends State { "url": 'https://www.example.com/product/path', "image_url": 'https://www.example.com/product/path.jpg' }); - analytics.track('Product Shared', properties: { + Analytics.instance.track('Product Shared', properties: { "share_via": 'email', "share_message": 'Hey, check out this item', "recipient": 'friend@example.com', @@ -131,7 +132,7 @@ class _MyAppState extends State { "url": 'https://www.example.com/product/path', "image_url": 'https://www.example.com/product/path.jpg' }); - analytics.track('Cart Shared', properties: { + Analytics.instance.track('Cart Shared', properties: { "share_via": 'email', "share_message": 'Hey, check out this item', "recipient": 'friend@example.com', @@ -146,13 +147,13 @@ class _MyAppState extends State { ), TextButton( onPressed: () { - analytics.reset(); + Analytics.instance.reset(); }, child: const Text('Reset'), ), TextButton( onPressed: () { - analytics.flush(); + Analytics.instance.flush(); }, child: const Text('Flush'), ), @@ -173,7 +174,7 @@ class _MyAppState extends State { ), TextButton( onPressed: () { - analytics.identify( + Analytics.instance.identify( userId: "testUserId", userTraits: UserTraits(name: "Test User")); }, From e680c4665e6d5397625e76004aac81d3f6ad3e03 Mon Sep 17 00:00:00 2001 From: Debkanchan Samadder Date: Fri, 7 Jul 2023 19:58:28 +0530 Subject: [PATCH 5/6] docs: update docs --- README.md | 52 +++++++++---------- packages/plugins/plugin_adjust/README.md | 18 +++---- .../plugins/plugin_advertising_id/README.md | 19 ++++--- packages/plugins/plugin_appsflyer/README.md | 18 +++---- packages/plugins/plugin_firebase/README.md | 20 +++---- packages/plugins/plugin_idfa/README.md | 29 ++++++----- 6 files changed, 78 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 963590a..c5bba78 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ If you need any plugins you can add them too: Now, in your Dart code, you can import the library as follows: ```dart -import 'package:analytics/client.dart'; +import 'package:analytics/analytics.dart'; ``` ### Permissions @@ -101,11 +101,11 @@ In your app's `AndroidManifest.xml` add the below line between the `` ### Setting up the client -The package exposes a method called `createClient` which we can use to create the Segment Analytics client. This central client manages all our tracking events. It is recommended you add this as a property on your main app's state class. +Call the `Analytics.init` method to create default segment client. **DO NOT** call `Analytics.internal`, it is for development purposes only. ```dart const writeKey = 'SEGMENT_API_KEY'; -final analytics = createClient(Configuration(writeKey)); +Analytics.init(Configuration(writeKey)); ``` You must pass at least the `writeKey`. Additional configuration options are listed below: @@ -145,7 +145,7 @@ Future track(String event: string, {Map? properties}); Example usage: ```dart -analytics.track("View Product", properties: { +Analytics.instance.track("View Product", properties: { "productId": 123, "productName": "Striped trousers" }); @@ -164,7 +164,7 @@ Future screen(String name: string, {Map? properties}); Example usage: ```dart -analytics.screen("ScreenName", properties: { +Analytics.instance.screen("ScreenName", properties: { "productSlug": "example-product-123", }); ``` @@ -184,7 +184,7 @@ Future identify({String? userId, UserTraits? userTraits}); Example usage: ```dart -analytics.identify(userId: "testUserId", userTraits: UserTraits( +Analytics.instance.identify(userId: "testUserId", userTraits: UserTraits( username: "MisterWhiskers", email: "hello@test.com", custom: { @@ -206,7 +206,7 @@ Future group(String groupId, {GroupTraits? groupTraits}); Example usage: ```dart -analytics.group("some-company", groupTraits: GroupTraits( +Analytics.instance.group("some-company", groupTraits: GroupTraits( name: 'Segment', custom: { "region": "UK" @@ -227,7 +227,7 @@ Future alias(String newUserId); Example usage: ```dart -analytics.alias("user-123"); +Analytics.instance.alias("user-123"); ``` ### Reset @@ -245,7 +245,7 @@ void reset(); Example usage: ```dart -analytics.reset(); +Analytics.instance.reset(); ``` ### Flush @@ -261,21 +261,21 @@ Future flush(); Example usage: ```dart -analytics.flush(); +Analytics.instance.flush(); ``` ### (Advanced) Cleanup You probably don't need this! -In case you need to reinitialize the client, that is, you've called `createClient` more than once for the same client in your application lifecycle, use this method _on the old client_ to clear any subscriptions and timers first. +In case you need to reinitialize the client, that is, you've called `Analytics.init` more than once for the same client in your application lifecycle, use this method _on the old client_ to clear any subscriptions and timers first. ```dart -var analytics = createClient(Configuration(writeKey)); +Analytics.init(Configuration(writeKey)); -analytics.cleanup(); +Analytics.instance.cleanup(); -analytics = createClient(Configuration(writeKey)); +Analytics.init(Configuration(writeKey)); ``` If you don't do this, the old client instance would still exist and retain the timers, making all your events fire twice. @@ -321,7 +321,7 @@ Or if you prefer, you can pass `autoAddSegmentDestination = false` in the option You can add a plugin at any time through the `add()` method. ```dart -import 'package:analytics/client.dart'; +import 'package:analytics/analytics.dart'; import 'package:analytics/event.dart'; import 'package:analytics/state.dart'; import 'package:analytics_plugin_advertising_id/plugin_advertising_id.dart'; @@ -332,17 +332,17 @@ import 'package:analytics_plugin_firebase/plugin_firebase.dart' const writeKey = 'SEGMENT_API_KEY'; class _MyAppState extends State { - final analytics = createClient(Configuration(writeKey)); + Analytics.init(Configuration(writeKey)); @override void initState() { super.initState(); initPlatformState(); - analytics + Analytics.instance. .addPlugin(FirebaseDestination(DefaultFirebaseOptions.currentPlatform)); - analytics.addPlugin(PluginAdvertisingId()); - analytics.addPlugin(PluginIdfa()); + Analytics.instance..addPlugin(PluginAdvertisingId()); + Analytics.instance..addPlugin(PluginIdfa()); } } ``` @@ -415,7 +415,7 @@ To make use of flush policies you can set them in the configuration of the clien import 'package:analytics/flush_policies/count_flush_policy.dart'; import 'package:analytics/flush_policies/timer_flush_policy.dart'; -final analytics = createClient(Configuration(/*...*/, flushPolicies: [ +Analytics.init(Configuration(/*...*/, flushPolicies: [ CountFlushPolicy(10), TimerFlushPolicy(100000) ])); @@ -438,9 +438,9 @@ For example you might want to disable flushes if you detect the user has no netw ```dart if (isConnected) { - analytics.addFlushPolicy(policiesIfNetworkIsUp); + Analytics.instance.addFlushPolicy(policiesIfNetworkIsUp); } else { - analytics.removeFlushPolicy(policiesIfNetworkIsUp) + Analytics.instance.removeFlushPolicy(policiesIfNetworkIsUp) } ``` @@ -538,16 +538,16 @@ final flushPolicies = [CountFlushPolicy(5), TimerFlushPolicy(500)]; void errorHandler(Exception error) { if (error is NetworkServerLimited) { // Remove all flush policies - analytics.removeFlushPolicy(analytics.getFlushPolicies()); + Analytics.instance.removeFlushPolicy(Analytics.instance.getFlushPolicies()); // Add less persistent flush policies - analytics.addFlushPolicy([ + Analytics.instance.addFlushPolicy([ CountFlushPolicy(100), TimerFlushPolicy(5000) ]); } } -final analytics = createClient(Configuration(writeKey), +Analytics.init(Configuration(writeKey), errorHandler: errorHandler, flushPolicies: flushPolicies); ``` @@ -564,7 +564,7 @@ import 'package:analytics/errors.dart'; try { distinctId = await mixpanel.getDistinctId(); } catch (e) { - analytics.error( + Analytics.instance.error( PluginError('Error: Mixpanel error calling getDistinctId', e) ); } diff --git a/packages/plugins/plugin_adjust/README.md b/packages/plugins/plugin_adjust/README.md index be38e2e..0a85878 100644 --- a/packages/plugins/plugin_adjust/README.md +++ b/packages/plugins/plugin_adjust/README.md @@ -7,10 +7,9 @@ Manually add this package to your `pubspec.yaml` file. ```yaml -dependencies: - - analytics_plugin_adjust: - git: +dependencies: + analytics_plugin_adjust: + git: url: https://github.com/segmentio/analytics_flutter ref: main path: packages/plugins/plugin_adjust @@ -20,23 +19,23 @@ dependencies: Follow the [instructions for adding plugins](https://github.com/segmentio/analytics_flutter_#adding-plugins) on the main Analytics client: -In your code where you initialize the analytics client call the `.add(plugin)` method with an `AdjustDestination` instance. +In your code where you initialize the analytics client call the `.add(plugin)` method with an `AdjustDestination` instance. ```dart -import 'package:analytics/client.dart'; +import 'package:analytics/analytics.dart'; import 'package:analytics_plugin_adjust/plugin_adjust.dart' show AdjustDestination; const writeKey = 'SEGMENT_API_KEY'; class _MyAppState extends State { - final analytics = createClient(Configuration(writeKey)); + Analytics.init(Configuration(writeKey)); @override void initState() { // ... - analytics + Analytics.instance .addPlugin(AdjustDestination()); } } @@ -51,6 +50,7 @@ Please use Github issues, Pull Requests, or feel free to reach out to our [suppo Interested in integrating your service with us? Check out our [Partners page](https://segment.com/partners/) for more details. ## License + ``` MIT License @@ -73,4 +73,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` \ No newline at end of file +``` diff --git a/packages/plugins/plugin_advertising_id/README.md b/packages/plugins/plugin_advertising_id/README.md index 3691817..aa0e874 100644 --- a/packages/plugins/plugin_advertising_id/README.md +++ b/packages/plugins/plugin_advertising_id/README.md @@ -7,16 +7,15 @@ Manually add this package to your `pubspec.yaml` file. ```yaml -dependencies: - - analytics_plugin_advertising_id: - git: +dependencies: + analytics_plugin_advertising_id: + git: url: https://github.com/segmentio/analytics_flutter ref: main path: packages/plugins/plugin_advertising_id ``` -This plugin requires a `compileSdkVersion` of at least 19. +This plugin requires a `compileSdkVersion` of at least 19. See [Google Play Services documentation](https://developers.google.com/admob/android/quick-start) for `advertisingId` setup @@ -24,23 +23,23 @@ See [Google Play Services documentation](https://developers.google.com/admob/and Follow the [instructions for adding plugins](https://github.com/segmentio/analytics_flutter_#adding-plugins) on the main Analytics client: -In your code where you initialize the analytics client call the `.add(plugin)` method with an `AppsFlyerDestination` instance. +In your code where you initialize the analytics client call the `.add(plugin)` method with an `AppsFlyerDestination` instance. ```dart -import 'package:analytics/client.dart'; +import 'package:analytics/analytics.dart'; import 'package:analytics_plugin_advertising_id/plugin_advertising_id.dart' show PluginAdvertisingId; const writeKey = 'SEGMENT_API_KEY'; class _MyAppState extends State { - final analytics = createClient(Configuration(writeKey)); + Analytics.init(Configuration(writeKey)); @override void initState() { // ... - analytics + Analytics.instance .addPlugin(PluginAdvertisingId()); } } @@ -74,4 +73,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` \ No newline at end of file +``` diff --git a/packages/plugins/plugin_appsflyer/README.md b/packages/plugins/plugin_appsflyer/README.md index 70d9df8..6e12a9f 100644 --- a/packages/plugins/plugin_appsflyer/README.md +++ b/packages/plugins/plugin_appsflyer/README.md @@ -7,10 +7,9 @@ Manually add this package to your `pubspec.yaml` file. ```yaml -dependencies: - - analytics_plugin_appsflyer: - git: +dependencies: + analytics_plugin_appsflyer: + git: url: https://github.com/segmentio/analytics_flutter ref: main path: packages/plugins/plugin_appsflyer @@ -20,23 +19,23 @@ dependencies: Follow the [instructions for adding plugins](https://github.com/segmentio/analytics_flutter_#adding-plugins) on the main Analytics client: -In your code where you initialize the analytics client call the `.add(plugin)` method with an `AppsFlyerDestination` instance. +In your code where you initialize the analytics client call the `.add(plugin)` method with an `AppsFlyerDestination` instance. ```dart -import 'package:analytics/client.dart'; +import 'package:analytics/analytics.dart'; import 'package:analytics_plugin_appsflyer/plugin_appsflyer.dart' show AppsFlyerDestination; const writeKey = 'SEGMENT_API_KEY'; class _MyAppState extends State { - final analytics = createClient(Configuration(writeKey)); + Analytics.init(Configuration(writeKey)); @override void initState() { // ... - analytics + Analytics.instance .addPlugin(AppsFlyerDestination()); } } @@ -51,6 +50,7 @@ Please use Github issues, Pull Requests, or feel free to reach out to our [suppo Interested in integrating your service with us? Check out our [Partners page](https://segment.com/partners/) for more details. ## License + ``` MIT License @@ -73,4 +73,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` \ No newline at end of file +``` diff --git a/packages/plugins/plugin_firebase/README.md b/packages/plugins/plugin_firebase/README.md index c3c466b..45ce94f 100644 --- a/packages/plugins/plugin_firebase/README.md +++ b/packages/plugins/plugin_firebase/README.md @@ -7,10 +7,9 @@ Manually add this package to your `pubspec.yaml` file. ```yaml -dependencies: - - analytics_plugin_firebase: - git: +dependencies: + analytics_plugin_firebase: + git: url: https://github.com/segmentio/analytics_flutter ref: main path: packages/plugins/plugin_firebase @@ -22,30 +21,30 @@ You will then need to configure your Firebase settings as per the [core Firebase flutterfire configure ``` -This will create a ```firebase_options.dart``` file under your ```lib``` folder. +This will create a `firebase_options.dart` file under your `lib` folder. ## Usage Follow the [instructions for adding plugins](https://github.com/segmentio/analytics_flutter_#adding-plugins) on the main Analytics client: -In your code where you initialize the analytics client call the `.add(plugin)` method with an `FirebaseDestination` instance. +In your code where you initialize the analytics client call the `.add(plugin)` method with an `FirebaseDestination` instance. ```dart import 'firebase_options.dart'; -import 'package:analytics/client.dart'; +import 'package:analytics/analytics.dart'; import 'package:analytics_plugin_firebase/plugin_firebase.dart' show FirebaseDestination; const writeKey = 'SEGMENT_API_KEY'; class _MyAppState extends State { - final analytics = createClient(Configuration(writeKey)); + Analytics.init(Configuration(writeKey)); @override void initState() { // ... - analytics + Analytics.instance .addPlugin(FirebaseDestination(DefaultFirebaseOptions.currentPlatform)); } } @@ -60,6 +59,7 @@ Please use Github issues, Pull Requests, or feel free to reach out to our [suppo Interested in integrating your service with us? Check out our [Partners page](https://segment.com/partners/) for more details. ## License + ``` MIT License @@ -82,4 +82,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` \ No newline at end of file +``` diff --git a/packages/plugins/plugin_idfa/README.md b/packages/plugins/plugin_idfa/README.md index 6241926..871e54b 100644 --- a/packages/plugins/plugin_idfa/README.md +++ b/packages/plugins/plugin_idfa/README.md @@ -9,10 +9,9 @@ Manually add this package to your `pubspec.yaml` file. ```yaml -dependencies: - - analytics_plugin_idfa: - git: +dependencies: + analytics_plugin_idfa: + git: url: https://github.com/segmentio/analytics_flutter ref: main path: packages/plugins/plugin_idfa @@ -24,40 +23,41 @@ You also need to ensure you have a description for `NSUserTrackingUsageDescripti Follow the [instructions for adding plugins](https://github.com/segmentio/analytics_flutter_#adding-plugins) on the main Analytics client: -In your code where you initialize the analytics client call the `.add(plugin)` method with an `AppsFlyerDestination` instance. +In your code where you initialize the analytics client call the `.add(plugin)` method with an `AppsFlyerDestination` instance. ```dart -import 'package:analytics/client.dart'; +import 'package:analytics/analytics.dart'; import 'package:analytics_plugin_idfa/plugin_idfa.dart' show PluginIdfa; const writeKey = 'SEGMENT_API_KEY'; class _MyAppState extends State { - final analytics = createClient(Configuration(writeKey)); + Analytics.init(Configuration(writeKey)); @override void initState() { // ... - analytics + Analytics.instance .addPlugin(PluginIdfa()); } } ``` + ## Customize IDFA Plugin Initialization -To delay the `IDFA Plugin` initialization (ie. to avoid race condition with push notification prompt) implement the following: +To delay the `IDFA Plugin` initialization (ie. to avoid race condition with push notification prompt) implement the following: ```dart -import 'package:analytics/client.dart'; +import 'package:analytics/analytics.dart'; import 'package:analytics_plugin_idfa/plugin_idfa.dart' show PluginIdfa; const writeKey = 'SEGMENT_API_KEY'; class _MyAppState extends State { - final analytics = createClient(Configuration(writeKey)); + Analytics.init(Configuration(writeKey)); @override void initState() { @@ -65,11 +65,11 @@ class _MyAppState extends State { final idfaPlugin = PluginIdfa(shouldAskPermission: false); - analytics + Analytics.instance .addPlugin(idfaPlugin); // ... - + idfaPlugin.requestTrackingPermission().then((enabled) { /** ... */ }); @@ -86,6 +86,7 @@ Please use Github issues, Pull Requests, or feel free to reach out to our [suppo Interested in integrating your service with us? Check out our [Partners page](https://segment.com/partners/) for more details. ## License + ``` MIT License @@ -108,4 +109,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` \ No newline at end of file +``` From 114e839bbda8a0eb2afffe42e18322e8eef8a2c2 Mon Sep 17 00:00:00 2001 From: Debkanchan Samadder Date: Sun, 16 Jul 2023 20:09:14 +0530 Subject: [PATCH 6/6] fix: handle unknown value types for firebase analytics --- packages/plugins/plugin_firebase/lib/properties.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/plugins/plugin_firebase/lib/properties.dart b/packages/plugins/plugin_firebase/lib/properties.dart index db3451c..764b0a5 100644 --- a/packages/plugins/plugin_firebase/lib/properties.dart +++ b/packages/plugins/plugin_firebase/lib/properties.dart @@ -28,6 +28,16 @@ String sanitizeEventName(String eventName) { return eventName.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '_'); } +Map castParameterType(Map properties) { + return properties.map((key, value) { + if (value is String || value is num || value == null) { + return MapEntry(key, value); + } else { + return MapEntry(key, value.toString()); + } + }); +} + @JsonSerializable() class AnalyticsEventItemJson extends AnalyticsEventItem { AnalyticsEventItemJson(Map json)