Skip to content

Instantly share code, notes, and snippets.

@zs-dima
Last active August 18, 2021 18:07
Show Gist options
  • Save zs-dima/752b03105c66bb07b7ebaedd576fb3cd to your computer and use it in GitHub Desktop.
Save zs-dima/752b03105c66bb07b7ebaedd576fb3cd to your computer and use it in GitHub Desktop.
BlocBuilder to discuss
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
typedef BlocBuilderCondition<State extends Object> = bool Function(State state);
typedef BlocBuilderConverter<State extends Object, Result extends Object?> = Result Function(State state);
typedef BlocBuilderBuilder<Result extends Object?> = Widget Function(BuildContext context, Result result);
class BlocBuilder<State extends Object, Result extends Object> extends StatelessWidget {
final bool animate;
final IStateObservable<State> bloc;
final BlocBuilderCondition<State>? buildWhen;
final BlocBuilderConverter<State, Result>? convert;
final BlocBuilderBuilder<Result> builder;
final Widget Function(BuildContext context, String error) onError;
final Widget Function(BuildContext context) onWaiting;
const BlocBuilder({
Key? key,
required this.bloc,
required this.builder,
this.buildWhen,
this.convert,
required this.onError,
required this.onWaiting,
this.animate = true,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final Stream<State> stream = buildWhen == null //
? bloc.stream
: bloc.stream.where((state) => buildWhen!(state));
final Stream<Result> resultStream = convert == null //
? stream.map((state) => state as Result)
: stream.map((state) => convert!(state));
final Result? state = convert == null //
? (bloc.state is Result ? bloc.state as Result : null)
: convert!(bloc.state);
return StreamBuilder(
initialData: state,
stream: resultStream.distinct(),
builder: (context, AsyncSnapshot<Result> snapshot) {
Widget result;
if (snapshot.hasError) {
result = onError(context, snapshot.error);
} else if (snapshot.hasData) {
Result data = snapshot.data!;
result = builder(context, data);
} else {
result = onWaiting(context);
}
if (animate) return AnimatedSwitcher(duration: const Duration(milliseconds: 500), child: result);
return result;
},
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment