import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:nomo/app/widgets/click_opacity.dart'; import 'package:nomo/config/theme/theme_extensions/theme_extension.dart'; /// 通用弹窗组件 class CustomDialog { /// 显示成功弹窗(如Premium激活成功) static void showSuccess({ required String title, required String message, String buttonText = 'Got it', VoidCallback? onPressed, IconData? icon, Color? iconColor, }) { Get.generalDialog( pageBuilder: (context, animation, secondaryAnimation) { return _CustomDialogWidget( type: DialogType.success, title: title, message: message, buttonText: buttonText, onPressed: onPressed, icon: icon ?? Icons.workspace_premium, iconColor: iconColor ?? const Color(0xFFFF9500), animation: animation, ); }, barrierDismissible: false, transitionDuration: const Duration(milliseconds: 300), ); } /// 显示信息弹窗(如邮件发送成功) static void showInfo({ required String title, required String message, String buttonText = 'OK', VoidCallback? onPressed, IconData? icon, Color? iconColor, }) { Get.generalDialog( pageBuilder: (context, animation, secondaryAnimation) { return _CustomDialogWidget( type: DialogType.info, title: title, message: message, buttonText: buttonText, onPressed: onPressed, icon: icon ?? Icons.mark_email_read, iconColor: iconColor ?? const Color(0xFF00A8E8), animation: animation, ); }, barrierDismissible: false, transitionDuration: const Duration(milliseconds: 300), ); } /// 显示错误弹窗(如网络连接错误) static void showError({ required String title, required String message, String buttonText = 'Retry', String? cancelText, VoidCallback? onPressed, VoidCallback? onCancel, IconData? icon, Color? iconColor, Color? confirmButtonColor, String? errorCode, }) { Get.generalDialog( pageBuilder: (context, animation, secondaryAnimation) { return _CustomDialogWidget( type: DialogType.error, title: title, message: message, buttonText: buttonText, cancelText: cancelText, onPressed: onPressed, onCancel: onCancel, icon: icon ?? Icons.wifi_off, iconColor: iconColor ?? const Color(0xFFFF9500), confirmButtonColor: confirmButtonColor ?? Get.reactiveTheme.primaryColor, errorCode: errorCode, animation: animation, ); }, barrierDismissible: false, transitionDuration: const Duration(milliseconds: 300), ); } /// 显示确认弹窗(如退出登录确认) static void showConfirm({ required String title, required String message, String confirmText = 'Confirm', String cancelText = 'Cancel', required VoidCallback onConfirm, VoidCallback? onCancel, IconData? icon, Color? iconColor, Color? confirmButtonColor, }) { Get.generalDialog( pageBuilder: (context, animation, secondaryAnimation) { return _CustomDialogWidget( type: DialogType.confirm, title: title, message: message, buttonText: confirmText, // 添加必需的参数 confirmText: confirmText, cancelText: cancelText, onConfirm: onConfirm, onCancel: onCancel, icon: icon ?? Icons.info_outline, iconColor: iconColor ?? const Color(0xFFFF3B30), confirmButtonColor: confirmButtonColor ?? const Color(0xFFFF3B30), animation: animation, ); }, barrierDismissible: true, barrierLabel: 'Dismiss', transitionDuration: const Duration(milliseconds: 300), ); } } /// 弹窗类型枚举 enum DialogType { success, info, error, confirm } /// 自定义弹窗组件 class _CustomDialogWidget extends StatelessWidget { final DialogType type; final String title; final String message; final String buttonText; final String? confirmText; final String? cancelText; final VoidCallback? onPressed; final VoidCallback? onConfirm; final VoidCallback? onCancel; final IconData icon; final Color iconColor; final Color? confirmButtonColor; final String? errorCode; final Animation? animation; const _CustomDialogWidget({ required this.type, required this.title, required this.message, required this.buttonText, this.confirmText, this.cancelText, this.onPressed, this.onConfirm, this.onCancel, required this.icon, required this.iconColor, this.confirmButtonColor, this.errorCode, this.animation, }); @override Widget build(BuildContext context) { if (animation == null) { // 如果没有动画,返回普通弹窗 return _buildDialog(); } // 使用动画构建弹窗 return _buildAnimatedDialog(); } /// 构建普通弹窗 Widget _buildDialog() { return Dialog( backgroundColor: Colors.transparent, insetPadding: EdgeInsets.symmetric(horizontal: 24.w), child: _buildDialogContent(), ); } /// 构建带动画的弹窗 Widget _buildAnimatedDialog() { return Dialog( backgroundColor: Colors.transparent, insetPadding: EdgeInsets.symmetric(horizontal: 24.w), child: AnimatedBuilder( animation: animation!, builder: (context, child) { // 使用不同的曲线来避免关闭时的抖动 final scaleValue = Tween(begin: 0.8, end: 1.0) .animate( CurvedAnimation( parent: animation!, curve: Curves.easeOutCubic, reverseCurve: Curves.easeInCubic, ), ) .value; final offsetValue = Tween(begin: 30, end: 0) .animate( CurvedAnimation( parent: animation!, curve: Curves.easeOutCubic, reverseCurve: Curves.easeInCubic, ), ) .value; return Transform.scale( scale: scaleValue, child: Transform.translate( offset: Offset(0, offsetValue), child: Opacity(opacity: animation!.value, child: child), ), ); }, child: _buildDialogContent(), ), ); } /// 构建弹窗内容 Widget _buildDialogContent() { return Container( padding: EdgeInsets.all(24.w), decoration: BoxDecoration( color: Get.reactiveTheme.highlightColor, borderRadius: BorderRadius.circular(16.r), ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // 图标 _buildIcon(), // 标题和消息 _buildContent(), 24.verticalSpaceFromWidth, // 按钮 _buildButtons(), ], ), ); } /// 构建图标 Widget _buildIcon() { return Container( margin: EdgeInsets.only(bottom: 10.w), child: Icon(icon, size: 40.w, color: iconColor), ); } /// 构建内容区域 Widget _buildContent() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 标题 Text( title, style: TextStyle( fontSize: 22.sp, fontWeight: FontWeight.w500, color: Get.reactiveTheme.textTheme.bodyLarge!.color, ), ), 18.verticalSpaceFromWidth, // 消息 Text( message, style: TextStyle( fontSize: 14.sp, color: Get.reactiveTheme.hintColor, height: 1.4, ), ), ], ); } /// 构建按钮区域 Widget _buildButtons() { switch (type) { case DialogType.success: case DialogType.info: return _buildSingleButton(); case DialogType.error: return _buildErrorButtons(); case DialogType.confirm: return _buildConfirmButtons(); } } /// 构建单个按钮 Widget _buildSingleButton() { return SizedBox( width: double.infinity, height: 42.w, child: ClickOpacity( onTap: () { onPressed?.call(); }, child: Container( decoration: BoxDecoration( color: confirmButtonColor ?? Get.reactiveTheme.primaryColor, borderRadius: BorderRadius.circular(8.r), ), alignment: Alignment.center, child: Text( buttonText, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: Get.reactiveTheme.textTheme.bodyLarge!.color, ), ), ), ), ); } /// 构建错误弹窗按钮 Widget _buildErrorButtons() { return Row( children: [ if (cancelText != null) ...[ Expanded( child: ClickOpacity( onTap: () { onCancel?.call(); }, child: Container( height: 42.h, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.r), border: Border.all( color: Get.reactiveTheme.dividerColor, width: 1.w, ), ), alignment: Alignment.center, child: Text( cancelText!, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: Get.reactiveTheme.hintColor, ), ), ), ), ), SizedBox(width: 12.w), ], Expanded( child: ClickOpacity( onTap: () { onPressed?.call(); }, child: Container( height: 42.h, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.r), border: Border.all( color: Get.reactiveTheme.dividerColor, width: 1.w, ), ), alignment: Alignment.center, child: Text( buttonText, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: confirmButtonColor, ), ), ), ), ), ], ); } /// 构建确认弹窗按钮 Widget _buildConfirmButtons() { return Row( children: [ Expanded( child: ClickOpacity( onTap: () { onCancel?.call(); }, child: Container( height: 42.w, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.r), border: Border.all( color: Get.reactiveTheme.dividerColor, width: 1.w, ), ), alignment: Alignment.center, child: Text( cancelText ?? 'Cancel', style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: Get.reactiveTheme.hintColor, ), ), ), ), ), 8.horizontalSpace, Expanded( child: ClickOpacity( onTap: () { onConfirm?.call(); }, child: Container( height: 42.w, decoration: BoxDecoration( color: confirmButtonColor ?? iconColor, borderRadius: BorderRadius.circular(8.r), ), alignment: Alignment.center, child: Text( confirmText ?? 'Confirm', style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: Get.reactiveTheme.textTheme.bodyLarge!.color, ), ), ), ), ), ], ); } }