packages/replay_bloc/README.md
An extension to package:bloc which adds automatic undo and redo support to bloc and cubit states. Built to work with package:bloc.
Learn more at bloclibrary.dev!
Our top sponsors are shown below! [Become a Sponsor]
<table style="background-color: white; border: 1px solid black"> <tbody> <tr> <td align="center" style="border: 1px solid black"> <a href="https://shorebird.dev"></a> </td> <td align="center" style="border: 1px solid black"> <a href="https://getstream.io/chat/flutter/tutorial/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_FlutterChat&utm_term=bloc"></a> </td> <td align="center" style="border: 1px solid black"> <a href="https://rettelgame.com/"></a> </td> </tr> </tbody> </table>class CounterCubit extends ReplayCubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
}
void main() {
final cubit = CounterCubit();
// trigger a state change
cubit.increment();
print(cubit.state); // 1
// undo the change
cubit.undo();
print(cubit.state); // 0
// redo the change
cubit.redo();
print(cubit.state); // 1
}
If you wish to be able to use a ReplayCubit in conjuction with a different type of cubit like HydratedCubit, you can use the ReplayCubitMixin.
class CounterCubit extends HydratedCubit<int> with ReplayCubitMixin {
CounterCubit() : super(0);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
@override
int fromJson(Map<String, dynamic> json) => json['value'] as int;
@override
Map<String, int> toJson(int state) => {'value': state};
}
class CounterEvent extends ReplayEvent {}
class CounterIncrementPressed extends CounterEvent {}
class CounterDecrementPressed extends CounterEvent {}
class CounterBloc extends ReplayBloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<CounterIncrementPressed>((event, emit) => emit(state + 1));
on<CounterDecrementPressed>((event, emit) => emit(state - 1));
}
}
void main() {
// trigger a state change
final bloc = CounterBloc()..add(CounterIncrementPressed());
// wait for state to update
await bloc.stream.first;
print(bloc.state); // 1
// undo the change
bloc.undo();
print(bloc.state); // 0
// redo the change
bloc.redo();
print(bloc.state); // 1
}
If you wish to be able to use a ReplayBloc in conjuction with a different type of cubit like HydratedBloc, you can use the ReplayBlocMixin.
sealed class CounterEvent with ReplayEvent {}
final class CounterIncrementPressed extends CounterEvent {}
final class CounterDecrementPressed extends CounterEvent {}
class CounterBloc extends HydratedBloc<CounterEvent, int> with ReplayBlocMixin {
CounterBloc() : super(0) {
on<CounterIncrementPressed>((event, emit) => emit(state + 1));
on<CounterDecrementPressed>((event, emit) => emit(state - 1));
}
@override
int fromJson(Map<String, dynamic> json) => json['value'] as int;
@override
Map<String, int> toJson(int state) => {'value': state};
}