Skip to content

Commit

Permalink
[shared_preferences] Adds new clearWithParameters and `getAllWithPa…
Browse files Browse the repository at this point in the history
…rameters` methods to platform interface. (#4261)

Adds new `clearWithParameters` and `getAllWithParameters` methods.

part of flutter/flutter#128948

precursor to #3794

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [relevant style guides] and ran the
auto-formatter. (Unlike the flutter/flutter repo, the flutter/packages
repo does use `dart format`.)
- [x] I signed the [CLA].
- [x] The title of the PR starts with the name of the package surrounded
by square brackets, e.g. `[shared_preferences]`
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated `pubspec.yaml` with an appropriate new version according
to the [pub versioning philosophy], or this PR is [exempt from version
changes].
- [x] I updated `CHANGELOG.md` to add a description of the change,
[following repository CHANGELOG style].
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/packages/blob/main/CONTRIBUTING.md
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[relevant style guides]:
https://github.com/flutter/packages/blob/main/CONTRIBUTING.md#style
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
[pub versioning philosophy]: https://dart.dev/tools/pub/versioning
[exempt from version changes]:
https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#version-and-changelog-updates
[following repository CHANGELOG style]:
https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#changelog-style
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
  • Loading branch information
tarrinneal committed Jun 27, 2023
1 parent 4e71ead commit e073e55
Show file tree
Hide file tree
Showing 12 changed files with 348 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ class SharedPreferences {
_preferenceCache.clear();
if (_prefixHasBeenChanged) {
try {
// ignore: deprecated_member_use
return _store.clearWithPrefix(_prefix);
} catch (e) {
// Catching and clarifying UnimplementedError to provide a more robust message.
Expand Down Expand Up @@ -213,6 +214,7 @@ Either update the implementation to support setPrefix, or do not call setPrefix.
final Map<String, Object> fromSystem = <String, Object>{};
if (_prefixHasBeenChanged) {
try {
// ignore: deprecated_member_use
fromSystem.addAll(await _store.getAllWithPrefix(_prefix));
} catch (e) {
// Catching and clarifying UnimplementedError to provide a more robust message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ class FakeSharedPreferencesStore extends SharedPreferencesStorePlatform {
@override
Future<Map<String, Object>> getAllWithPrefix(String prefix) {
log.add(const MethodCall('getAllWithPrefix'));
// ignore: deprecated_member_use
return backend.getAllWithPrefix(prefix);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ void main() {
});

tearDown(() {
// ignore: deprecated_member_use
preferences.clearWithPrefix('');
});

testWidgets('reading', (WidgetTester _) async {
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values['String'], isNull);
expect(values['Bool'], isNull);
Expand Down Expand Up @@ -83,6 +85,7 @@ void main() {
allTestValues['flutter.StringList']!)
]);
final Map<String, Object> values =
// ignore: deprecated_member_use
await preferences.getAllWithPrefix('prefix.');
expect(values['prefix.String'], allTestValues['prefix.String']);
expect(values['prefix.Bool'], allTestValues['prefix.Bool']);
Expand Down Expand Up @@ -113,14 +116,17 @@ void main() {
preferences.setValue('StringList', 'flutter.StringList',
allTestValues['flutter.StringList']!)
]);
// ignore: deprecated_member_use
await preferences.clearWithPrefix('prefix.');
Map<String, Object> values =
// ignore: deprecated_member_use
await preferences.getAllWithPrefix('prefix.');
expect(values['prefix.String'], null);
expect(values['prefix.Bool'], null);
expect(values['prefix.Int'], null);
expect(values['prefix.Double'], null);
expect(values['prefix.StringList'], null);
// ignore: deprecated_member_use
values = await preferences.getAllWithPrefix('flutter.');
expect(values['flutter.String'], allTestValues['flutter.String']);
expect(values['flutter.Bool'], allTestValues['flutter.Bool']);
Expand Down Expand Up @@ -148,6 +154,7 @@ void main() {
preferences.setValue('StringList', 'flutter.StringList',
allTestValues['flutter.StringList']!)
]);
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values['String'], allTestValues['String']);
expect(values['Bool'], allTestValues['Bool']);
Expand Down Expand Up @@ -180,7 +187,9 @@ void main() {
preferences.setValue('StringList', 'flutter.StringList',
allTestValues['flutter.StringList']!)
]);
// ignore: deprecated_member_use
await preferences.clearWithPrefix('');
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values['String'], null);
expect(values['Bool'], null);
Expand Down Expand Up @@ -226,6 +235,7 @@ void main() {
await preferences.setValue(
'StringList', key, allTestValues['flutter.StringList']!);
await preferences.remove(key);
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values[key], isNull);
});
Expand Down Expand Up @@ -260,6 +270,7 @@ void main() {
// All writes should succeed.
expect(result.where((bool element) => !element), isEmpty);
// The last write should win.
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values['Int'], writeCount);
});
Expand All @@ -268,6 +279,7 @@ void main() {
(WidgetTester _) async {
const String key = 'akey';
const String value = 'a string value';
// ignore: deprecated_member_use
await preferences.clearWithPrefix('');

// Special prefixes used to store datatypes that can't be stored directly
Expand All @@ -284,6 +296,7 @@ void main() {
expect(preferences.setValue('String', key, prefix + value),
throwsA(isA<PlatformException>()));
final Map<String, Object> values =
// ignore: deprecated_member_use
await preferences.getAllWithPrefix('');
expect(values[key], null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ void main() {
});

tearDown(() {
// ignore: deprecated_member_use
preferences.clearWithPrefix('');
});

testWidgets('reading', (WidgetTester _) async {
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values['String'], isNull);
expect(values['Bool'], isNull);
Expand Down Expand Up @@ -82,6 +84,7 @@ void main() {
allTestValues['flutter.StringList']!)
]);
final Map<String, Object> values =
// ignore: deprecated_member_use
await preferences.getAllWithPrefix('prefix.');
expect(values['prefix.String'], allTestValues['prefix.String']);
expect(values['prefix.Bool'], allTestValues['prefix.Bool']);
Expand Down Expand Up @@ -112,14 +115,17 @@ void main() {
preferences.setValue('StringList', 'flutter.StringList',
allTestValues['flutter.StringList']!)
]);
// ignore: deprecated_member_use
await preferences.clearWithPrefix('prefix.');
Map<String, Object> values =
// ignore: deprecated_member_use
await preferences.getAllWithPrefix('prefix.');
expect(values['prefix.String'], null);
expect(values['prefix.Bool'], null);
expect(values['prefix.Int'], null);
expect(values['prefix.Double'], null);
expect(values['prefix.StringList'], null);
// ignore: deprecated_member_use
values = await preferences.getAllWithPrefix('flutter.');
expect(values['flutter.String'], allTestValues['flutter.String']);
expect(values['flutter.Bool'], allTestValues['flutter.Bool']);
Expand Down Expand Up @@ -147,6 +153,7 @@ void main() {
preferences.setValue('StringList', 'flutter.StringList',
allTestValues['flutter.StringList']!)
]);
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values['String'], allTestValues['String']);
expect(values['Bool'], allTestValues['Bool']);
Expand Down Expand Up @@ -179,7 +186,9 @@ void main() {
preferences.setValue('StringList', 'flutter.StringList',
allTestValues['flutter.StringList']!)
]);
// ignore: deprecated_member_use
await preferences.clearWithPrefix('');
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values['String'], null);
expect(values['Bool'], null);
Expand Down Expand Up @@ -225,6 +234,7 @@ void main() {
await preferences.setValue(
'StringList', key, allTestValues['flutter.StringList']!);
await preferences.remove(key);
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values[key], isNull);
});
Expand Down Expand Up @@ -259,6 +269,7 @@ void main() {
// All writes should succeed.
expect(result.where((bool element) => !element), isEmpty);
// The last write should win.
// ignore: deprecated_member_use
final Map<String, Object> values = await preferences.getAllWithPrefix('');
expect(values['Int'], writeCount);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## NEXT
## 2.3.0

* Adds `clearWithParameters` and `getAllWithParameters` methods.
* Deprecates `clearWithPrefix` and `getAllWithPrefix` methods.
* Updates minimum supported SDK version to Flutter 3.3/Dart 2.18.

## 2.2.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'dart:async';
import 'package:flutter/services.dart';

import 'shared_preferences_platform_interface.dart';
import 'types.dart';

const MethodChannel _kChannel =
MethodChannel('plugins.flutter.io/shared_preferences');
Expand Down Expand Up @@ -39,25 +40,58 @@ class MethodChannelSharedPreferencesStore
}

