Last active
April 9, 2020 22:02
-
-
Save ThinkDigitalSoftware/737e6007f496f581285367d2d6afd42e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:flutter/cupertino.dart'; | |
import 'package:flutter/foundation.dart'; | |
import 'package:fritter_for_reddit/exports.dart'; | |
import 'package:hive/hive.dart'; | |
/// Every time notifyListeners is called, the state is persisted to allow easy app persistence. | |
/// Persistence is based on Hive with a box opened with the class name. | |
/// If this is not desired, supply an alternative [boxName] in the constructor. | |
/// | |
/// Listeners are automatically notified whenever [state] changes. | |
abstract class StatePersistingChangeNotifier<T extends SerializableClass> | |
extends ChangeNotifier { | |
final Completer<bool> isInitializedCompleter = Completer(); | |
Future<bool> get initializationFuture => isInitializedCompleter.future; | |
Box _storage; | |
T _state; | |
T get state => _state; | |
set state(T state) { | |
_state = state; | |
writeState(state); | |
notifyListeners(); | |
} | |
StatePersistingChangeNotifier({String boxName}) { | |
_state = initialState; | |
Hive.openBox(boxName ?? runtimeType.toString()).then((box) { | |
_storage = box; | |
isInitializedCompleter.complete(true); | |
state = fromJson(_storage.get('state')) ?? initialState; | |
notifyListeners(); | |
}); | |
} | |
T fromJson(Map json); | |
@mustCallSuper | |
void writeState(T state) async { | |
await initializationFuture; | |
debugPrint('Writing state: $state'); | |
_storage.put('state', state.toJson()); | |
} | |
T get initialState; | |
} | |
abstract class SerializableClass<T> { | |
Map<String, dynamic> toJson(); | |
} | |
class SettingsNotifier extends StatePersistingChangeNotifier<SettingsState> { | |
@override | |
SettingsState get initialState => SettingsState.initial(); | |
static SettingsNotifier of(BuildContext context, {bool listen = false}) => | |
Provider.of<SettingsNotifier>(context, listen: listen); | |
void changeViewMode(ViewMode viewMode) => | |
state = state.copyWith(viewMode: viewMode); | |
@override | |
SettingsState fromJson(Map<dynamic, dynamic> json) { | |
return SettingsState.fromJson(json); | |
} | |
} | |
@immutable | |
class SettingsState extends SerializableClass { | |
final ViewMode viewMode; | |
SettingsState({@required this.viewMode}); | |
@override | |
String toString() { | |
return 'SettingsState{viewMode: $viewMode}'; | |
} | |
SettingsState.initial() : viewMode = ViewMode.card; | |
@override | |
factory SettingsState.fromJson(Map json) { | |
if (json == null) { | |
return SettingsState.initial(); | |
} | |
return SettingsState( | |
viewMode: viewModeFromString(json['viewMode']), | |
); | |
} | |
@override | |
Map<String, dynamic> toJson() => {'viewMode': viewMode.toString()}; | |
static ViewMode viewModeFromString(String viewModeString) { | |
switch (viewModeString) { | |
case 'ViewMode.card': | |
return ViewMode.card; | |
case 'ViewMode.gallery': | |
return ViewMode.gallery; | |
default: | |
{ | |
debugPrint( | |
'$viewModeString is not a supported ViewMode setting. Returning ViewMode.card'); | |
return ViewMode.card; | |
} | |
} | |
} | |
SettingsState copyWith({ | |
ViewMode viewMode, | |
}) => | |
SettingsState( | |
viewMode: viewMode ?? this.viewMode, | |
); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@loicgeek, yeah, I use
copyWith
as well.