replay_bloc 0.3.0

SDKdartflutter
Platformandroidioswindowslinuxmacosweb

An extension to the bloc state management library which adds support for undo and redo.

ReplayBloc

Pub build codecov Star on Github Flutter Website Awesome Flutter Flutter Samples License: MIT Discord Bloc Library

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!


Sponsors

Our top sponsors are shown below! [Become a Sponsor]


Creating a ReplayCubit

class CounterCubit extends ReplayCubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);
}

Using a ReplayCubit

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
}

ReplayCubitMixin

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};
}

Creating a ReplayBloc

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));
  }
}

Using a ReplayBloc

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
}

ReplayBlocMixin

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};
}

Dart Versions

  • Dart 2: >= 2.14

Maintainers