mainWidget method

Widget mainWidget()

Implementation

Widget mainWidget() {
  final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
  TextStyle? effectiveTextStyle = widget.textCustomization?.style;
  if (widget.textCustomization?.style == null ||
      (widget.textCustomization?.style?.inherit ?? false)) {
    effectiveTextStyle =
        defaultTextStyle.style.merge(widget.textCustomization?.style);
  }
  final defaultLessStyle = widget.features.readMore.decoration.lessStyle;
  final defaultMoreStyle = widget.features.readMore.decoration.moreStyle;

  final textAlign = widget.textCustomization?.textAlign ??
      defaultTextStyle.textAlign ??
      TextAlign.start;
  final textDirection =
      widget.textCustomization?.textDirection ?? Directionality.of(context);
  final textScaleFactor = widget.textCustomization?.textScaleFactor ??
      MediaQuery.textScaleFactorOf(context);
  final overflow = defaultTextStyle.overflow;
  final locale = widget.textCustomization?.locale ??
      Localizations.maybeLocaleOf(context);

  final TextSpan link = TextSpan(
    text: _readMoreStatus
        ? widget.features.readMore.collapsedText
        : widget.features.readMore.expandedText,
    style: _readMoreStatus ? defaultMoreStyle : defaultLessStyle,
    recognizer: TapGestureRecognizer()..onTap = _onTapLink,
  );

  return LayoutBuilder(
    builder: (BuildContext context, BoxConstraints constraints) {
      assert(constraints.hasBoundedWidth);
      final double maxWidth = constraints.maxWidth;

      // Create a TextSpan with data
      final TextSpan text = widget.features.hyperlink.enable
          ? buildTextSpan(
              linkify(widget.text ?? ""),
              style: widget.textCustomization?.style,
              onOpen: (link) => widget.features.hyperlink.onTap != null
                  ? widget.features.hyperlink.onTap!(context, link.url)
                  : onTapHyperLink(context, link),
              linkStyle: widget.features.hyperlink.style,
            )
          : TextSpan(
              style: effectiveTextStyle,
              text: widget.text,
            );

      // Layout and measure link
      TextPainter textPainter = TextPainter(
        text: link,
        textAlign: textAlign,
        textDirection: textDirection,
        textScaleFactor: textScaleFactor,
        maxLines: 2,
        ellipsis: overflow == TextOverflow.ellipsis ? kEllipsis : null,
        locale: locale,
      );

      textPainter.layout(minWidth: 0, maxWidth: maxWidth);

      // Layout and measure text
      textPainter.text = text;
      textPainter.layout(minWidth: constraints.minWidth, maxWidth: maxWidth);

      TextSpan? textSpan;

      if (widget.features.readMore.enable) {
        switch (widget.features.readMore.trim.mode) {
          case TrimMode.length:
            if (widget.features.readMore.trim.length < widget.text!.length) {
              if (widget.features.hyperlink.enable) {
                bool broke = false;
                int totalCharacterCount = 0;
                List<InlineSpan> textChildren = (text.children ?? []);
                List<InlineSpan> shortTextSpanChildren = <InlineSpan>[];
                for (int textChildrenIndex = 0;
                    textChildrenIndex < textChildren.length;
                    textChildrenIndex++) {
                  final TextSpan textSpan =
                      (textChildren[textChildrenIndex] as TextSpan);
                  final String textSpanText = (textSpan.text ?? "");
                  int localCharacterIndex = 0;
                  for (int textCharacterIndex = 0;
                      textCharacterIndex < textSpanText.length;
                      textCharacterIndex++) {
                    localCharacterIndex++;
                    totalCharacterCount++;

                    if (totalCharacterCount >
                        widget.features.readMore.trim.length) {
                      TextSpan temp1 =
                          textChildren[textChildrenIndex] as TextSpan;
                      TextSpan temp2 = TextSpan(
                        children: temp1.children,
                        locale: temp1.locale,
                        mouseCursor: temp1.mouseCursor,
                        onEnter: temp1.onEnter,
                        onExit: temp1.onExit,
                        recognizer: temp1.recognizer,
                        semanticsLabel: temp1.semanticsLabel,
                        spellOut: temp1.spellOut,
                        style: temp1.style,
                        text: temp1.text?.substring(0, localCharacterIndex),
                      );

                      for (int i = 0; i < textChildrenIndex; i++) {
                        shortTextSpanChildren
                            .add(textChildren[i] as TextSpan);
                      }
                      shortTextSpanChildren.add(temp2);
                      broke = true;
                      break;
                    }
                  }
                  if (broke) {
                    break;
                  }
                }

                final List<InlineSpan> finalTextSpan = _readMoreStatus
                    ? shortTextSpanChildren
                    : (text.children ?? <InlineSpan>[]);

                textSpan = TextSpan(
                  children: [...finalTextSpan, link],
                  locale: text.locale,
                  mouseCursor: text.mouseCursor,
                  recognizer: text.recognizer,
                  onEnter: text.onEnter,
                  onExit: text.onExit,
                  semanticsLabel: text.semanticsLabel,
                  spellOut: text.spellOut,
                  style: effectiveTextStyle,
                  text: _readMoreStatus
                      ? text.text
                          ?.substring(0, widget.features.readMore.trim.length)
                      : text.text,
                );
              } else {
                textSpan = TextSpan(
                  style: effectiveTextStyle,
                  text: _readMoreStatus
                      ? widget.text
                          ?.substring(0, widget.features.readMore.trim.length)
                      : widget.text,
                  children: <TextSpan>[link],
                );
              }
            } else {
              if (widget.features.hyperlink.enable) {
                textSpan = TextSpan(
                  children: text.children,
                  locale: text.locale,
                  mouseCursor: text.mouseCursor,
                  recognizer: text.recognizer,
                  onEnter: text.onEnter,
                  onExit: text.onExit,
                  semanticsLabel: text.semanticsLabel,
                  spellOut: text.spellOut,
                  style: effectiveTextStyle,
                  text: text.text,
                );
              } else {
                textSpan = TextSpan(
                  style: effectiveTextStyle,
                  text: widget.text,
                );
              }
            }
            break;
          default:
            throw Exception(
                'TrimMode type: ${widget.features.readMore.trim.mode} is not supported');
        }
      } else {
        if (widget.features.hyperlink.enable) {
          textSpan = TextSpan(
            children: text.children,
            locale: text.locale,
            mouseCursor: text.mouseCursor,
            recognizer: text.recognizer,
            onEnter: text.onEnter,
            onExit: text.onExit,
            semanticsLabel: text.semanticsLabel,
            spellOut: text.spellOut,
            style: effectiveTextStyle,
            text: text.text,
          );
        } else {
          textSpan = TextSpan(
            style: effectiveTextStyle,
            text: widget.text,
          );
        }
      }

      return RichText(
        textAlign: textAlign,
        textDirection: textDirection,
        softWrap: true,
        overflow: TextOverflow.clip,
        textScaleFactor: textScaleFactor,
        text: textSpan,
      );
    },
  );
}