feat(crud)!: make crudbuilder integration more easy by integrating blocbuilder (closes #181)
continuous-integration/drone/pr Build is failing

This commit is contained in:
2023-11-14 14:42:16 +01:00
parent 3a7b7dfd1d
commit 12568b3ada
4 changed files with 294 additions and 255 deletions
@@ -15,26 +15,27 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wyatt_crud_bloc/src/features/crud/blocs/crud_base_cubit/crud_base_cubit.dart';
/// {@template crud_builder}
/// A widget that builds itself based on the latest snapshot of interaction
/// with a [CrudBaseCubit].
///
/// * I = Initial State
/// * L = Loading State
/// * S = Success State
/// * E = Error State
/// {@endtemplate}
class CrudBuilder<I, L, S, E> extends StatelessWidget {
class CrudBuilder<
Bloc extends StateStreamable<CrudState>,
Initial extends CrudState,
Loading extends CrudState,
Success extends CrudState,
Error extends CrudState> extends StatelessWidget {
/// {@macro crud_builder}
const CrudBuilder({
required this.state,
required this.builder,
required this.initialBuilder,
required this.loadingBuilder,
required this.errorBuilder,
this.unknownBuilder,
this.buildWhen,
super.key,
});
@@ -43,50 +44,121 @@ class CrudBuilder<I, L, S, E> extends StatelessWidget {
/// This factory constructor is used to create a [CrudBuilder] with
/// [CrudState]s. `S` is the Success State, and it must be a subtype of
/// [CrudSuccess]. It the only type that you have to specify.
static CrudBuilder<CrudInitial, CrudLoading, CrudSuccess, CrudError>
typed<S extends CrudSuccess>({
required CrudState state,
required Widget Function(BuildContext, S) builder,
static CrudBuilder<Bloc, CrudInitial, CrudLoading, CrudSuccess, CrudError>
typed<Bloc extends StateStreamable<CrudState>,
Success extends CrudSuccess>({
required Widget Function(BuildContext, Success) builder,
required Widget Function(BuildContext, CrudInitial) initialBuilder,
required Widget Function(BuildContext, CrudLoading) loadingBuilder,
required Widget Function(BuildContext, CrudError) errorBuilder,
Widget Function(BuildContext, Object)? unknownBuilder,
Widget Function(BuildContext, CrudState)? unknownBuilder,
BlocBuilderCondition<CrudState>? buildWhen,
}) =>
CrudBuilder<CrudInitial, CrudLoading, S, CrudError>(
state: state,
CrudBuilder<Bloc, CrudInitial, CrudLoading, Success, CrudError>(
builder: builder,
initialBuilder: initialBuilder,
loadingBuilder: loadingBuilder,
errorBuilder: errorBuilder,
unknownBuilder: unknownBuilder,
buildWhen: buildWhen,
);
final Object state;
final Widget Function(BuildContext context, S state) builder;
final Widget Function(BuildContext context, I state) initialBuilder;
final Widget Function(BuildContext context, L state) loadingBuilder;
final Widget Function(BuildContext context, E state) errorBuilder;
final Widget Function(BuildContext context, Object state)? unknownBuilder;
/// {@macro crud_builder}
///
/// This factory constructor is used to create a [CrudBuilder] wich reacts
/// only to [CrudLoading] states.
static CrudBuilder<Bloc, CrudInitial, CrudLoading, CrudSuccess, CrudError>
onLoading<Bloc extends StateStreamable<CrudState>>({
required Widget? Function(BuildContext, CrudLoading) builder,
Widget Function(BuildContext, CrudState)? otherBuilder,
BlocBuilderCondition<CrudState>? buildWhen,
}) =>
CrudBuilder<Bloc, CrudInitial, CrudLoading, CrudSuccess, CrudError>(
loadingBuilder: (context, state) =>
builder.call(context, state) ??
otherBuilder?.call(context, state) ??
const SizedBox.shrink(),
builder: (context, state) =>
otherBuilder?.call(context, state) ?? const SizedBox.shrink(),
initialBuilder: (context, state) =>
otherBuilder?.call(context, state) ?? const SizedBox.shrink(),
errorBuilder: (context, state) =>
otherBuilder?.call(context, state) ?? const SizedBox.shrink(),
unknownBuilder: otherBuilder,
buildWhen: buildWhen,
);
/// {@macro crud_builder}
///
/// This factory constructor is used to create a [CrudBuilder] wich reacts
/// only to [CrudInitial] states.
static CrudBuilder<Bloc, CrudInitial, CrudLoading, CrudSuccess, CrudError>
onInitial<Bloc extends StateStreamable<CrudState>>({
required Widget? Function(BuildContext, CrudInitial) builder,
Widget Function(BuildContext, CrudState)? otherBuilder,
BlocBuilderCondition<CrudState>? buildWhen,
}) =>
CrudBuilder<Bloc, CrudInitial, CrudLoading, CrudSuccess, CrudError>(
initialBuilder: (context, state) =>
builder.call(context, state) ??
otherBuilder?.call(context, state) ??
const SizedBox.shrink(),
builder: (context, state) =>
otherBuilder?.call(context, state) ?? const SizedBox.shrink(),
loadingBuilder: (context, state) =>
otherBuilder?.call(context, state) ?? const SizedBox.shrink(),
errorBuilder: (context, state) =>
otherBuilder?.call(context, state) ?? const SizedBox.shrink(),
unknownBuilder: otherBuilder,
buildWhen: buildWhen,
);
/// {@macro crud_builder}
///
/// This factory constructor is used to create a [CrudBuilder] wich reacts
/// only to [CrudError] states.
static CrudBuilder<Bloc, CrudInitial, CrudLoading, CrudSuccess, CrudError>
onError<Bloc extends StateStreamable<CrudState>>({
required Widget? Function(BuildContext, CrudError) builder,
Widget Function(BuildContext, CrudState)? otherBuilder,
BlocBuilderCondition<CrudState>? buildWhen,
}) =>
CrudBuilder<Bloc, CrudInitial, CrudLoading, CrudSuccess, CrudError>(
errorBuilder: (context, state) =>
builder.call(context, state) ??
otherBuilder?.call(context, state) ??
const SizedBox.shrink(),
builder: (context, state) =>
otherBuilder?.call(context, state) ?? const SizedBox.shrink(),
loadingBuilder: (context, state) =>
otherBuilder?.call(context, state) ?? const SizedBox.shrink(),
initialBuilder: (context, state) =>
otherBuilder?.call(context, state) ?? const SizedBox.shrink(),
unknownBuilder: otherBuilder,
buildWhen: buildWhen,
);
final BlocBuilderCondition<CrudState>? buildWhen;
final Widget Function(BuildContext context, Success state) builder;
final Widget Function(BuildContext context, Initial state) initialBuilder;
final Widget Function(BuildContext context, Loading state) loadingBuilder;
final Widget Function(BuildContext context, Error state) errorBuilder;
final Widget Function(BuildContext context, CrudState state)? unknownBuilder;
@override
Widget build(BuildContext context) => Builder(
builder: (context) {
if (state is S) {
return builder(context, state as S);
} else if (state is E) {
return errorBuilder(context, state as E);
} else if (state is L) {
return loadingBuilder(context, state as L);
} else if (state is I) {
return initialBuilder(context, state as I);
} else {
return unknownBuilder?.call(context, state) ??
Center(
child: Text(
'Unknown state: $state',
),
);
}
Widget build(BuildContext context) => BlocBuilder<Bloc, CrudState>(
buildWhen: buildWhen,
builder: (context, state) => switch (state) {
Success() => builder(context, state),
Initial() => initialBuilder(context, state),
Loading() => loadingBuilder(context, state),
Error() => errorBuilder(context, state),
_ => unknownBuilder?.call(context, state) ??
Center(
child: Text(
'Unknown state: $state',
),
),
},
);
}