buildBlocBuilder method

  1. @protected
Widget buildBlocBuilder(
  1. BuildParameters params
)

Implementation

@protected
Widget buildBlocBuilder(BuildParameters params) {
  final children = params.widgets["states"] as List<Map>?;
  if (children == null || children.isEmpty) {
    return const SizedBox();
  }

  final log = Logger("BlocBuilder");
  final stateActions = <String>[];
  final stateWidgets = <String>[];
  final actionMap = <String, Map?>{};
  final widgetMap = <String, Map?>{};
  for (var child in children) {
    final childProps = child["properties"] as Map? ?? {};
    final state = childProps["state"] as String? ?? "";

    if (state.isNotEmpty) {
      stateActions.add(state);
      final childActions = child["actions"] as Map? ?? {};
      actionMap[state] = childActions["listener"] as Map?;

      if (child["_type"] != "StateListener") {
        stateWidgets.add(state);
        final childWidgets = child["widgets"] as Map? ?? {};
        widgetMap[state] = childWidgets["child"] as Map?;
      }
    }
  }

  final parentContext = params.parentContext ?? {};
  final type = params.props["type"] ?? "local";
  final defaultWidgetSpec = params.widgets["child"] as Map?;

  listenWhen(BaseState prev, BaseState next) =>
      prev != next &&
      next is ActionState &&
      stateActions.contains(next.state);
  buildWhen(BaseState prev, BaseState next) =>
      prev != next &&
      next is ActionState &&
      stateWidgets.contains(next.state);

  listener(BuildContext context, BaseState state) {
    if (state is! ActionState) {
      return;
    }

    final actionSpec = actionMap[state.state];
    if (actionSpec == null) {
      return;
    }

    final stateContext = parentContext.clone();
    stateContext.addAll({"stateData": state.data});

    final func = events.getFunction(
        context, actionSpec.clone(), params.state, stateContext);
    if (func != null) {
      log.info(
          "Executing '${actionSpec["name"] ?? actionSpec["_type"]}' from state '${state.state}'");
      func();
    }
  }

  stateBuilder(BuildContext context, BaseState state) {
    Map? widgetSpec;
    if (state is ActionState) {
      widgetSpec = widgetMap[state.state];
    }
    widgetSpec ??= defaultWidgetSpec;
    if (widgetSpec == null) return const SizedBox();

    final stateContext = parentContext.clone();
    if (state is ActionState) {
      stateContext.addAll({"stateData": state.data});
      log.info(
          "Building '${widgetSpec["name"] ?? widgetSpec["_type"]}' from state '${state.state}'");
    }
    params.state.remove(widgetSpec["_id"]);

    // Returning a dummy Builder with an unique key to force a repaint.
    return Builder(
      key: UniqueKey(),
      builder: (context) => builder.buildWidget(
          context, widgetSpec!.clone(), params.state, stateContext),
    );
  }

  return type == "global"
      ? BlocConsumer<GlobalBloc, BaseState>(
          listenWhen: listenWhen,
          listener: listener,
          buildWhen: buildWhen,
          builder: stateBuilder)
      : BlocConsumer<LocalBloc, BaseState>(
          listenWhen: listenWhen,
          listener: listener,
          buildWhen: buildWhen,
          builder: stateBuilder);
}