networkImageRender function

CustomRender networkImageRender({
  1. Map<String, String>? headers,
  2. String mapUrl(
    1. String?
    )?,
  3. double? width,
  4. double? height,
  5. Widget altWidget(
    1. String?
    )?,
  6. Widget loadingWidget()?,
})

Implementation

CustomRender networkImageRender({
  Map<String, String>? headers,
  String Function(String?)? mapUrl,
  double? width,
  double? height,
  Widget Function(String?)? altWidget,
  Widget Function()? loadingWidget,
}) =>
    CustomRender.widget(widget: (context, buildChildren) {
      final src = mapUrl?.call(_src(context.tree.element!.attributes.cast())) ??
          _src(context.tree.element!.attributes.cast())!;
      Completer<Size> completer = Completer();
      if (context.parser.cachedImageSizes[src] != null) {
        completer.complete(context.parser.cachedImageSizes[src]);
      } else {
        Image image = Image.network(src, frameBuilder: (ctx, child, frame, _) {
          if (frame == null) {
            if (!completer.isCompleted) {
              completer.completeError("error");
            }
            return child;
          } else {
            return child;
          }
        });

        ImageStreamListener? listener;
        listener =
            ImageStreamListener((ImageInfo imageInfo, bool synchronousCall) {
          var myImage = imageInfo.image;
          Size size = Size(myImage.width.toDouble(), myImage.height.toDouble());
          if (!completer.isCompleted) {
            context.parser.cachedImageSizes[src] = size;
            completer.complete(size);
            image.image.resolve(const ImageConfiguration()).removeListener(listener!);
          }
        }, onError: (object, stacktrace) {
          if (!completer.isCompleted) {
            completer.completeError(object);
            image.image.resolve(const ImageConfiguration()).removeListener(listener!);
          }
        });

        image.image.resolve(const ImageConfiguration()).addListener(listener);
      }
      final attributes =
          context.tree.element!.attributes.cast<String, String>();
      final widget = FutureBuilder<Size>(
        future: completer.future,
        initialData: context.parser.cachedImageSizes[src],
        builder: (BuildContext buildContext, AsyncSnapshot<Size> snapshot) {
          if (snapshot.hasData) {
            return Container(
              constraints: BoxConstraints(
                  maxWidth: width ?? _width(attributes) ?? snapshot.data!.width,
                  maxHeight:
                      (width ?? _width(attributes) ?? snapshot.data!.width) /
                          _aspectRatio(attributes, snapshot)),
              child: AspectRatio(
                aspectRatio: _aspectRatio(attributes, snapshot),
                child: Image.network(
                  src,
                  headers: headers,
                  width: width ?? _width(attributes) ?? snapshot.data!.width,
                  height: height ?? _height(attributes),
                  frameBuilder: (ctx, child, frame, _) {
                    if (frame == null) {
                      return altWidget?.call(_alt(attributes)) ??
                          Text(_alt(attributes) ?? "",
                              style: context.style.generateTextStyle());
                    }
                    return child;
                  },
                ),
              ),
            );
          } else if (snapshot.hasError) {
            return altWidget
                    ?.call(_alt(context.tree.element!.attributes.cast())) ??
                Text(_alt(context.tree.element!.attributes.cast()) ?? "",
                    style: context.style.generateTextStyle());
          } else {
            return loadingWidget?.call() ?? const CircularProgressIndicator();
          }
        },
      );
      return Builder(
          key: context.key,
          builder: (buildContext) {
            return GestureDetector(
              child: widget,
              onTap: () {
                if (MultipleTapGestureDetector.of(buildContext) != null) {
                  MultipleTapGestureDetector.of(buildContext)!.onTap?.call();
                }
                context.parser.onImageTap?.call(
                    src,
                    context,
                    context.tree.element!.attributes.cast(),
                    context.tree.element);
              },
            );
          });
    });