replay_bloc 0.2.7 copy "replay_bloc: ^0.2.7" to clipboard
replay_bloc: ^0.2.7 copied to clipboard

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

example/lib/main.dart

// ignore_for_file: avoid_print

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:replay_bloc/replay_bloc.dart';

void main() {
  Bloc.observer = const AppBlocObserver();
  runApp(const App());
}

/// {@template app_bloc_observer}
/// Custom [BlocObserver] that observes all bloc and cubit state changes.
/// {@endtemplate}
class AppBlocObserver extends BlocObserver {
  /// {@macro app_bloc_observer}
  const AppBlocObserver();

  @override
  void onChange(BlocBase<dynamic> bloc, Change<dynamic> change) {
    super.onChange(bloc, change);
    if (bloc is Cubit) print(change);
  }

  @override
  void onTransition(
    Bloc<dynamic, dynamic> bloc,
    Transition<dynamic, dynamic> transition,
  ) {
    super.onTransition(bloc, transition);
    print(transition);
  }
}

/// {@template app}
/// A [StatelessWidget] that:
/// * uses [replay_bloc](https://pub.dev/packages/replay_bloc)
/// and [flutter_bloc](https://pub.dev/packages/flutter_bloc)
/// to manage the state of a counter.
/// {@endtemplate}
class App extends StatelessWidget {
  /// {@macro app}
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (_) => CounterBloc(),
      child: const MaterialApp(
        home: CounterPage(),
      ),
    );
  }
}

/// {@template counter_page}
/// A [StatelessWidget] that:
/// * demonstrates how to consume and interact with a [ReplayBloc]/[ReplayCubit].
/// {@endtemplate}
class CounterPage extends StatelessWidget {
  /// {@macro counter_page}
  const CounterPage({super.key});

  @override
  Widget build(BuildContext context) {
    final textTheme = Theme.of(context).textTheme;
    return Scaffold(
      appBar: AppBar(
        title: const Text('Counter'),
        actions: [
          BlocBuilder<CounterBloc, int>(
            builder: (context, state) {
              final bloc = context.read<CounterBloc>();
              return IconButton(
                icon: const Icon(Icons.undo),
                onPressed: bloc.canUndo ? bloc.undo : null,
              );
            },
          ),
          BlocBuilder<CounterBloc, int>(
            builder: (context, state) {
              final bloc = context.read<CounterBloc>();
              return IconButton(
                icon: const Icon(Icons.redo),
                onPressed: bloc.canRedo ? bloc.redo : null,
              );
            },
          ),
        ],
      ),
      body: Center(
        child: BlocBuilder<CounterBloc, int>(
          builder: (context, state) {
            return Text('$state', style: textTheme.displayMedium);
          },
        ),
      ),
      floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            child: const Icon(Icons.add),
            onPressed: () {
              context.read<CounterBloc>().add(CounterIncrementPressed());
            },
          ),
          const SizedBox(height: 4),
          FloatingActionButton(
            child: const Icon(Icons.remove),
            onPressed: () {
              context.read<CounterBloc>().add(CounterDecrementPressed());
            },
          ),
          const SizedBox(height: 4),
          FloatingActionButton(
            child: const Icon(Icons.delete_forever),
            onPressed: () {
              context.read<CounterBloc>().add(CounterResetPressed());
            },
          ),
        ],
      ),
    );
  }
}

/// Base event class for the [CounterBloc].
sealed class CounterEvent extends ReplayEvent {}

/// Notifies [CounterBloc] to increment its state.
final class CounterIncrementPressed extends CounterEvent {
  @override
  String toString() => 'CounterIncrementPressed';
}

/// Notifies [CounterBloc] to decrement its state.
final class CounterDecrementPressed extends CounterEvent {
  @override
  String toString() => 'CounterDecrementPressed';
}

/// Notifies [CounterBloc] to reset its state.
final class CounterResetPressed extends CounterEvent {
  @override
  String toString() => 'CounterResetPressed';
}

/// {@template replay_counter_bloc}
/// A simple [ReplayBloc] which manages an `int` as its state
/// and reacts to three events:
/// * [CounterIncrementPressed]
/// * [CounterDecrementPressed]
/// * [CounterResetPressed]
/// {@endtemplate}
class CounterBloc extends ReplayBloc<CounterEvent, int> {
  /// {@macro replay_counter_bloc}
  CounterBloc() : super(0) {
    on<CounterIncrementPressed>((event, emit) => emit(state + 1));
    on<CounterDecrementPressed>((event, emit) => emit(state - 1));
    on<CounterResetPressed>((event, emit) => emit(0));
  }
}
173
likes
160
points
12k
downloads
screenshot

Publisher

verified publisherbloclibrary.dev

Weekly Downloads

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

Homepage
Repository (GitHub)
View/report issues
Contributing

Topics

#bloc #state-management

Documentation

API reference

License

MIT (license)

Dependencies

bloc

More

Packages that depend on replay_bloc