Browse Source

Merge pull request #527 from Leptopoda/fix/option_persistence

fix(neon): option serialization and reset
pull/530/head
Nikolas Rimikis 1 year ago committed by GitHub
parent
commit
ce3140c262
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      packages/neon/neon/lib/src/settings/models/option.dart
  2. 30
      packages/neon/neon/lib/src/settings/models/select_option.dart
  3. 3
      packages/neon/neon/lib/src/settings/models/storage.dart
  4. 10
      packages/neon/neon/lib/src/settings/models/toggle_option.dart
  5. 18
      packages/neon/neon/test/option_test.dart

4
packages/neon/neon/lib/src/settings/models/option.dart

@ -84,10 +84,10 @@ abstract class Option<T> extends ChangeNotifier implements ValueListenable<T> {
} }
/// Deserializes the data. /// Deserializes the data.
T deserialize(final Object data); T? deserialize(final Object? data);
/// Serializes the [value]. /// Serializes the [value].
Object serialize(); Object? serialize();
BehaviorSubject<T>? _stream; BehaviorSubject<T>? _stream;

30
packages/neon/neon/lib/src/settings/models/select_option.dart

@ -46,15 +46,14 @@ class SelectOption<T> extends Option<T> {
return stored as T; return stored as T;
} }
return _fromString(vs, stored); return _deserialize(vs, stored);
} }
static T? _fromString<T>(final Map<T, LabelBuilder> vs, final String? valueStr) { @override
if (valueStr == null) { void reset() {
return null; unawaited(storage.remove(key));
}
return vs.keys.firstWhereOrNull((final e) => e.toString() == valueStr); super.reset();
} }
Map<T, LabelBuilder> _values; Map<T, LabelBuilder> _values;
@ -62,7 +61,10 @@ class SelectOption<T> extends Option<T> {
@override @override
set value(final T value) { set value(final T value) {
super.value = value; super.value = value;
unawaited(storage.setString(key, serialize()));
if (value != null) {
unawaited(storage.setString(key, serialize()!));
}
} }
/// A collection of different values this can have. /// A collection of different values this can have.
@ -80,8 +82,18 @@ class SelectOption<T> extends Option<T> {
} }
@override @override
String serialize() => value.toString(); String? serialize() => _serialize(value);
static String? _serialize<T>(final T value) => value?.toString();
@override @override
T deserialize(final Object data) => _fromString(_values, data as String)!; T? deserialize(final Object? data) => _deserialize(_values, data as String?);
static T? _deserialize<T>(final Map<T, LabelBuilder> vs, final String? valueStr) {
if (valueStr == null) {
return null;
}
return vs.keys.firstWhereOrNull((final e) => _serialize(e) == valueStr);
}
} }

3
packages/neon/neon/lib/src/settings/models/storage.dart

@ -9,6 +9,8 @@ abstract interface class SettingsStorage {
// ignore: avoid_positional_boolean_parameters // ignore: avoid_positional_boolean_parameters
Future setBool(final String key, final bool value); Future setBool(final String key, final bool value);
Future<bool> remove(final String key);
} }
class AppStorage implements SettingsStorage { class AppStorage implements SettingsStorage {
@ -24,6 +26,7 @@ class AppStorage implements SettingsStorage {
bool containsKey(final String key) => _sharedPreferences.containsKey(_formatKey(key)); bool containsKey(final String key) => _sharedPreferences.containsKey(_formatKey(key));
@override
Future<bool> remove(final String key) => _sharedPreferences.remove(_formatKey(key)); Future<bool> remove(final String key) => _sharedPreferences.remove(_formatKey(key));
@override @override

10
packages/neon/neon/lib/src/settings/models/toggle_option.dart

@ -25,9 +25,17 @@ class ToggleOption extends Option<bool> {
defaultValue: storage.getBool(key) ?? defaultValue, defaultValue: storage.getBool(key) ?? defaultValue,
); );
@override
void reset() {
unawaited(storage.remove(key));
super.reset();
}
@override @override
set value(final bool value) { set value(final bool value) {
super.value = value; super.value = value;
unawaited(storage.setBool(key, serialize())); unawaited(storage.setBool(key, serialize()));
} }
@ -35,5 +43,5 @@ class ToggleOption extends Option<bool> {
bool serialize() => value; bool serialize() => value;
@override @override
bool deserialize(final Object data) => data as bool; bool? deserialize(final Object? data) => data as bool?;
} }

18
packages/neon/neon/test/option_test.dart

@ -37,6 +37,8 @@ void main() {
setUp(() { setUp(() {
when(() => storage.setString(key, any())).thenAnswer((final _) async {}); when(() => storage.setString(key, any())).thenAnswer((final _) async {});
when(() => storage.remove(key)).thenAnswer((final _) async => true);
option = SelectOption<SelectValues>( option = SelectOption<SelectValues>(
storage: storage, storage: storage,
key: key, key: key,
@ -148,8 +150,21 @@ void main() {
option.reset(); option.reset();
verify(callback.call).called(1); verify(callback.call).called(1);
verify(() => storage.remove(key)).called(1);
expect(option.value, option.defaultValue, reason: 'Should reset the value.'); expect(option.value, option.defaultValue, reason: 'Should reset the value.');
}); });
test('Serialize null', () {
final option = SelectOption<SelectValues?>(
storage: storage,
key: key,
label: labelBuilder,
defaultValue: null,
values: valuesLabel,
);
expect(option.serialize(), null, reason: 'Should serialize to null. A string containing "null" is an error');
});
}); });
group('ToggleOption', () { group('ToggleOption', () {
@ -157,6 +172,8 @@ void main() {
setUp(() { setUp(() {
when(() => storage.setBool(key, any())).thenAnswer((final _) async {}); when(() => storage.setBool(key, any())).thenAnswer((final _) async {});
when(() => storage.remove(key)).thenAnswer((final _) async => true);
option = ToggleOption( option = ToggleOption(
storage: storage, storage: storage,
key: key, key: key,
@ -245,6 +262,7 @@ void main() {
option.reset(); option.reset();
verify(callback.call).called(1); verify(callback.call).called(1);
verify(() => storage.remove(key)).called(1);
expect(option.value, option.defaultValue, reason: 'Should reset the value.'); expect(option.value, option.defaultValue, reason: 'Should reset the value.');
}); });
}); });

Loading…
Cancel
Save