Last active
August 19, 2021 09:34
-
-
Save zs-dima/009139aa960612e036287d1147aed19c to your computer and use it in GitHub Desktop.
StateBuilder to discuss
This file contains 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
typedef StateBuilderCondition<State extends Object> = bool Function(State state); | |
typedef StateBuilderConverter<State extends Object, Result extends Object?> = Result Function(State state); | |
typedef StateBuilderBuilder<Result extends Object?> = Widget Function(BuildContext context, Result result); | |
typedef StateBuilderOnWaiting = Widget Function(BuildContext context); | |
typedef StateBuilderOnError = Widget Function(BuildContext context, Object? error); | |
class StateBuilder { | |
@factory | |
static _StateBuilder<State> where<State extends Object>({ | |
Key? key, | |
State? initialData, | |
required IStateObservable bloc, | |
StateBuilderCondition<State>? buildWhen, | |
required StateBuilderBuilder<State> builder, | |
StateBuilderOnWaiting? onWaiting, | |
StateBuilderOnError? onError, | |
bool animate = true, | |
}) => | |
_StateBuilder<State>( | |
key: key, | |
initialData: initialData, | |
bloc: bloc.whereState<State>(), | |
buildWhen: buildWhen, | |
builder: builder, | |
onError: onError, | |
onWaiting: onWaiting, | |
animate: animate, | |
); | |
@factory | |
static _StateBuilderConvert<State, Result> whereConvert<State extends Object, Result extends Object?>({ | |
Key? key, | |
Result? initialData, | |
required IStateObservable bloc, | |
StateBuilderCondition<State>? buildWhen, | |
required StateBuilderConverter<State, Result> convert, | |
required StateBuilderBuilder<Result> builder, | |
StateBuilderOnWaiting? onWaiting, | |
StateBuilderOnError? onError, | |
bool animate = true, | |
}) => | |
_StateBuilderConvert<State, Result>( | |
key: key, | |
initialData: initialData, | |
bloc: bloc.whereState<State>(), | |
buildWhen: buildWhen, | |
convert: convert, | |
builder: builder, | |
onError: onError, | |
onWaiting: onWaiting, | |
animate: animate, | |
); | |
} | |
class _StateBuilderConvert<State extends Object, Result extends Object?> extends StatelessWidget { | |
final bool animate; | |
final Result? initialData; | |
final StateObservable<State> bloc; | |
final StateBuilderCondition<State>? buildWhen; | |
final StateBuilderConverter<State, Result> convert; | |
final StateBuilderBuilder<Result> builder; | |
final StateBuilderOnWaiting? onWaiting; | |
final StateBuilderOnError? onError; | |
const _StateBuilderConvert({ | |
Key? key, | |
this.initialData, | |
required this.bloc, | |
required this.builder, | |
this.buildWhen, | |
required this.convert, | |
this.onWaiting, | |
this.onError, | |
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)); | |
return StreamBuilder( | |
initialData: bloc.state is State ? convert(bloc.state) : initialData, | |
stream: stream.map(convert).distinct(), | |
builder: (context, AsyncSnapshot<Result> snapshot) { | |
Widget result; | |
if (snapshot.hasError) { | |
result = onError != null // | |
? onError!(context, snapshot.error) | |
: (context.tryRead<DefaultBlocErrorWidget>() ?? const SizedBox.shrink()); | |
} else if (snapshot.hasData) { | |
final Result data = snapshot.data as Result; | |
result = builder(context, data); | |
} else { | |
result = onWaiting != null // | |
? onWaiting!(context) | |
: (context.tryRead<DefaultBlocWaitingWidget>() ?? const SizedBox.shrink()); | |
} | |
if (animate) return AnimatedSwitcher(duration: const Duration(milliseconds: 500), child: result); | |
return result; | |
}, | |
); | |
} | |
} | |
class _StateBuilder<State extends Object> extends StatelessWidget { | |
final bool animate; | |
final State? initialData; | |
final StateObservable<State> bloc; | |
final StateBuilderCondition<State>? buildWhen; | |
final StateBuilderBuilder<State> builder; | |
final StateBuilderOnWaiting? onWaiting; | |
final StateBuilderOnError? onError; | |
const _StateBuilder({ | |
Key? key, | |
this.initialData, | |
required this.bloc, | |
required this.builder, | |
this.buildWhen, | |
this.onWaiting, | |
this.onError, | |
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)); | |
return StreamBuilder( | |
initialData: bloc.state is State ? bloc.state : initialData, | |
stream: stream.distinct(), | |
builder: (context, AsyncSnapshot<State> snapshot) { | |
Widget result; | |
if (snapshot.hasError) { | |
result = onError != null // | |
? onError!(context, snapshot.error) | |
: (context.tryRead<DefaultBlocErrorWidget>() ?? const SizedBox.shrink()); | |
} else if (snapshot.hasData) { | |
final State data = snapshot.data as State; | |
result = builder(context, data); | |
} else { | |
result = onWaiting != null // | |
? onWaiting!(context) | |
: (context.tryRead<DefaultBlocWaitingWidget>() ?? const SizedBox.shrink()); | |
} | |
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