@override
@Deprecated('Use clearWithParameters instead')
Future<bool> clearWithPrefix(String prefix) async {
return clearWithParameters(
ClearParameters(
filter: PreferencesFilter(prefix: prefix),
),
);
}

@override
Future<bool> clearWithParameters(ClearParameters parameters) async {
final PreferencesFilter filter = parameters.filter;
return (await _kChannel.invokeMethod<bool>(
'clearWithPrefix',
<String, dynamic>{'prefix': prefix},
'clearWithParameters',
<String, dynamic>{
'prefix': filter.prefix,
'allowList': filter.allowList?.toList(),
},
))!;
}

@override
Future<Map<String, Object>> getAllWithPrefix(String prefix) async {
return await _kChannel.invokeMapMethod<String, Object>(
'getAllWithPrefix',
<String, dynamic>{'prefix': prefix},
) ??
Future<Map<String, Object>> getAll() async {
return await _kChannel.invokeMapMethod<String, Object>('getAll') ??
<String, Object>{};
}

@override
Future<Map<String, Object>> getAll() async {
return await _kChannel.invokeMapMethod<String, Object>('getAll') ??
@Deprecated('Use getAllWithParameters instead')
Future<Map<String, Object>> getAllWithPrefix(
String prefix, {
Set<String>? allowList,
}) async {
return getAllWithParameters(
GetAllParameters(
filter: PreferencesFilter(prefix: prefix),
),
);
}

@override
Future<Map<String, Object>> getAllWithParameters(
GetAllParameters parameters) async {
final PreferencesFilter filter = parameters.filter;
final List<String>? allowListAsList = filter.allowList?.toList();
return await _kChannel.invokeMapMethod<String, Object>(
'getAllWithParameters',
<String, dynamic>{
'prefix': filter.prefix,
'allowList': allowListAsList
},
) ??
<String, Object>{};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';

import 'method_channel_shared_preferences.dart';
import 'types.dart';

/// The interface that implementations of shared_preferences must implement.
///
Expand Down Expand Up @@ -69,11 +70,17 @@ abstract class SharedPreferencesStorePlatform extends PlatformInterface {
/// prefix 'flutter.'.
Future<bool> clear();

/// Removes all keys and values in the store with given prefix.
/// Removes all keys and values in the store with given [prefix].
@Deprecated('Use clearWithParameters instead')
Future<bool> clearWithPrefix(String prefix) {
throw UnimplementedError('clearWithPrefix is not implemented.');
}

/// Removes all keys and values in the store that match [options].
Future<bool> clearWithParameters(ClearParameters parameters) {
throw UnimplementedError('clearWithParameters is not implemented.');
}

/// Returns all key/value pairs persisted in this store where the key starts with 'flutter.'.
///
/// This default behavior is for backwards compatibility with older versions of this
Expand All @@ -82,9 +89,16 @@ abstract class SharedPreferencesStorePlatform extends PlatformInterface {
Future<Map<String, Object>> getAll();

/// Returns all key/value pairs persisting in this store that have given [prefix].
@Deprecated('Use getAllWithParameters instead')
Future<Map<String, Object>> getAllWithPrefix(String prefix) {
throw UnimplementedError('getAllWithPrefix is not implemented.');
}

/// Returns all key/value pairs persisting in this store that match [options].
Future<Map<String, Object>> getAllWithParameters(
GetAllParameters parameters) {
throw UnimplementedError('getAllWithParameters is not implemented.');
}
}

/// Stores data in memory.
Expand All @@ -103,24 +117,60 @@ class InMemorySharedPreferencesStore extends SharedPreferencesStorePlatform {

@override
Future<bool> clear() async {
return clearWithPrefix(_defaultPrefix);
return clearWithParameters(
ClearParameters(
filter: PreferencesFilter(prefix: _defaultPrefix),
),
);
}

@override
Future<bool> clearWithPrefix(String prefix) async {
_data.removeWhere((String key, _) => key.startsWith(prefix));
return clearWithParameters(
ClearParameters(
filter: PreferencesFilter(prefix: prefix),
),
);
}

@override
Future<bool> clearWithParameters(ClearParameters parameters) async {
final PreferencesFilter filter = parameters.filter;
if (filter.allowList != null) {
_data.removeWhere((String key, _) =>
key.startsWith(filter.prefix) && filter.allowList!.contains(key));
} else {
_data.removeWhere((String key, _) => key.startsWith(filter.prefix));
}
return true;
}

@override
Future<Map<String, Object>> getAll() async {
return getAllWithPrefix(_defaultPrefix);
return getAllWithParameters(
GetAllParameters(
filter: PreferencesFilter(prefix: _defaultPrefix),
),
);
}

@override
Future<Map<String, Object>> getAllWithPrefix(String prefix) async {
return getAllWithParameters(
GetAllParameters(
filter: PreferencesFilter(prefix: prefix),
),
);
}

@override
Future<Map<String, Object>> getAllWithParameters(
GetAllParameters parameters) async {
final PreferencesFilter filter = parameters.filter;
final Map<String, Object> preferences = Map<String, Object>.from(_data);
preferences.removeWhere((String key, _) => !key.startsWith(prefix));
preferences.removeWhere((String key, _) =>
!key.startsWith(filter.prefix) ||
(filter.allowList != null && !filter.allowList!.contains(key)));
return preferences;
}

Expand Down
Loading

0 comments on commit e073e55

Please sign in to comment.