// ignore_for_file: deprecated_member_use_from_same_package, use_build_context_synchronously, deprecated_member_use import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:go_router/go_router.dart'; import 'package:hoshan/core/gen/assets.gen.dart'; import 'package:hoshan/core/routes/route_generator.dart'; import 'package:hoshan/core/services/firebase/firebase_api.dart'; import 'package:hoshan/data/model/ai/credit_model.dart'; import 'package:hoshan/data/model/chat_args.dart'; import 'package:hoshan/data/model/event_model.dart'; import 'package:hoshan/data/storage/shared_preferences_helper.dart'; import 'package:hoshan/ui/screens/main/home/bloc/bots_bloc.dart'; import 'package:hoshan/ui/screens/setting/cubit/settlement_cubit.dart'; import 'package:hoshan/ui/screens/splash/cubit/user_info_cubit.dart'; import 'package:hoshan/ui/theme/colors.dart'; import 'package:hoshan/ui/theme/cubit/theme_mode_cubit.dart'; import 'package:hoshan/ui/theme/responsive.dart'; import 'package:hoshan/ui/theme/text.dart'; import 'package:hoshan/ui/widgets/components/button/loading_button.dart'; import 'package:hoshan/ui/widgets/components/calender/persian_date_picker.dart'; import 'package:hoshan/ui/widgets/components/calender/shamsi_year_month_picker.dart'; import 'package:hoshan/ui/widgets/components/image/custome_image.dart'; import 'package:hoshan/ui/widgets/components/image/network_image.dart'; import 'package:hoshan/ui/widgets/components/snackbar/snackbar_manager.dart'; import 'package:hoshan/ui/widgets/components/text/auth_text_field.dart'; import 'package:hoshan/ui/widgets/components/video/video_player_widget.dart'; import 'package:hoshan/ui/widgets/sections/loading/default_placeholder.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:shamsi_date/shamsi_date.dart'; import 'package:string_validator/string_validator.dart'; import 'package:url_launcher/url_launcher.dart'; class DialogHandler { final BuildContext context; final double maxDialogWidthInDesktop = 600; DialogHandler({required this.context}); Future loadingDialog({final String? text}) async { await showDialog( context: context, barrierDismissible: false, builder: (context) => Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shadowColor: Colors.white, backgroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: AspectRatio( aspectRatio: 1 / 1, child: Center( child: Padding( padding: const EdgeInsets.all(16.0), child: SpinKitThreeBounce( size: 36, color: AppColors.primaryColor.defaultShade, ), ), ), ), ), ), ); } Future showDatePicker( {final Function(List)? onConfirm, final Function()? onDismise, final int? dateCounts, final List? selectedDates}) async { await showDialog( context: context, builder: (context) { return Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( surfaceTintColor: Theme.of(context).colorScheme.surface, backgroundColor: Theme.of(context).colorScheme.surface, child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: MediaQuery.sizeOf(context).width, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(16), ), child: PersianDatePicker( selectedDates: selectedDates, dateCounts: dateCounts, onConfirm: (p0) { onConfirm?.call(p0); context.pop(); }, onDismise: () { onDismise?.call(); context.pop(); }, ), ), ], )), ); }, ); } Future showExit() async { bool exit = false; await showDialog( context: context, builder: (context) { return Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( margin: const EdgeInsets.all(16), width: 120, height: 120, padding: const EdgeInsets.all(8), decoration: BoxDecoration( shape: BoxShape.circle, color: AppColors.red[50]), child: Assets.icon.gif.exit.image()), Text( 'خروج از برنامه', style: AppTextStyles.headline6.copyWith( color: Theme.of(context).colorScheme.onSurface), textAlign: TextAlign.center, ), const SizedBox( height: 4, ), Text( 'میخواهید از برنامه خارج شوید؟', style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.onSurface), textAlign: TextAlign.center, ), const SizedBox( height: 16, ), Row( children: [ Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: LoadingButton( width: MediaQuery.sizeOf(context).width, radius: 32, isOutlined: true, color: Theme.of(context).colorScheme.secondary, backgroundColor: Theme.of(context).dialogTheme.backgroundColor, onPressed: () { exit = true; context.pop(); }, child: Text( 'بله', style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.secondary), ), ), )), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: LoadingButton( width: MediaQuery.sizeOf(context).width, radius: 32, color: Theme.of(context).colorScheme.secondary, child: Text('خیر', style: AppTextStyles.body4 .copyWith(color: Colors.white)), onPressed: () { context.pop(); }, ), )), ], ) ], ), ), ), ); }, ); return exit; } Future showLogOut() async { await showDialog( context: context, builder: (context) { return Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( margin: const EdgeInsets.all(16), width: 120, height: 120, padding: const EdgeInsets.all(8), decoration: BoxDecoration( shape: BoxShape.circle, color: AppColors.red[50]), child: Assets.icon.gif.exit.image()), Text( '!خروج از حساب کاربری', style: AppTextStyles.headline6.copyWith( color: Theme.of(context).colorScheme.onSurface), textAlign: TextAlign.center, ), const SizedBox( height: 4, ), Text( 'از خروج اطمینان دارید؟', style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.onSurface), textAlign: TextAlign.center, ), const SizedBox( height: 16, ), Row( children: [ Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: LoadingButton( width: MediaQuery.sizeOf(context).width, radius: 32, isOutlined: true, backgroundColor: Theme.of(context).dialogTheme.backgroundColor, color: Theme.of(context).colorScheme.secondary, onPressed: () { AuthTokenStorage.clearToken(); FirebasApi.deleteToken(); context.read().clearUser(); contxet.go(Routes.main, extra: false); }, child: Text( 'بله', style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.secondary), ), ), )), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: LoadingButton( width: MediaQuery.sizeOf(context).width, radius: 32, color: Theme.of(context).colorScheme.secondary, child: Text('خیر', style: AppTextStyles.body4 .copyWith(color: Colors.white)), onPressed: () { context.pop(); }, ), )), ], ) ], ), ), ), ); }, ); } Future showDeleteItem( {final String? title, final String? description, final Function()? onConfirm}) async { await showDialog( context: context, builder: (context) { return Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( margin: const EdgeInsets.all(16), width: 120, height: 120, padding: const EdgeInsets.all(8), decoration: BoxDecoration( shape: BoxShape.circle, color: AppColors.red[50]), child: Assets.icon.gif.delete.image()), if (title != null) Text( title, style: AppTextStyles.headline6.copyWith( color: Theme.of(context).colorScheme.onSurface), textAlign: TextAlign.center, textDirection: TextDirection.rtl, ), const SizedBox( height: 4, ), if (description != null) Text( description, style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.onSurface), textAlign: TextAlign.center, textDirection: TextDirection.rtl, ), const SizedBox( height: 16, ), Row( children: [ Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: LoadingButton( width: MediaQuery.sizeOf(context).width, radius: 32, isOutlined: true, backgroundColor: Theme.of(context).dialogTheme.backgroundColor, color: Theme.of(context).colorScheme.secondary, onPressed: () { onConfirm?.call(); context.pop(); }, child: Text( 'بله', style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.secondary), ), ), )), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: LoadingButton( width: MediaQuery.sizeOf(context).width, radius: 32, color: Theme.of(context).colorScheme.secondary, child: Text('خیر', style: AppTextStyles.body4 .copyWith(color: Colors.white)), onPressed: () { context.pop(); }, ), )), ], ) ], ), ), ), ); }, ); } Future showImageHero( {required final String image, final bool? isUrl}) async { final TransformationController transformationController = TransformationController(); await showDialog( context: context, builder: (context) { return Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( insetPadding: EdgeInsets.zero, backgroundColor: Colors.transparent, child: SizedBox( width: double.infinity, height: double.infinity, child: GestureDetector( onTap: () => context.pop(), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: InteractiveViewer( transformationController: transformationController, panEnabled: true, minScale: 0.5, maxScale: 4, child: Center( child: Padding( padding: const EdgeInsets.all(16.0), child: GestureDetector( onTap: () {}, onDoubleTapDown: (details) { final double currentScale = transformationController .value .getMaxScaleOnAxis(); final double newScale = currentScale >= 4.0 ? 1 : currentScale * 2; final Offset tapPosition = details.localPosition; final Matrix4 newMatrix = Matrix4.identity() ..scale(newScale) ..translate( (newScale == 1 ? 1 : tapPosition.dx) * (1 - newScale / currentScale), (newScale == 1 ? 1 : tapPosition.dy) * (1 - newScale / currentScale), ); transformationController.value = newMatrix; }, child: Container( constraints: BoxConstraints( maxWidth: MediaQuery.sizeOf(context).width * 0.8, maxHeight: MediaQuery.sizeOf(context).width * 0.8, ), child: isUrl ?? image.isURL() ? ImageNetwork( url: image, radius: 4, ) : ClipRRect( borderRadius: BorderRadius.circular(4), child: CustomeImage( src: image, )), ), ), ), ), ), ), ), ), ), ); }, ); } Future showVideoHero( {required final String url, final bool? isUrl}) async { await showDialog( context: context, builder: (context) { return Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( insetPadding: EdgeInsets.zero, backgroundColor: Colors.transparent, child: Stack( children: [ SizedBox( width: double.infinity, height: double.infinity, child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: VideoPlayerWidget( url: url, )), ), Positioned( top: 16, left: 16, child: GestureDetector( onTap: () => context.pop(), child: Container( width: 24, height: 24, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: Theme.of(context).colorScheme.onSurface, )), child: Icon( CupertinoIcons.xmark, size: 18, color: Theme.of(context).colorScheme.onSurface, ), ), )) ], ), ), ); }, ); } void showUpgradeCredit() async { await showAlertDialog( title: 'اوه نه! اعتبارت تموم شد!', imageGif: Assets.icon.gif.oneCoin.image(), description: 'برای ادامه ماجراجویی‌هاتون با مدل‌های هوش مصنوعی حرفه‌ای، لطفاً اشتراکتون رو ارتقا بدین!', onConfirmText: 'ارتقای اشتراک', onConfirm: (c) async { c.go(Routes.purchase); }, ); } void showInstagramFollow({ final Function()? onConfirm, final Function()? onCancel, }) async { await showAlertDialog( title: '!هوشانو دنبال کن', imageGif: Assets.icon.gif.instagram.image(), description: 'اگه دنبال آخرین اخبار، آموزش‌ها، کدهای تخفیف و کلی چیز خفن دیگه هستی، حتماً ما رو تو اینستاگرام فالو کن! تازه، 20 سکه هوشانی هم هدیه می‌گیری!', onConfirmText: 'دنبال کردن', onCancel: (c) => context.pop(), onConfirm: (c) async { await launchUrl(Uri.parse('https://www.instagram.com/Houshan.ai'), mode: LaunchMode.externalApplication) .onError( (error, stackTrace) { if (kDebugMode) { print('error open Link is: $error'); } return false; }, ); }, ); } void showHeart({ final Function()? onConfirm, final Function()? onCancel, }) async { // Disabled by request: do nothing return; } void showEdit({ final Function()? onConfirm, final Function()? onCancel, }) async { await showAlertDialog( title: '!هوشانی شو', imageGif: Assets.icon.gif.write.image(), description: 'با تکمیل اطلاعات حساب کاربریت، علاوه بر اینکه 20 سکه هوشانی هدیه می‌گیری، به شکل بهینه‌تری از هوشان استفاده می‌کنی.', onConfirmText: 'دعوت از دوستان', onCancel: (c) => c.pop(), onConfirm: (c) async {}, ); } void showGift({ required final String mesasge, final Function()? onConfirm, final Function()? onCancel, }) async { await showAlertDialog( title: 'یک هدیه ویژه شما', imageGif: Assets.icon.gif.gift.image(), description: mesasge, ); } void showWellcome({ required final String mesasge, final Function()? onConfirm, final Function()? onCancel, }) async { await showAlertDialog( imageGif: Assets.icon.gif.bell.image(), description: mesasge, ); } void showCreateSuccess({ final Function()? onConfirm, final Function()? onCancel, }) async { await showAlertDialog( onConfirm: (c) async => c.pop(), onConfirmText: 'تایید', imageGif: Assets.icon.gif.clock.image(), description: 'دستیار هوش مصنوعی شما با موفقیت ساخته شد.\nاین دستیار پس از تأیید در فهرست “دستیار‌های من” نمایش داده می‌شود.', ); } void showCoin({required final Function() onSuccess}) async { await showAlertDialog( title: 'تسویه حساب', imageGif: Assets.icon.gif.coin.image(), child: Padding( padding: const EdgeInsets.only(top: 16), child: BlocProvider( create: (context) => SettlementCubit(), child: BlocConsumer( listener: (context, state) async { if (state is SettlementSuccess) { await context.read().getUserInfo(); context.read().changeCredit(CreditModel( credit: UserInfoCubit.userInfoModel.credit, freeCredit: UserInfoCubit.userInfoModel.freeCredit)); } }, builder: (context, state) { String msg = 'خطا لحظاتی دیگر دوباره تلاش کنید'; if (state is SettlementSuccess) { msg = state.message; onSuccess.call(); } if (state is SettlementFail) { if (state.message != null) { msg = state.message!; } } return state is SettlementInitial ? Column( children: [ Text( 'شیوه دریافت درآمد خود را انتخاب کنید.', style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.onSurface), textDirection: TextDirection.rtl, ), const SizedBox(height: 16), Row( children: [ Expanded( child: LoadingButton( width: double.infinity, color: AppColors.primaryColor.defaultShade, onPressed: () async { context.read().init(false); }, child: Text( 'سکه', style: AppTextStyles.body3 .copyWith(color: Colors.white), ), )), const SizedBox( width: 8, ), Expanded( child: LoadingButton( width: double.infinity, color: AppColors.primaryColor.defaultShade, onPressed: UserInfoCubit.userInfoModel.cardNumber == null ? null : () { context .read() .init(true); }, child: Text( 'ریالی', style: AppTextStyles.body3.copyWith( color: Colors.white, fontWeight: FontWeight.bold), ), )), ], ), if (UserInfoCubit.userInfoModel.cardNumber == null) Padding( padding: const EdgeInsets.all(4), child: Directionality( textDirection: TextDirection.rtl, child: Row( children: [ Assets.icon.outline.warning2.svg( color: AppColors.red.defaultShade, width: 18, height: 18), const SizedBox( width: 4, ), Flexible( child: Text( 'برای دریافت ریالی باید شماره کارت خود را در ویرایش پروفایل اضافه کنید', textDirection: TextDirection.rtl, style: AppTextStyles.body6.copyWith( color: AppColors.red.defaultShade, fontWeight: FontWeight.bold), ), ), ], ), ), ) ], ) : state is SettlementLoading ? SpinKitThreeBounce( color: AppColors.primaryColor.defaultShade, size: 32, ) : Text( msg, textDirection: TextDirection.rtl, style: AppTextStyles.body4.copyWith( fontWeight: FontWeight.bold, color: state is SettlementSuccess ? AppColors.green.defaultShade : AppColors.red.defaultShade), ); }, ), ), )); } void showExtras() async { await showAlertDialog( title: '', imageGif: Assets.icon.gif.extras.image(), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( 'قبل از هر چیز لازم است بدانید که:', style: AppTextStyles.body5.copyWith( fontWeight: FontWeight.bold, color: AppColors.gray[ context.read().isDark() ? 600 : 900]), textDirection: TextDirection.rtl, ), ], ), const SizedBox( height: 8, ), Padding( padding: const EdgeInsets.symmetric(vertical: 6.0), child: Row( textDirection: TextDirection.rtl, crossAxisAlignment: CrossAxisAlignment.start, children: [ Assets.icon.outline.verify.svg(), const SizedBox( width: 8, ), Expanded( child: Text( 'دسترسی شما تاریخ انقضاء ندارد', style: AppTextStyles.body5.copyWith( color: AppColors.gray[ context.read().isDark() ? 600 : 900]), textDirection: TextDirection.rtl, ), ), const SizedBox( width: 8, ), Assets.icon.outline.tickSquare.svg(), ], ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 6.0), child: Row( textDirection: TextDirection.rtl, crossAxisAlignment: CrossAxisAlignment.start, children: [ Assets.icon.outline.verify.svg(), const SizedBox( width: 8, ), Expanded( child: Text( 'به همه مدل‌ها و ابزارها دسترسی دارید', style: AppTextStyles.body5.copyWith( color: AppColors.gray[ context.read().isDark() ? 600 : 900]), textDirection: TextDirection.rtl, ), ), const SizedBox( width: 8, ), Assets.icon.outline.tickSquare.svg(), ], ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 6.0), child: Row( textDirection: TextDirection.rtl, crossAxisAlignment: CrossAxisAlignment.start, children: [ Assets.icon.outline.verify.svg(), const SizedBox( width: 8, ), Expanded( child: Text( 'پرداخت شما ارزان و بر اساس میزان استفاده شماست', style: AppTextStyles.body5.copyWith( color: AppColors.gray[ context.read().isDark() ? 600 : 900]), textDirection: TextDirection.rtl, ), ), const SizedBox( width: 8, ), Assets.icon.outline.tickSquare.svg(), ], ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 6.0), child: Row( textDirection: TextDirection.rtl, crossAxisAlignment: CrossAxisAlignment.start, children: [ Assets.icon.outline.verify.svg(), const SizedBox( width: 8, ), Expanded( child: Text( 'بسته‌ی انتخابی شما بلافاصله پس از پرداخت فعال می‌شود.', style: AppTextStyles.body5.copyWith( color: AppColors.gray[ context.read().isDark() ? 600 : 900]), textDirection: TextDirection.rtl, ), ), const SizedBox( width: 8, ), Assets.icon.outline.tickSquare.svg(), ], ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 6.0), child: Row( textDirection: TextDirection.rtl, crossAxisAlignment: CrossAxisAlignment.start, children: [ Assets.icon.outline.verify.svg(), const SizedBox( width: 8, ), Expanded( child: Text( 'حذف تبلیغات', style: AppTextStyles.body5.copyWith( color: AppColors.gray[ context.read().isDark() ? 600 : 900]), textDirection: TextDirection.rtl, ), ), const SizedBox( width: 8, ), Assets.icon.outline.tickSquare.svg(), ], ), ), ], )); } Future showAlertDialog({ final String? title, required final Image imageGif, final String? description, final Widget? child, final bool barrierDismissible = true, final String onConfirmText = '', final String onCancelText = 'بازگشت', final Future Function(BuildContext contxet)? onConfirm, final Function(BuildContext contxet)? onCancel, }) async { await showDialog( context: context, barrierDismissible: barrierDismissible, builder: (context) { final ValueNotifier loading = ValueNotifier(false); return Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => PopScope( canPop: barrierDismissible, child: Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ if (barrierDismissible) Row( children: [ GestureDetector( onTap: () => context.pop(), child: Container( width: 24, height: 24, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: Theme.of(context).colorScheme.onSurface, )), child: Icon( CupertinoIcons.xmark, size: 18, color: Theme.of(context).colorScheme.onSurface, ), ), ) ], ), Container( width: 94, height: 94, padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppColors.secondryColor[50], shape: BoxShape.circle), child: imageGif, ), const SizedBox( height: 8, ), if (title != null) Text( title, style: AppTextStyles.body3.copyWith( fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.onSurface), textDirection: TextDirection.rtl, ), if (description != null) Column( children: [ const SizedBox( height: 8, ), Text( description, style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.onSurface), textAlign: TextAlign.center, textDirection: TextDirection.rtl, ), ], ), if (child != null) child, const SizedBox( height: 16, ), Row( children: [ if (onConfirm != null) Expanded( flex: 6, child: ValueListenableBuilder( valueListenable: loading, builder: (context, l, _) { return LoadingButton( width: double.infinity, loading: l, color: AppColors.primaryColor.defaultShade, onPressed: () async { loading.value = true; await onConfirm.call(contxet); loading.value = false; }, child: Text( onConfirmText, style: AppTextStyles.body5 .copyWith(color: Colors.white), ), ); })), if (onConfirm != null && onCancel != null) const SizedBox( width: 24, ), if (onCancel != null) Expanded( flex: 4, child: LoadingButton( width: double.infinity, color: Theme.of(context).colorScheme.secondary, isOutlined: true, backgroundColor: Theme.of(context) .dialogTheme .backgroundColor, onPressed: () => onCancel.call(contxet), child: Text( onCancelText, style: AppTextStyles.body5.copyWith( color: Theme.of(context) .colorScheme .secondary, fontWeight: FontWeight.bold), ), )), ], ) ], ), ), ), ), ); }, ); } Future showPersonsAlert() async { final TextEditingController textEditingController = TextEditingController(); await showDialog( context: context, builder: (context) => Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(16.0), child: Directionality( textDirection: TextDirection.rtl, child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( title: Text( 'جای چه شخصیتی اینجا خالیه؟', style: AppTextStyles.body3.copyWith( color: Theme.of(context).colorScheme.onSurface), ), ), const SizedBox( height: 16, ), AuthTextField( controller: textEditingController, hintText: 'دوست داری با چه کسی گپ بزنی؟', label: 'نام شخصیت مد نظر', ), const SizedBox( height: 32, ), Row( children: [ Expanded( flex: 5, child: LoadingButton( onPressed: () { contxet.pop(); }, width: double.infinity, isOutlined: true, backgroundColor: Theme.of(context).dialogTheme.backgroundColor, color: Theme.of(context).colorScheme.primary, child: Text( 'بازگشت', style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.bold), )), ), const SizedBox( width: 12, ), Expanded( flex: 6, child: LoadingButton( onPressed: () {}, width: double.infinity, child: Text( 'تایید', style: AppTextStyles.body4.copyWith( color: Colors.white, fontWeight: FontWeight.bold), )), ), ], ) ], ), ), ), ), ), ); } /* Future showUpgradeCredit( {final String? title, final Function()? onConfirm}) async { final titleString = title == null ? '' : '" $title " '; await showDialog( context: context, builder: (context) { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(16.0), child: CircleIconBtn( size: 48, icon: Assets.icon.outline.crown, color: AppColors.red[50], iconColor: AppColors.red[100], iconPadding: const EdgeInsets.all(12), ), ), Text( 'شما به هوش مصنوعی $titleStringدسترسی ندارید', style: AppTextStyles.headline6, textAlign: TextAlign.center, ), const SizedBox( height: 4, ), Text( 'برای دسترسی، اشتراک خود را ارتقا دهید ', style: AppTextStyles.body4, textAlign: TextAlign.center, ), const SizedBox( height: 16, ), Row( children: [ Flexible( flex: 3, child: Padding( padding: const EdgeInsets.all(8.0), child: LoadingButton( width: MediaQuery.sizeOf(context).width, radius: 32, color: AppColors.red.defaultShade, child: Text('ارتقای اشتراک', style: AppTextStyles.body4 .copyWith(color: Colors.white)), onPressed: () { onConfirm?.call(); context.pop(); }, ), )), Flexible( flex: 2, child: Padding( padding: const EdgeInsets.all(8.0), child: LoadingButton( width: MediaQuery.sizeOf(context).width, radius: 32, isOutlined: true, color: AppColors.red.defaultShade, onPressed: () { context.pop(); }, child: Text( 'بازگشت', style: AppTextStyles.body4 .copyWith(color: AppColors.red.defaultShade), ), ), )), ], ) ], ), ), ); }, ); } Future showGiftCredit({final Function()? onConfirm}) async { await showDialog( context: context, builder: (context) { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ GestureDetector( onTap: () => context.pop(), child: Container( width: 24, height: 24, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all(color: AppColors.gray[900])), child: const Icon( CupertinoIcons.xmark, size: 16, ), ), ), ], ), Padding( padding: const EdgeInsets.all(16.0), child: CircleIconBtn( size: 86, icon: Assets.icon.outline.coin, color: AppColors.secondryColor[50], iconColor: AppColors.secondryColor.defaultShade, iconPadding: const EdgeInsets.all(12), ), ), Text( 'بسته اعتبار هدیه', style: AppTextStyles.headline6, textAlign: TextAlign.center, ), const SizedBox( height: 4, ), Text( '100 / 100', style: AppTextStyles.body4.copyWith(fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), Padding( padding: const EdgeInsets.symmetric( horizontal: 32.0, vertical: 16), child: LoadingButton( radius: 32, color: AppColors.primaryColor.defaultShade, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('مشاهده همه بسته‌ها', style: AppTextStyles.body4 .copyWith(color: Colors.white)), const SizedBox( width: 8, ), Assets.icon.outline.crown.svg(color: Colors.white), ], ), onPressed: () { onConfirm?.call(); context.pop(); }, ), ), ], ), ), ); }, ); } */ Future showPurchStatus( {required final bool success, required final String detail}) async { final color = success ? AppColors.green.defaultShade : AppColors.red.defaultShade; await showDialog( context: context, builder: (context) => Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 94, height: 94, padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: success ? AppColors.green[50] : AppColors.red[50], shape: BoxShape.circle), child: Icon( success ? CupertinoIcons.check_mark : CupertinoIcons.xmark, size: 80, color: Colors.white, ), ), const SizedBox( height: 8, ), Text( 'پرداخت ${success ? 'موفق' : 'ناموفق'}', style: AppTextStyles.body3 .copyWith(fontWeight: FontWeight.bold, color: color), ), Column( children: [ const SizedBox( height: 8, ), Text( detail, style: AppTextStyles.body4, textAlign: TextAlign.center, textDirection: TextDirection.rtl, ), ], ), const SizedBox( height: 16, ), ], ), ), ), ), ); } Future showCustomeReport() async { await showDialog( context: context, builder: (context) => Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(16.0), child: Directionality( textDirection: TextDirection.rtl, child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( title: Text( 'گزارش اشکال', style: AppTextStyles.body2.copyWith( color: Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.bold), ), ), const SizedBox( height: 12, ), const AuthTextField( label: 'لطفاً توضیح دهید', minLines: 6, maxLines: 6, ), const SizedBox( height: 32, ), Row( children: [ Expanded( child: LoadingButton( width: double.infinity, onPressed: () { context.pop(); }, child: Text( 'بازگشت', style: AppTextStyles.body4.copyWith( fontWeight: FontWeight.bold, color: Colors.white), ))), const SizedBox( width: 24, ), Expanded( child: LoadingButton( width: double.infinity, onPressed: () { context.pop(); context.pop(); SnackBarManager(context, id: 'report-success') .show( status: SnackBarStatus.success, message: 'گزارش با موفقیت ارسال شد'); }, isOutlined: true, color: Theme.of(context).colorScheme.primary, backgroundColor: Theme.of(context).dialogTheme.backgroundColor, child: Text( 'گزارش', style: AppTextStyles.body4.copyWith( fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary), ))), ], ) ], ), ), ), ), ), ); } Future showShamsiYearMonthPicker( {required Jalali initailDate, required dynamic Function(Jalali selectedDate) onDateSelected}) async { await showDialog( context: context, builder: (context) => Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(16.0), child: ShamsiYearMonthPicker( onDateSelected: onDateSelected, initailDate: initailDate, ), ), ), ), ); } Future showPrivateBots() async { await showDialog( context: context, builder: (context) => Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (context, maxWidth) => Center( child: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.sizeOf(context).height * 0.5), child: Dialog( backgroundColor: Theme.of(context).scaffoldBackgroundColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(16.0), child: Directionality( textDirection: TextDirection.rtl, child: BlocBuilder( builder: (context, state) { if (state is BotsFail) { return const SizedBox.shrink(); } if (state is BotsSuccess) { final privateBots = state.privateBots; if (privateBots.isEmpty) return const SizedBox.shrink(); return Scrollbar( thumbVisibility: true, interactive: true, child: SingleChildScrollView( physics: const BouncingScrollPhysics(), child: Column( children: [ ListTile( title: Text( 'مدل‌های حرفه‌ای', style: AppTextStyles.body3 .copyWith(fontWeight: FontWeight.bold), ), leading: Assets.icon.outline.crown.svg( color: Theme.of(context) .colorScheme .onSurface), ), ListView.builder( itemCount: privateBots.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.symmetric( horizontal: 16), itemBuilder: (context, index) { final bot = privateBots[index]; return InkWell( onTap: () { context.push(Routes.chat, extra: ChatArgs(bot: bot)); }, child: Container( padding: const EdgeInsets.symmetric( vertical: 8), decoration: BoxDecoration( border: index != privateBots.length - 1 ? Border( bottom: BorderSide( color: AppColors .gray[context .read< ThemeModeCubit>() .isDark() ? 600 : 900])) : null), child: Row( children: [ ImageNetwork( url: bot.image, width: 32, height: 32, radius: 360, color: bot.image != null && bot.image! .contains('/llm') ? Theme.of(context) .colorScheme .onSurface : null, fit: BoxFit.cover, ), const SizedBox( width: 8, ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( bot.name ?? '', maxLines: 1, overflow: TextOverflow.ellipsis, style: AppTextStyles.body4 .copyWith( color: Theme.of(context) .colorScheme .onSurface, fontWeight: FontWeight.bold), ), if (bot.description != null) Text(bot.description!, style: AppTextStyles.body5 .copyWith( color: AppColors .gray[context .read< ThemeModeCubit>() .isDark() ? 600 : 900])) ], )), const SizedBox( width: 8, ), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Theme.of(context) .colorScheme .primary, borderRadius: BorderRadius.circular( 16)), child: Center( child: Text( bot.cost == 0 || bot.cost == null ? 'رایگان' : '${bot.cost} سکه', style: AppTextStyles.body6 .copyWith( color: Colors.white), ), ), ) ], ), ), ); }, ), ], ), ), ); } return Column( children: [ DefaultPlaceHolder( child: ListTile( title: Text( 'مدل‌های هوش مصنوعی حرفه‌ای', style: AppTextStyles.body4.copyWith( fontWeight: FontWeight.bold, color: Theme.of(context) .colorScheme .onSurface), ), leading: Assets.icon.outline.crown.svg( color: Theme.of(context).colorScheme.onSurface), ), ), ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: 10, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, index) { return DefaultPlaceHolder( child: Container( height: 32, margin: const EdgeInsets.symmetric(vertical: 8), decoration: const BoxDecoration(color: Colors.white), )); }, ), const SizedBox( height: 16, ) ], ); }, ), ), ), ), ), ), ), ); } void onMusicCreate({ final Function()? onConfirm, final Function()? onCancel, }) async { // Disabled by request: do nothing return; } void onVideoCreate({ final Function()? onConfirm, final Function()? onCancel, }) async { // Disabled by request: do nothing return; } void onPhotoCreated({ final Function()? onConfirm, final Function()? onCancel, }) async { // Disabled by request: do nothing return; } void conditionsForCmp({required final String awards}) async { await showDialog( context: context, builder: (context) => Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ Directionality( textDirection: TextDirection.rtl, child: ListTile( contentPadding: EdgeInsets.zero, title: Text( '📑 شرایط شرکت در مسابقه', style: AppTextStyles.headline6.copyWith( color: Theme.of(context).colorScheme.onSurface), ), ), ), const SizedBox( height: 16, ), Scrollbar( thumbVisibility: true, trackVisibility: true, interactive: true, child: Directionality( textDirection: TextDirection.rtl, child: Container( margin: const EdgeInsets.only(right: 8), constraints: BoxConstraints( maxHeight: MediaQuery.sizeOf(context).height * 0.4), child: SingleChildScrollView( physics: BouncingScrollPhysics(), child: Html( data: awards, shrinkWrap: true, onLinkTap: (url, attributes, element) async { try { await launchUrl(Uri.parse(url!), mode: LaunchMode.externalApplication) .onError( (error, stackTrace) { if (kDebugMode) { print('error open Link is: $error'); } return false; }, ); } catch (e) { if (kDebugMode) { print(e); } } }, style: { 'p': Style( fontFamily: AppTextStyles.defaultFontFamily, color: Theme.of(context).colorScheme.onSurface, fontSize: FontSize(16)) }), ), ), ), ), const SizedBox( height: 16, ), LoadingButton( width: double.infinity, onPressed: () { contxet.pop(); }, color: Theme.of(context).colorScheme.primary, child: Text( 'بازگشت', style: AppTextStyles.body4.copyWith(color: Colors.white), )) ], ), ), ), ), ); } void rewardForCmp({required final String rewards}) async { await showDialog( context: context, builder: (context) => Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ Directionality( textDirection: TextDirection.rtl, child: ListTile( contentPadding: EdgeInsets.zero, title: Text( '🏆 جوایز مسابقه', style: AppTextStyles.headline6.copyWith( color: Theme.of(context).colorScheme.onSurface), ), ), ), const SizedBox( height: 16, ), Scrollbar( thumbVisibility: true, trackVisibility: true, interactive: true, child: Directionality( textDirection: TextDirection.rtl, child: Container( margin: const EdgeInsets.only(right: 8), constraints: BoxConstraints( maxHeight: MediaQuery.sizeOf(context).height * 0.4), child: SingleChildScrollView( physics: BouncingScrollPhysics(), child: Html( data: rewards, shrinkWrap: true, onLinkTap: (url, attributes, element) async { try { await launchUrl(Uri.parse(url!), mode: LaunchMode.externalApplication) .onError( (error, stackTrace) { if (kDebugMode) { print('error open Link is: $error'); } return false; }, ); } catch (e) { if (kDebugMode) { print(e); } } }, style: { 'p': Style( fontFamily: AppTextStyles.defaultFontFamily, color: Theme.of(context).colorScheme.onSurface, fontSize: FontSize(16)), }), ), ), )), const SizedBox( height: 16, ), LoadingButton( width: double.infinity, onPressed: () { contxet.pop(); }, color: Theme.of(context).colorScheme.primary, child: Text( 'بازگشت', style: AppTextStyles.body4.copyWith(color: Colors.white), )) ], ), ), ), ), ); } void winnersForCmp({required final List winners}) async { await showDialog( context: context, builder: (context) => Responsive(context).maxWidthInDesktop( maxWidth: maxDialogWidthInDesktop, child: (contxet, maxWidth) => Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(16.0), child: Directionality( textDirection: TextDirection.rtl, child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( contentPadding: EdgeInsets.zero, title: Text( '✌️ نفرات برتر مسابقه', style: AppTextStyles.headline6.copyWith( color: Theme.of(context).colorScheme.onSurface), ), ), const SizedBox( height: 16, ), ListView.builder( itemCount: winners.length, shrinkWrap: true, itemBuilder: (context, index) { final winner = winners[index]; return ListTile( leading: const CircleAvatar(), title: Text('${winner.rank ?? 1}', style: AppTextStyles.body3.copyWith( color: Theme.of(context).colorScheme.onSurface, )), subtitle: Text.rich( TextSpan(text: winner.username ?? '', children: [ TextSpan( text: 'مشاهده اثر', style: TextStyle( color: Theme.of(context).colorScheme.primary)) ]), style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.onSurface), ), ); }, ), const SizedBox( height: 16, ), LoadingButton( width: double.infinity, onPressed: () { contxet.pop(); }, color: Theme.of(context).colorScheme.primary, child: Text( 'بازگشت', style: AppTextStyles.body4.copyWith(color: Colors.white), )) ], ), ), ), ), ), ); } Future updateAlert( {required final String message, required final bool force, required final String version}) async { final versionStyle = AppTextStyles.body4.copyWith( fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.onSurface); await showAlertDialog( barrierDismissible: !force, imageGif: Assets.icon.gif.waveHand.image(), title: 'به روزرسانی هوشان', onConfirmText: 'به روزرسانی', onCancelText: force ? '' : '!الان نه', onCancel: force ? null : (c) => context.pop(), onConfirm: (c) async { await launchUrl(Uri.parse('https://api.houshan.ai/apk'), mode: LaunchMode.externalApplication) .onError( (error, stackTrace) { if (kDebugMode) { print('error open Link is: $error'); } return false; }, ); }, child: Column( children: [ SizedBox( height: 8, ), Text(message, textDirection: TextDirection.rtl, textAlign: TextAlign.justify, style: AppTextStyles.body4 .copyWith(color: Theme.of(context).colorScheme.onSurface)), SizedBox( height: 16, ), Row( children: [ Expanded( child: Center( child: FutureBuilder( future: PackageInfo.fromPlatform(), builder: (context, snapshot) { String version = '...'; if (snapshot.hasData && snapshot.data != null) { version = snapshot.data!.version; } return Text(version, style: versionStyle); }), )), Text('>>>', style: versionStyle), Expanded( child: Center( child: Text(version, style: versionStyle), )), ], ) ], )); } }