diff --git a/example/pubspec.lock b/example/pubspec.lock index 69f18f9..308d45a 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -50,20 +50,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" - ffi: - dependency: transitive - description: - name: ffi - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - file: - dependency: transitive - description: - name: file - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.0" flutter: dependency: "direct main" description: flutter @@ -74,11 +60,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" http: dependency: transitive description: @@ -93,13 +74,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.0" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.3" matcher: dependency: transitive description: @@ -128,27 +102,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" pedantic: dependency: transitive description: @@ -156,69 +109,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.11.0" - platform: - dependency: transitive - description: - name: platform - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - process: - dependency: transitive - description: - name: process - url: "https://pub.dartlang.org" - source: hosted - version: "4.1.0" - shared_preferences: - dependency: transitive - description: - name: shared_preferences - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.3" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - shared_preferences_macos: - dependency: transitive - description: - name: shared_preferences_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" sky_engine: dependency: transitive description: flutter @@ -280,20 +170,5 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" - win32: - dependency: transitive - description: - name: win32 - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0" sdks: dart: ">=2.12.0 <3.0.0" - flutter: ">=1.20.0" diff --git a/lib/src/mixpanel_analytics.dart b/lib/src/mixpanel_analytics.dart index f244375..885326e 100644 --- a/lib/src/mixpanel_analytics.dart +++ b/lib/src/mixpanel_analytics.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; -import 'package:shared_preferences/shared_preferences.dart'; +// import 'package:shared_preferences/shared_preferences.dart'; enum MixpanelUpdateOperations { $set, @@ -16,6 +16,40 @@ enum MixpanelUpdateOperations { $delete, } +abstract class StringCache { + Future getString(String key); + Future setString(String key, String value); +} + +class InMemoryStringCache implements StringCache { + final _map = {}; + + @override + Future getString(String key) => Future.value(_map[key]); + + @override + Future setString(String key, String value) { + _map[key] = value; + return Future.value(true); + } +} + +// class SharedPreferencesStringCache implements StringCache { +// SharedPreferences? _prefs; +// +// @override +// Future getString(String key) async { +// _prefs ??= await SharedPreferences.getInstance(); +// return _prefs!.getString(key); +// } +// +// @override +// Future setString(String key, String value) async { +// _prefs ??= await SharedPreferences.getInstance(); +// return _prefs!.setString(key, value); +// } +// } + typedef ShaFn = String Function(String value); class MixpanelAnalytics { @@ -33,10 +67,7 @@ class MixpanelAnalytics { /// Will be zero by default Duration _uploadInterval = Duration.zero; - /// In case we use [MixpanelAnalytics.batch()] we need to provide a storage provider - /// This will be used to save the events not sent - @visibleForTesting - SharedPreferences? prefs; + final StringCache _cache; /// If exists, will be sent in the event, otherwise anonymousId will be used. final Stream? _userId$; @@ -129,6 +160,7 @@ class MixpanelAnalytics { /// [baseApiUrl] Ingestion API URL. If you don't inform it, the US-based url will be used (api.mixpanel.com). https://developer.mixpanel.com/docs/privacy-security#storing-your-data-in-the-european-union MixpanelAnalytics({ required String token, + StringCache? cache, Stream? userId$, bool shouldAnonymize = false, ShaFn shaFn = _defaultShaFn, @@ -140,6 +172,7 @@ class MixpanelAnalytics { String? prefsKey, String? baseApiUrl, }) : _token = token, + _cache = cache ?? InMemoryStringCache(), _userId$ = userId$, _verbose = verbose, _useIp = useIp, @@ -169,6 +202,7 @@ class MixpanelAnalytics { /// [baseApiUrl] Ingestion API URL. If you don't inform it, the US-based url will be used (api.mixpanel.com). https://developer.mixpanel.com/docs/privacy-security#storing-your-data-in-the-european-union MixpanelAnalytics.batch({ required String token, + StringCache? cache, required Duration uploadInterval, Stream? userId$, bool shouldAnonymize = false, @@ -181,6 +215,7 @@ class MixpanelAnalytics { String? prefsKey, String? baseApiUrl, }) : _token = token, + _cache = cache ?? InMemoryStringCache(), _userId$ = userId$, _verbose = verbose, _useIp = useIp, @@ -269,8 +304,7 @@ class MixpanelAnalytics { /// Reads queued events from the storage when we are in batch mode. /// We do this in case the app was closed with events pending to be sent. Future _restoreQueuedEventsFromStorage() async { - prefs ??= await SharedPreferences.getInstance(); - final encoded = prefs!.getString(_prefsKey); + final encoded = await _cache.getString(_prefsKey); if (encoded != null) { Map events = json.decode(encoded); _queuedEvents.addAll(events); @@ -279,10 +313,9 @@ class MixpanelAnalytics { /// If we are in batch mode we save all events in storage in case the app is closed. Future _saveQueuedEventsToLocalStorage() async { - prefs ??= await SharedPreferences.getInstance(); final encoded = json.encode(_queuedEvents); final result = - await prefs!.setString(_prefsKey, encoded).catchError((error) { + await _cache.setString(_prefsKey, encoded).catchError((error) { _onErrorHandler(error, 'Error saving events in storage'); return false; }); diff --git a/pubspec.lock b/pubspec.lock index 6d3e0d4..03b771c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -169,13 +169,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" - ffi: - dependency: transitive - description: - name: ffi - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" file: dependency: transitive description: @@ -200,11 +193,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" glob: dependency: transitive description: @@ -310,27 +298,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" pedantic: dependency: transitive description: @@ -338,20 +305,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.11.0" - platform: - dependency: transitive - description: - name: platform - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" pool: dependency: transitive description: @@ -359,13 +312,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.5.0" - process: - dependency: transitive - description: - name: process - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.1" pub_semver: dependency: transitive description: @@ -380,48 +326,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" - shared_preferences: - dependency: "direct main" - description: - name: shared_preferences - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.5" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - shared_preferences_macos: - dependency: transitive - description: - name: shared_preferences_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" shelf: dependency: transitive description: @@ -532,20 +436,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" - win32: - dependency: transitive - description: - name: win32 - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0" yaml: dependency: transitive description: @@ -555,4 +445,3 @@ packages: version: "3.1.0" sdks: dart: ">=2.12.0 <3.0.0" - flutter: ">=1.20.0" diff --git a/pubspec.yaml b/pubspec.yaml index d68edb7..0f21c33 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: sdk: flutter http: ^0.13.0 - shared_preferences: ^2.0.3 +# shared_preferences: ^2.0.3 dev_dependencies: flutter_test: diff --git a/test/mixpanel_analytics_test.dart b/test/mixpanel_analytics_test.dart index 93eb523..992f7c4 100644 --- a/test/mixpanel_analytics_test.dart +++ b/test/mixpanel_analytics_test.dart @@ -6,7 +6,6 @@ import 'package:http/http.dart' show Client, Response; import 'package:mixpanel_analytics/mixpanel_analytics.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'mixpanel_analytics_test.mocks.dart'; @@ -20,22 +19,12 @@ const Map fakeResponseNoVerbose = {'ok': '1', 'nook': '0'}; const String fakeNoOkResponseNoVerbose = '0'; -@GenerateMocks([Client, SharedPreferences]) +@GenerateMocks([Client]) void main() { late MockClient http; - late MockSharedPreferences prefs; late MixpanelAnalytics sut; late StreamController userId$; - void stubPrefsSetString() { - when(prefs.setString('mixpanel.analytics', any)) - .thenAnswer((_) async => true); - } - - void stubPrefsGetString(String? value) { - when(prefs.getString('mixpanel.analytics')).thenReturn(value); - } - String base64Encoder(Object event) { final str = json.encode(event); final bytes = utf8.encode(str); @@ -160,7 +149,6 @@ void main() { setUp(() { userId$ = StreamController(); - prefs = MockSharedPreferences(); http = MockClient(); sut = MixpanelAnalytics.batch( token: mixpanelToken, @@ -169,9 +157,7 @@ void main() { verbose: false, useIp: false, onError: (_) {}, - ) - ..http = http - ..prefs = prefs; + )..http = http; userId$.add(userId); }); @@ -183,9 +169,6 @@ void main() { test( '.track() sends a bunch of events in batch to mixpanel with proper syntax using REST API after X seconds', () async { - stubPrefsSetString(); - stubPrefsGetString(null); - stubPost(Response(fakeResponseNoVerbose['ok']!, 200)); final expected = { @@ -271,10 +254,6 @@ void main() { }, }; - stubPrefsSetString(); - - stubPrefsGetString(json.encode(events)); - stubPost(Response(fakeResponseNoVerbose['ok']!, 200)); verifyZeroInteractions(http);