nudgeSpotlight function

void nudgeSpotlight(
  1. BuildContext context,
  2. Root rootData,
  3. String eventName
)

Implementation

void nudgeSpotlight(
  BuildContext context,
  Root rootData,
  String eventName,
) async {
  OverlayEntry? overlayForegroundEntry;
  OverlayEntry? overlayBackgroundEntry;

  Nudge.getInstance().submit(
    taskId: NudgeNudgesUi.taskID!,
    response: [
      {
        "root_id": rootData.id,
        "widget_id": rootData.components[NudgeNudgesUi.currentNudgeIndex].id,
        // "component_id": rootData.components[NudgeNudgesUi.currentNudgeIndex].id,
        "widget_type": null,
        "answers": [],
        "action": "OPENED",
      }
    ],
    onSuccessCallback: (response) {
      print("Spotlight Opened, $response");
    },
    onErrorCallback: (error, stackTrace) {
      print("Error: $error");
    },
  );

  NudgeNudgesUi.componentName = rootData
          .components[NudgeNudgesUi.currentNudgeIndex]
          .componentProps
          .elementId ??
      "";

  print('Component Name: ${NudgeNudgesUi.componentName}');

  // return;

  String? referenceSize = rootData.rootProps.size;

  Size referenceDimensions = Size(
    int.parse(referenceSize.split('x')[0]).toDouble(),
    int.parse(referenceSize.split('x')[1]).toDouble(),
  );

  int referenceHeight = referenceDimensions.height.toInt();
  int referenceWidth = referenceDimensions.width.toInt();

  Size screenSize = MediaQuery.of(context).size;
  double screenHeight = screenSize.height;
  double screenWidth = screenSize.width;

  double scaleHeight = screenHeight / referenceHeight;
  double scaleWidth = screenWidth / referenceWidth;

  Color fillColor = HexColor.fromHex(
    rootData.components[NudgeNudgesUi.currentNudgeIndex].componentProps
            .overlayColor ??
        "#000000",
  );

  overlayBackgroundEntry = OverlayEntry(builder: (context) {
    return Positioned(
      height: MediaQuery.of(context).size.height,
      width: MediaQuery.of(context).size.width,
      child: GestureDetector(
        onTap: () {
          // overlayBackgroundEntry!.remove();
          // overlayForegroundEntry!.remove();
        },
        child: Container(
          color: fillColor.withOpacity(0),
        ),
      ),
    );
  });

  NudgeProviderState.navigatorKey.currentState!.overlay!.insert(
    overlayBackgroundEntry,
  );

  // NudgeNudgesUi.componentName = rootData
  //         .components[NudgeNudgesUi.currentNudgeIndex]
  //         .componentProps
  //         .elementProps!
  //         .name ??
  //     "";

  WidgetDetails? targetView = NudgeWidgetTracker.findWidgetPositionByLabel(
    NudgeNudgesUi.componentName,
    scaleWidth,
    scaleHeight,
  );

  bool isPositionBased = rootData.components[NudgeNudgesUi.currentNudgeIndex]
          .componentProps.isPositionBased ??
      false;

  if (targetView == null && !isPositionBased) {
    overlayBackgroundEntry.remove();
  }

  final NudgeNudgesUi nudgeNudgesUi = NudgeNudgesUi();

  nudgeNudgesUi
      .scrollToTargetWidget(
        targetView?.key,
        isPositionBased: isPositionBased,
      )
      .then(
        (value) => Future.delayed(
          const Duration(milliseconds: 1),
        ),
      )
      .then((value) {
    WidgetDetails? targetViewMain =
        NudgeWidgetTracker.findWidgetPositionByLabel(
      NudgeNudgesUi.componentName,
      scaleWidth,
      scaleHeight,
    );

    if (isPositionBased) {
      // logger.e("Position Based");
      NudgeNudgesUi.componentY = rootData
              .components[NudgeNudgesUi.currentNudgeIndex]
              .componentProps
              .elementProps!
              .y
              .roundToDouble() *
          scaleHeight;
      NudgeNudgesUi.componentX = rootData
              .components[NudgeNudgesUi.currentNudgeIndex]
              .componentProps
              .elementProps!
              .x
              .roundToDouble() *
          scaleWidth;
      NudgeNudgesUi.componentHeight = rootData
              .components[NudgeNudgesUi.currentNudgeIndex]
              .componentProps
              .elementProps!
              .height
              .roundToDouble() *
          scaleHeight;
      NudgeNudgesUi.componentWidth = rootData
              .components[NudgeNudgesUi.currentNudgeIndex]
              .componentProps
              .elementProps!
              .width
              .roundToDouble() *
          scaleWidth;

      // logger.i("""
      //   Component Height: ${NudgeNudgesUi.componentHeight},
      //   Component Width: ${NudgeNudgesUi.componentWidth},
      //   Component X: ${NudgeNudgesUi.componentX},
      //   Component Y: ${NudgeNudgesUi.componentY}
      // """);
    } else if (targetViewMain != null) {
      NudgeNudgesUi.componentHeight = targetViewMain.height;
      NudgeNudgesUi.componentWidth = targetViewMain.width;

      NudgeNudgesUi.componentX = targetViewMain.x;
      NudgeNudgesUi.componentY = targetViewMain.y;
    }

    var componentHeight = rootData.components[NudgeNudgesUi.currentNudgeIndex]
            .componentProps.elementProps?.height ??
        0;

    var componentWidth = rootData.components[NudgeNudgesUi.currentNudgeIndex]
            .componentProps.elementProps?.width ??
        0;

    var heightRatioDist = (NudgeNudgesUi.componentHeight / componentHeight);
    var widthRatioDist = (NudgeNudgesUi.componentWidth / componentWidth);

    ImageSize imageSize = extractSize(
      rootData.rootProps.size,
    );

    try {
      nudgeNudgesUi.heightRatio =
          (MediaQuery.of(context).size.height / imageSize.height);
      nudgeNudgesUi.widthRatio =
          (MediaQuery.of(context).size.width / imageSize.width);
    } catch (e) {
      print(e);
    }

    double contentX = rootData.components[NudgeNudgesUi.currentNudgeIndex]
            .componentProps.contentX!
            .toDouble() *
        widthRatioDist;

    double contentY = rootData.components[NudgeNudgesUi.currentNudgeIndex]
            .componentProps.contentY!
            .toDouble() *
        heightRatioDist;

    Color fillColor = HexColor.fromHex(rootData
                .components[NudgeNudgesUi.currentNudgeIndex]
                .componentProps
                .overlayColor ??
            "#000000")
        .withOpacity(
      rootData.components[NudgeNudgesUi.currentNudgeIndex].componentProps
              .overlayOpacity! /
          100,
    );

    // double bgOpacity = double.parse(
    //   rootData.components[NudgeNudgesUi.currentNudgeIndex].componentProps
    //       .overlayOpacity
    //       .toString(),
    // );

    double arrowImageX = rootData.components[NudgeNudgesUi.currentNudgeIndex]
            .componentProps.spotlightArrowX!
            .toDouble() *
        widthRatioDist;

    double arrowImageY = rootData.components[NudgeNudgesUi.currentNudgeIndex]
            .componentProps.spotlightArrowY!
            .toDouble() *
        heightRatioDist;

    // log("arrowImageX: $arrowImageX, arrowImageY: $arrowImageY", name: "Arrow");

    overlayForegroundEntry = OverlayEntry(builder: (context) {
      return Positioned(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: Opacity(
          opacity: 0,
          child: ClipPath(
            clipper: RectangularHoleClipper(
              xPosition: NudgeNudgesUi.componentX,
              yPosition: NudgeNudgesUi.componentY,
              width: NudgeNudgesUi.componentWidth,
              height: NudgeNudgesUi.componentHeight,
            ),
            child: Stack(
              children: [
                GestureDetector(
                  onTap: () {
                    overlayForegroundEntry?.remove();
                  },
                  child: Container(
                    color: fillColor,
                  ),
                ),
                Positioned(
                  top: NudgeNudgesUi.componentY,
                  left: NudgeNudgesUi.componentX,
                  child: UIPage(
                    rootId: rootData.id,
                    taskId: NudgeNudgesUi.taskID!,
                    key: nudgeNudgesUi.contentKey,
                    nudgeProps: rootData
                        .components[NudgeNudgesUi.currentNudgeIndex]
                        .componentProps
                        .toJson(),
                    type: () {
                      if (rootData.components[NudgeNudgesUi.currentNudgeIndex]
                              .componentProps.orientation ==
                          "vertical") {
                        return 24;
                      } else {
                        return 25;
                      }
                    }(),
                    json: rootData
                        .components[NudgeNudgesUi.currentNudgeIndex].widgets!,
                    assetUrl: assetUrl,
                    assets: Nudge.assets,
                  ),
                ),
                rootData.components[NudgeNudgesUi.currentNudgeIndex]
                                .componentProps.spotlightArrowAsset !=
                            null &&
                        rootData.components[NudgeNudgesUi.currentNudgeIndex]
                            .componentProps.spotlightArrowAsset!.isNotEmpty
                    ? Positioned(
                        top: NudgeNudgesUi.componentY +
                            NudgeNudgesUi.componentHeight / 2 -
                            arrowImageY,
                        left: NudgeNudgesUi.componentX +
                            NudgeNudgesUi.componentWidth / 2 -
                            arrowImageX,
                        child: rootData
                                .components[NudgeNudgesUi.currentNudgeIndex]
                                .componentProps
                                .spotlightArrowAsset!
                                .split("?")[0]
                                .isNotEmpty
                            ? Image.network(
                                () {
                                  if (rootData
                                      .components[
                                          NudgeNudgesUi.currentNudgeIndex]
                                      .componentProps
                                      .spotlightArrowAsset!
                                      .contains('.gif')) {
                                    return rootData
                                        .components[
                                            NudgeNudgesUi.currentNudgeIndex]
                                        .componentProps
                                        .spotlightArrowAsset!;
                                  }

                                  var asset = rootData
                                      .components[
                                          NudgeNudgesUi.currentNudgeIndex]
                                      .componentProps
                                      .spotlightArrowAsset!
                                      .split("?")[0];

                                  if (asset.isEmpty) {
                                    return "";
                                  }

                                  return assetUrl + asset;
                                }(),
                                fit: BoxFit.fill,
                                scale: 1.0,
                                height: rootData
                                        .components[
                                            NudgeNudgesUi.currentNudgeIndex]
                                        .componentProps
                                        .spotlightArrowHeight!
                                        .toDouble() *
                                    nudgeNudgesUi.heightRatio,
                                width: rootData
                                        .components[
                                            NudgeNudgesUi.currentNudgeIndex]
                                        .componentProps
                                        .spotlightArrowWidth!
                                        .toDouble() *
                                    nudgeNudgesUi.widthRatio,
                              )
                            : const SizedBox.shrink(),
                      )
                    : const SizedBox.shrink(),
              ],
            ),
          ),
        ),
      );
    });

    NudgeProviderState.navigatorKey.currentState!.overlay!.insert(
      overlayForegroundEntry!,
    );

    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      double newTop;
      double newLeft;

      double newArrowTop;
      double newArrowLeft;

      try {
        final RenderBox renderBox = nudgeNudgesUi.contentKey.currentContext!
            .findRenderObject() as RenderBox;

        NudgeNudgesUi.spotlightContainerHeight = renderBox.size.height;
        NudgeNudgesUi.spotlightContainerWidth = renderBox.size.width;

        // print(
        //     "Spotlight Container Height: ${NudgeNudgesUi.spotlightContainerHeight}");
        // print(
        //     "Spotlight Container Width: ${NudgeNudgesUi.spotlightContainerWidth}");

        var baseX = NudgeNudgesUi.componentX + NudgeNudgesUi.componentWidth / 2;

        var baseY =
            NudgeNudgesUi.componentY + NudgeNudgesUi.componentHeight / 2;

        var contentHeight = NudgeNudgesUi.spotlightContainerHeight;

        var contentWidth = NudgeNudgesUi.spotlightContainerWidth;

        // print("Content Height: $contentHeight, Content Width: $contentWidth");
        // print("Base X: $baseX, Base Y: $baseY");
        // print("Content X: $contentX, Content Y: $contentY");

        newTop = baseY - contentHeight / 2 + contentY;
        newLeft = baseX - contentWidth / 2 + contentX;

        var arrowHeight = rootData.components[NudgeNudgesUi.currentNudgeIndex]
                .componentProps.spotlightArrowHeight!
                .toDouble() *
            nudgeNudgesUi.heightRatio;

        var arrowWidth = rootData.components[NudgeNudgesUi.currentNudgeIndex]
                .componentProps.spotlightArrowWidth!
                .toDouble() *
            nudgeNudgesUi.widthRatio;

        newArrowTop = baseY - arrowHeight / 2 + arrowImageY;
        newArrowLeft = baseX - arrowWidth / 2 + arrowImageX;

        overlayForegroundEntry?.remove();
        // print("New Top: $newTop, New Left: $newLeft");
        // print(
        //     "Component Y: ${NudgeNudgesUi.componentY}, Component X: ${NudgeNudgesUi.componentX}");

        overlayForegroundEntry = OverlayEntry(builder: (context) {
          return ClipPath(
            clipper: RectangularHoleClipper(
              xPosition: NudgeNudgesUi.componentX,
              yPosition: NudgeNudgesUi.componentY,
              width: NudgeNudgesUi.componentWidth,
              height: NudgeNudgesUi.componentHeight,
            ),
            child: Stack(
              children: [
                GestureDetector(
                  onTap: () {
                    overlayBackgroundEntry!.remove();
                    overlayForegroundEntry!.remove();
                    Nudge.getInstance().submit(
                      taskId: NudgeNudgesUi.taskID!,
                      response: [
                        {
                          "root_id": rootData.id,
                          "widget_id": rootData
                              .components[NudgeNudgesUi.currentNudgeIndex].id,
                          // "component_id": rootData
                          //     .components[NudgeNudgesUi.currentNudgeIndex].id,
                          // "wt": null,
                          "answers": [],
                          "action": "DISMISSED",
                        }
                      ],
                      onSuccessCallback: (response) {
                        print("Spotlight Dismissed, $response");
                      },
                      onErrorCallback: (error, stackTrace) {
                        print("Error: $error");
                      },
                    );
                  },
                  child: Container(
                    color: fillColor,
                  ),
                ),
                Positioned(
                  top: newArrowTop,
                  left: newArrowLeft,
                  child: rootData.components[NudgeNudgesUi.currentNudgeIndex]
                                  .componentProps.spotlightArrowAsset !=
                              null &&
                          rootData.components[NudgeNudgesUi.currentNudgeIndex]
                                  .componentProps.spotlightArrowAsset !=
                              ""
                      ? Image.network(
                          () {
                            if (rootData
                                .components[NudgeNudgesUi.currentNudgeIndex]
                                .componentProps
                                .spotlightArrowAsset!
                                .contains('.gif')) {
                              return rootData
                                  .components[NudgeNudgesUi.currentNudgeIndex]
                                  .componentProps
                                  .spotlightArrowAsset!;
                            }

                            var asset = rootData
                                .components[NudgeNudgesUi.currentNudgeIndex]
                                .componentProps
                                .spotlightArrowAsset!
                                .split("?")[0];

                            return assetUrl + asset;
                          }(),
                          fit: BoxFit.fill,
                          scale: 1.0,
                          height: rootData
                                  .components[NudgeNudgesUi.currentNudgeIndex]
                                  .componentProps
                                  .spotlightArrowHeight!
                                  .toDouble() *
                              nudgeNudgesUi.heightRatio,
                          width: rootData
                                  .components[NudgeNudgesUi.currentNudgeIndex]
                                  .componentProps
                                  .spotlightArrowWidth!
                                  .toDouble() *
                              nudgeNudgesUi.widthRatio,
                        )
                      : const SizedBox(),
                ),
                Positioned(
                  top: newTop,
                  left: newLeft,
                  child: UIPage(
                    rootId: rootData.id,
                    taskId: NudgeNudgesUi.taskID!,
                    callBack: ({widgetId, target, clickType, widgetType}) {
                      Nudge.getInstance().submit(
                        taskId: NudgeNudgesUi.taskID!,
                        response: [
                          {
                            "root_id": rootData.id,
                            "widget_id": rootData
                                .components[NudgeNudgesUi.currentNudgeIndex].id,
                            // "component_id": rootData
                            //     .components[NudgeNudgesUi.currentNudgeIndex].id,
                            "wt": widgetType,
                            "answers": [],
                            "action": "CTA_CLICKED",
                          }
                        ],
                        onSuccessCallback: (response) {
                          print("Spotlight CTA Clicked, $response");
                        },
                        onErrorCallback: (error, stackTrace) {
                          print("Error: $error");
                        },
                      );

                      if (clickType == "DEEP_LINK") {
                        _launchUrl(target!);
                      } else if (clickType == "EXTERNAL_URL") {
                        _launchUrl(target!);
                      } else if (clickType == "NEXT_NUDGE") {
                        if (NudgeNudgesUi.currentNudgeIndex ==
                            NudgeNudgesUi.nudgesLength - 1) {
                          overlayBackgroundEntry?.remove();
                          overlayForegroundEntry?.remove();
                          return;
                        }
                        NudgeNudgesUi.currentNudgeIndex++;

                        // print(
                        //     "Next Nudge Index: ${NudgeNudgesUi.currentNudgeIndex}, type : ${rootData.components[NudgeNudgesUi.currentNudgeIndex].componentProps.name}");
                        if (rootData.components[NudgeNudgesUi.currentNudgeIndex]
                                .componentProps.type ==
                            "spotlight") {
                          print("Spotlight");
                          overlayForegroundEntry?.remove();
                          overlayBackgroundEntry?.remove();
                          nudgeSpotlight(context, rootData, eventName);
                        } else if (rootData
                                .components[NudgeNudgesUi.currentNudgeIndex]
                                .componentProps
                                .type ==
                            "coachmark") {
                          print("Coachmark");
                          overlayForegroundEntry?.remove();
                          overlayBackgroundEntry?.remove();
                          nudgeCoachMark(context, rootData, eventName);
                        } else if (rootData
                                .components[NudgeNudgesUi.currentNudgeIndex]
                                .componentProps
                                .type ==
                            "tooltip") {
                          print("Tooltip");
                          overlayForegroundEntry?.remove();
                          overlayBackgroundEntry?.remove();
                          nudgeTooltip(context, rootData, eventName);
                        }
                      } else {
                        overlayBackgroundEntry?.remove();
                        overlayForegroundEntry?.remove();
                      }
                    },
                    // key: nudgeNudgesUi.contentKey,
                    nudgeProps: rootData
                        .components[NudgeNudgesUi.currentNudgeIndex]
                        .componentProps
                        .toJson(),
                    // width: NudgeNudgesUi.spotlightContainerWidth,
                    type: () {
                      if (rootData.components[NudgeNudgesUi.currentNudgeIndex]
                              .componentProps.orientation ==
                          "vertical") {
                        return 24;
                      } else {
                        return 25;
                      }
                    }(),
                    width: NudgeNudgesUi.spotlightContainerWidth -
                        (rootData.components[NudgeNudgesUi.currentNudgeIndex]
                            .componentProps.padding.left) -
                        (rootData.components[NudgeNudgesUi.currentNudgeIndex]
                            .componentProps.padding.right),
                    json: rootData
                        .components[NudgeNudgesUi.currentNudgeIndex].widgets!,
                    assetUrl: assetUrl,
                    assets: Nudge.assets,
                  ),
                ),
              ],
            ),
          );
        });

        logger.e("UPDATING NEXT CALLBACK, SPOTLIGHT!!!!");

        Future<void> newNextCallback(nextRootId) async {
          logger.e("NEXT CALLBACK, SPOTLIGHT!!!!, $nextRootId");
          if (NudgeNudgesUi.currentNudgeIndex ==
              NudgeNudgesUi.nudgesLength - 1) {
            overlayBackgroundEntry?.remove();
            overlayForegroundEntry?.remove();
            return;
          }
          NudgeNudgesUi.currentNudgeIndex++;

          if (rootData.components[NudgeNudgesUi.currentNudgeIndex]
                  .componentProps.type ==
              "spotlight") {
            overlayForegroundEntry?.remove();
            overlayBackgroundEntry?.remove();
            nudgeSpotlight(context, rootData, eventName);
          } else if (rootData.components[NudgeNudgesUi.currentNudgeIndex]
                  .componentProps.type ==
              "coachmark") {
            overlayForegroundEntry?.remove();
            overlayBackgroundEntry?.remove();
            nudgeCoachMark(context, rootData, eventName);
          } else if (rootData.components[NudgeNudgesUi.currentNudgeIndex]
                  .componentProps.type ==
              "tooltip") {
            overlayForegroundEntry?.remove();
            overlayBackgroundEntry?.remove();
            nudgeTooltip(context, rootData, eventName);
          }
        }

        Future<void> newCloseCallback(param) async {
          overlayBackgroundEntry?.remove();
          overlayForegroundEntry?.remove();
        }

        CentralDataRepository.updateInstance(
          NudgeNudgesUi.taskID!,
          closeCallback: ({
            rootId,
            widgetId,
            widgetType,
            context,
          }) async {
            overlayBackgroundEntry?.remove();
            overlayForegroundEntry?.remove();

            Nudge.getInstance().submit(
              taskId: NudgeNudgesUi.taskID!,
              response: [
                {
                  "root_id": rootData.id,
                  "widget_id":
                      rootData.components[NudgeNudgesUi.currentNudgeIndex].id,
                  "answers": [],
                  "action": "DISMISSED",
                }
              ],
              onSuccessCallback: (data) {},
              onErrorCallback: (error, stacktrace) {},
            );
          },
          nextCallBack: newNextCallback,
        );

        WidgetDetails? targetViewFinal =
            NudgeWidgetTracker.findWidgetPositionByLabel(
          NudgeNudgesUi.componentName,
          scaleWidth,
          scaleHeight,
        );

        if (targetViewFinal != null) {
          if (targetViewFinal.x == NudgeNudgesUi.componentX &&
              targetViewFinal.y == NudgeNudgesUi.componentY) {
            NudgeProviderState.navigatorKey.currentState!.overlay!.insert(
              overlayForegroundEntry!,
            );

            print(NudgeProviderState.navigatorKey.currentState!.overlay!);
          }
        } else if (isPositionBased) {
          NudgeProviderState.navigatorKey.currentState?.overlay
              ?.insert(overlayForegroundEntry!);
        }
      } catch (e, st) {
        print(e);
        print(st);
      }
    });
  }).catchError((e, stackTrace) {
    log(e.toString(), name: 'NudgeSpotlight');
    log(stackTrace.toString(), name: 'NudgeSpotlight');
  });
}