makeDialog static method

Future<void> makeDialog(
  1. BuildContext buildContext,
  2. String sendId,
  3. String surveyId,
  4. String channelId, {
  5. Map<String, dynamic> parameters = const {},
  6. Map<String, dynamic> options = const {},
  7. VoidCallback? onCancel,
  8. VoidCallback? onSubmit,
  9. ErrorCallback? onError,
  10. VoidCallback? onClose,
})

Implementation

static Future<void> makeDialog(BuildContext buildContext, String sendId,
    String surveyId, String channelId,
    {Map<String, dynamic> parameters = const {},
    Map<String, dynamic> options = const {},
    VoidCallback? onCancel,
    VoidCallback? onSubmit,
    ErrorCallback? onError,
    VoidCallback? onClose}) async {
  if ((sendId.isEmpty && (surveyId.isEmpty || channelId.isEmpty))) {
    LoggerService.error(
        "invalid parameter please check sendid sid $sendId, surveyId $surveyId and channelId $channelId");
    return;
  }

  ServiceContext serviceContext = ServiceContext();
  SurveyModel survey;

  try {
    survey = await serviceContext.unionStart(
        sendId, surveyId, channelId, parameters);
  } catch (e) {
    LoggerService.error("unionStart failed: $e");
    onError?.call(e.toString());
    return;
  }

  Alignment alignment = Alignment.bottomCenter;

  switch (survey.channelConfig!.embedVerticalAlign) {
    case 'BOTTOM':
      alignment = Alignment.bottomCenter;
      break;
    case 'TOP':
      alignment = Alignment.topCenter;
      break;
    case 'CENTER':
      alignment = Alignment.center;
      break;
    default:
  }
  // survey.channelConfig.embedHeightMode
  // showAlignedDialog

  return showGeneralDialog(
    context: buildContext,
    useRootNavigator: false,
    barrierColor: survey.channelConfig!.embedBackGround
        ? Colors.black54
        : Colors.transparent, // Background color based on config
    barrierDismissible: options['clickDismiss'] ?? false,
    transitionDuration: const Duration(milliseconds: 300),
    transitionBuilder: (context, animation, secondaryAnimation, child) {
      // 根据对齐方式选择不同的动画效果
      switch (survey.channelConfig!.embedVerticalAlign) {
        case 'BOTTOM':
          // 底部向上滑入
          final offsetAnimation = Tween<Offset>(
            begin: const Offset(0.0, 1.0), // 从下方开始
            end: Offset.zero,
          ).animate(CurvedAnimation(
            parent: animation,
            curve: Curves.easeOutCubic,
          ));
          return SlideTransition(
            position: offsetAnimation,
            child: child,
          );

        case 'TOP':
          // 顶部向下滑入
          final offsetAnimation = Tween<Offset>(
            begin: const Offset(0.0, -1.0), // 从上方开始
            end: Offset.zero,
          ).animate(CurvedAnimation(
            parent: animation,
            curve: Curves.easeOutCubic,
          ));
          return SlideTransition(
            position: offsetAnimation,
            child: child,
          );

        default:
          // CENTER: 默认淡入淡出
          return FadeTransition(
            opacity: CurvedAnimation(
              parent: animation,
              curve: Curves.easeOut,
            ),
            child: child,
          );
      }
    },
    pageBuilder: (BuildContext context, Animation<double> animation,
        Animation<double> secondaryAnimation) {
      // ignore: deprecated_member_use
      return WillPopScope(
        // 使用 WillPopScope 以兼容 Flutter 3.7.8+
        // PopScope 需要 Flutter 3.16+,暂不迁移以保持向后兼容性
        onWillPop: () async {
          // 处理返回键事件
          Navigator.of(context).pop('normal_close');
          return false; // 返回 false 拦截系统的 pop 行为
        },
        child: Align(
          alignment: alignment,
          child: SafeArea(
            top: alignment == Alignment.topCenter, // 顶部对齐时启用顶部安全区域
            bottom: alignment == Alignment.bottomCenter, // 底部对齐时启用底部安全区域
            left: true, // 始终保留横向安全区域
            right: true,
            minimum: EdgeInsets.symmetric(
              horizontal: survey.channelConfig!.appPaddingWidth,
            ),
            child: Material(
                color: Colors
                    .transparent, // Transparent background for custom styling
                child: KeyboardAwareDialog(
                  embedHeight: survey.channelConfig!.embedHeight,
                  embedHeightMode: survey.channelConfig!.embedHeightMode,
                  child: Container(
                    margin: EdgeInsets.symmetric(
                      horizontal: survey.channelConfig!.appPaddingWidth,
                    ),
                    decoration: BoxDecoration(
                      color: survey.style.backgroundColor,
                      borderRadius: BorderRadius.only(
                        topLeft: Radius.circular(
                            survey.channelConfig!.embedVerticalAlign != 'TOP'
                                ? survey.channelConfig!.appBorderRadius
                                : 0),
                        topRight: Radius.circular(
                            survey.channelConfig!.embedVerticalAlign != 'TOP'
                                ? survey.channelConfig!.appBorderRadius
                                : 0),
                        bottomLeft: Radius.circular(
                            survey.channelConfig!.embedVerticalAlign !=
                                    'BOTTOM'
                                ? survey.channelConfig!.appBorderRadius
                                : 0),
                        bottomRight: Radius.circular(
                            survey.channelConfig!.embedVerticalAlign !=
                                    'BOTTOM'
                                ? survey.channelConfig!.appBorderRadius
                                : 0),
                      ),
                    ),
                    child: ChangeNotifierProvider<ServiceContext>.value(
                      value: serviceContext,
                      child: Stack(
                        children: [
                          SingleChildScrollView(
                            physics: const ClampingScrollPhysics(), // 防止弹性滚动
                            keyboardDismissBehavior:
                                ScrollViewKeyboardDismissBehavior
                                    .manual, // 防止滚动时关闭键盘
                            child: HySurveyWidget(
                              key: ValueKey('survey_${survey.clientId}'),
                              sendId: sendId,
                              surveyId: surveyId,
                              channelId: channelId,
                              showClose: false,
                              isDialog: true,
                              onCancel: () {
                                Navigator.pop(context, 'normal_close');
                              },
                              onClose: () {
                                Navigator.pop(context, 'normal_close');
                              },
                              onSubmit: onSubmit,
                              onError: onError,
                            ),
                          ),
                          if (!options.containsKey("showClose") ||
                              options["showClose"] == true)
                            Positioned(
                              right: 2,
                              top: 2,
                              child: SurveyCloseWidget(
                                onClose: () {
                                  Navigator.pop(context, 'normal_close');
                                },
                              ),
                            ),
                        ],
                      ),
                    ),
                  ),
                )),
          ),
        ),
      );
    },
  ).then((value) {
    onClose?.call();
  });
}