From d3513089b74706bf264e801d4b724d545946bd1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petrus=20Nguy=E1=BB=85n=20Th=C3=A1i=20H=E1=BB=8Dc?= Date: Sat, 10 Oct 2020 19:35:34 +0700 Subject: [PATCH] Dev: 1.3.2 (#10) * updated stream extensions * added extension * added extension --- CHANGELOG.md | 9 ++ README.md | 5 +- example/pubspec.lock | 144 +++++++++++++++--- lib/rx_shared_preferences.dart | 1 + lib/src/config/global_config.dart | 7 + lib/src/extensions/preferences_extension.dart | 24 +++ lib/src/impl/real_rx_shared_preferences.dart | 13 +- lib/src/interface/rx_shared_preferences.dart | 7 +- .../map_not_null_stream_transformer.dart | 10 +- pubspec.lock | 142 ++++++++++++++--- pubspec.yaml | 3 +- test/streams_test.dart | 14 ++ 12 files changed, 317 insertions(+), 62 deletions(-) create mode 100644 lib/src/config/global_config.dart create mode 100644 lib/src/extensions/preferences_extension.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 343ce2b..8471049 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## 1.3.2 - Oct 10, 2020 + +* Add extension: `RxSharedPreferences get rx` for `SharedPreferences`. + This allows writing concise code like this: `sharedPreferences.rx.getStringStream('key')`. + +* Allows changing logger for default singleton instance or extension: `RxSharedPreferencesConfig.logger = ...`; + +* Internal implementation refactor. + ## 1.3.1 - May 29, 2020 * Update docs. diff --git a/README.md b/README.md index 9de9af7..4085d34 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ In your flutter project, add the dependency to your `pubspec.yaml` ```yaml dependencies: ... - rx_shared_preferences: ^1.3.0 + rx_shared_preferences: ^1.3.2 ``` ## Usage @@ -57,6 +57,9 @@ Wrap your `SharedPreferences` in a `RxSharedPreferences`. final rxPrefs = RxSharedPreferences(await SharedPreferences.getInstance()); final rxPrefs = RxSharedPreferences(SharedPreferences.getInstance()); // await is optional final rxPrefs = RxSharedPreferences.getInstance(); // default singleton instance + +// via extension. +final rxPrefs = (await SharedPreferences.getInstance()).rx; ``` ### 2. Can add a logger diff --git a/example/pubspec.lock b/example/pubspec.lock index 5b59f86..d70a73a 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,35 +7,42 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.5.0-nullsafety" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0-nullsafety.2" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0-nullsafety" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0-nullsafety" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" + version: "1.15.0-nullsafety.2" cupertino_icons: dependency: "direct main" description: @@ -49,7 +56,21 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.0-nullsafety" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "5.2.1" flutter: dependency: "direct main" description: flutter @@ -65,27 +86,55 @@ packages: description: flutter source: sdk version: "0.0.0" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10-nullsafety" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.2" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+2" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4+1" pedantic: dependency: "direct dev" description: @@ -93,13 +142,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.13" rx_shared_preferences: dependency: "direct main" description: path: ".." relative: true source: path - version: "1.3.0" + version: "1.3.2" rxdart: dependency: transitive description: @@ -113,28 +183,42 @@ packages: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "0.5.7+3" + version: "0.5.12" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.2+2" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+3" + version: "0.0.1+10" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.0.4" shared_preferences_web: dependency: transitive description: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.2+2" + version: "0.1.2+7" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+1" sky_engine: dependency: transitive description: flutter @@ -146,56 +230,70 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0-nullsafety" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.15" + version: "0.2.19-nullsafety" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0-nullsafety.2" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.2" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" sdks: - dart: ">=2.6.0 <3.0.0" + dart: ">=2.10.0-0.0.dev <2.10.0" flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/lib/rx_shared_preferences.dart b/lib/rx_shared_preferences.dart index d1d5b24..d8c9ebc 100644 --- a/lib/rx_shared_preferences.dart +++ b/lib/rx_shared_preferences.dart @@ -5,6 +5,7 @@ /// library rx_shared_preferences; +export 'src/extensions/preferences_extension.dart'; export 'src/interface/rx_shared_preferences.dart'; export 'src/interface/shared_preferences_like.dart'; export 'src/logger/default_logger.dart'; diff --git a/lib/src/config/global_config.dart b/lib/src/config/global_config.dart new file mode 100644 index 0000000..24d39c2 --- /dev/null +++ b/lib/src/config/global_config.dart @@ -0,0 +1,7 @@ +import '../../rx_shared_preferences.dart'; + +/// Global config for default singleton or extension. +class RxSharedPreferencesConfig { + /// Config for logger. + static Logger logger = const DefaultLogger(); +} diff --git a/lib/src/extensions/preferences_extension.dart b/lib/src/extensions/preferences_extension.dart new file mode 100644 index 0000000..90e6820 --- /dev/null +++ b/lib/src/extensions/preferences_extension.dart @@ -0,0 +1,24 @@ +import 'package:rx_shared_preferences/rx_shared_preferences.dart'; +import 'package:rx_shared_preferences/src/config/global_config.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +final _instances = {}; + +/// Provide [RxSharedPreferences] via [rx] getter. +extension SharedPreferencesRxExtension on SharedPreferences { + /// Returns singleton instance associated with this [SharedPreferences]. + RxSharedPreferences get rx { + final instances = _instances; + + final cached = instances[this]; + if (cached != null) { + return cached; + } + + return instances[this] = RxSharedPreferences( + this, + RxSharedPreferencesConfig.logger, + () => instances.remove(this), + ); + } +} diff --git a/lib/src/impl/real_rx_shared_preferences.dart b/lib/src/impl/real_rx_shared_preferences.dart index 50aff07..128efa2 100644 --- a/lib/src/impl/real_rx_shared_preferences.dart +++ b/lib/src/impl/real_rx_shared_preferences.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:collection'; import 'package:rx_shared_preferences/rx_shared_preferences.dart'; +import 'package:rx_shared_preferences/src/config/global_config.dart'; import 'package:rx_shared_preferences/src/stream_extensions/single_subscription.dart'; import 'package:rxdart/rxdart.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -31,12 +32,16 @@ class RealRxSharedPreferences implements RxSharedPreferences { /// final Logger _logger; + /// On dispose + void Function() _onDispose; + /// /// Construct a [RealRxSharedPreferences] with [sharedPreference] and optional logger /// RealRxSharedPreferences( FutureOr sharedPreference, [ this._logger, + this._onDispose, ]) : assert(sharedPreference != null), _sharedPrefsFuture = Future.value(sharedPreference) { _subscription = _keyValuesSubject.listen((map) { @@ -53,7 +58,8 @@ class RealRxSharedPreferences implements RxSharedPreferences { factory RealRxSharedPreferences.getInstance() => _defaultInstance ??= RealRxSharedPreferences( SharedPreferences.getInstance(), - const DefaultLogger(), + RxSharedPreferencesConfig.logger, + () => _defaultInstance = null, ); // @@ -317,9 +323,6 @@ class RealRxSharedPreferences implements RxSharedPreferences { .where((future) => future != null); await Future.wait(futures); - // if dispose default instance, then set it to null - if (identical(this, _defaultInstance)) { - _defaultInstance = null; - } + _onDispose?.call(); } } diff --git a/lib/src/interface/rx_shared_preferences.dart b/lib/src/interface/rx_shared_preferences.dart index e16350a..2636e2d 100644 --- a/lib/src/interface/rx_shared_preferences.dart +++ b/lib/src/interface/rx_shared_preferences.dart @@ -15,8 +15,13 @@ abstract class RxSharedPreferences implements SharedPreferencesLike { factory RxSharedPreferences( FutureOr sharedPreference, [ Logger logger, + void Function() onDispose, ]) => - RealRxSharedPreferences(sharedPreference, logger); + RealRxSharedPreferences( + sharedPreference, + logger, + onDispose, + ); /// /// Return default singleton instance diff --git a/lib/src/stream_extensions/map_not_null_stream_transformer.dart b/lib/src/stream_extensions/map_not_null_stream_transformer.dart index 9591c12..d5dd965 100644 --- a/lib/src/stream_extensions/map_not_null_stream_transformer.dart +++ b/lib/src/stream_extensions/map_not_null_stream_transformer.dart @@ -14,12 +14,6 @@ class MapNotNullStreamTransformer extends StreamTransformerBase { StreamController controller; StreamSubscription subscription; - void onDone() { - if (!controller.isClosed) { - controller.close(); - } - } - void onListen() { subscription = stream.listen( (data) { @@ -37,7 +31,7 @@ class MapNotNullStreamTransformer extends StreamTransformerBase { } }, onError: controller.addError, - onDone: onDone, + onDone: controller.close, ); } @@ -53,7 +47,7 @@ class MapNotNullStreamTransformer extends StreamTransformerBase { controller = StreamController( sync: true, onListen: onListen, - onPause: ([Future resumeSignal]) => subscription.pause(resumeSignal), + onPause: () => subscription.pause(), onResume: () => subscription.resume(), onCancel: onCancel, ); diff --git a/pubspec.lock b/pubspec.lock index e20caf8..99ae061 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,42 +7,63 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.5.0-nullsafety" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0-nullsafety.2" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0-nullsafety" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0-nullsafety" collection: dependency: "direct dev" description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" + version: "1.15.0-nullsafety.2" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.0-nullsafety" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "5.2.1" flutter: dependency: "direct main" description: flutter @@ -58,27 +79,55 @@ packages: description: flutter source: sdk version: "0.0.0" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10-nullsafety" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.2" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+2" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4+1" pedantic: dependency: "direct dev" description: @@ -86,6 +135,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.13" rxdart: dependency: "direct main" description: @@ -99,14 +169,21 @@ packages: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "0.5.7+3" + version: "0.5.12" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.2+2" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+3" + version: "0.0.1+10" shared_preferences_platform_interface: dependency: "direct dev" description: @@ -120,7 +197,14 @@ packages: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.2+2" + version: "0.1.2+7" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+1" sky_engine: dependency: transitive description: flutter @@ -132,56 +216,70 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0-nullsafety" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety" test_api: - dependency: "direct dev" + dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.15" + version: "0.2.19-nullsafety" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0-nullsafety.2" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.2" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" sdks: - dart: ">=2.6.0 <3.0.0" + dart: ">=2.10.0-0.0.dev <2.10.0" flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 0eb0835..e796fa2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: rx_shared_preferences description: Rxdart streaming shared preferences. Reactive stream rxdart wrapper around SharedPreferences. A stream based wrapper over shared_preferences, allowing reactive key-value storage. -version: 1.3.1 +version: 1.3.2 homepage: https://github.com/hoc081098/rx_shared_preferences.git repository: https://github.com/hoc081098/rx_shared_preferences.git issue_tracker: https://github.com/hoc081098/rx_shared_preferences/issues @@ -17,7 +17,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - test_api: ^0.2.11 pedantic: ^1.9.0 shared_preferences_platform_interface: ^1.0.4 collection: ^1.14.11 diff --git a/test/streams_test.dart b/test/streams_test.dart index dbca7fe..654b57c 100644 --- a/test/streams_test.dart +++ b/test/streams_test.dart @@ -359,5 +359,19 @@ void main() { stream.listen(null); expect(() => stream.listen(null), throwsStateError); }); + + test('rx', () async { + final prefs = await SharedPreferences.getInstance(); + + expect(prefs.rx.getStringStream('key'), emits(anything)); + expect(prefs.rx.getStringListStream('flutter.List'), emits(anything)); + expect(prefs.rx.getDoubleStream('flutter.double'), emits(anything)); + + final old = prefs.rx; + expect(identical(old, prefs.rx), true); + + await old.dispose(); + expect(identical(old, prefs.rx), false); + }); }); }