// ignore_for_file: library_private_types_in_public_api, deprecated_member_use import 'dart:async'; import 'package:didvan/config/design_config.dart'; import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/constants/assets.dart'; import 'package:didvan/main.dart'; import 'package:didvan/models/ai/ai_chat_args.dart'; import 'package:didvan/models/view/action_sheet_data.dart'; import 'package:didvan/routes/routes.dart'; import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/views/ai/history_ai_chat_state.dart'; import 'package:didvan/views/ai/widgets/hoshan_drawer.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/hoshan_app_bar.dart'; import 'package:didvan/views/widgets/shimmer_placeholder.dart'; import 'package:didvan/views/widgets/state_handlers/empty_state.dart'; import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:provider/provider.dart'; class HistoryAiChatPage extends StatefulWidget { final bool? archived; const HistoryAiChatPage({Key? key, required this.archived}) : super(key: key); @override _HistoryAiChatPageState createState() => _HistoryAiChatPageState(); } class _HistoryAiChatPageState extends State { final ScrollController scrollController = ScrollController(); final GlobalKey scaffKey = GlobalKey(); Timer? _timer; late bool archived = widget.archived ?? false; @override void initState() { final state = context.read(); Future.delayed( Duration.zero, () => state.getChats(archived: archived), ); super.initState(); } @override Widget build(BuildContext context) { final theme = Theme.of(context); return WillPopScope( onWillPop: () async { if (context.read().refresh) { context.read().getChats(); context.read().refresh = false; } return true; }, child: Scaffold( key: scaffKey, appBar: HoshanAppBar( onBack: () { if (context.read().refresh) { context.read().getChats(); context.read().refresh = false; } Navigator.pop(context); }, withActions: false, withInfo: true, ), drawer: HoshanDrawer( scaffKey: scaffKey, ), body: CustomScrollView( physics: const BouncingScrollPhysics(), controller: scrollController, slivers: [ SliverAppBar( backgroundColor: Theme.of(context).colorScheme.surface, scrolledUnderElevation: 0, automaticallyImplyLeading: false, pinned: true, toolbarHeight: archived ? 50 : 110, flexibleSpace: Container( color: Theme.of(context).colorScheme.surface, padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), child: Column( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Text('فهرست آرشیوشده‌ها', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: DesignConfig.isDark ? const Color.fromARGB(255, 0, 90, 119) : const Color.fromARGB(255, 0, 53, 70))), ), // SearchField( // title: 'گفت‌و‌گو‌ها', // onChanged: (value) { // final state = context.read(); // if (value.isEmpty) { // state.getChats(archived: archived); // return; // } // _timer?.cancel(); // _timer = Timer(const Duration(seconds: 1), () { // state.search = value; // state.getSearchChats(q: value, archived: archived); // }); // }, // focusNode: FocusNode(), // ), if (!archived) Padding( padding: const EdgeInsets.only(top: 0.0), child: InkWell( onTap: () { Navigator.of(context) .pushNamed(Routes.aiArchivedHistory); }, child: Row( children: [ Icon( DidvanIcons.ai_regular, size: 18, color: theme.colorScheme.primary, ), const SizedBox(width: 8), DidvanText( 'گفت‌وگوهای آرشیو شده', style: TextStyle( color: theme.colorScheme.primary, fontWeight: FontWeight.bold, fontSize: 14, ), ), ], ), ), ), ], ), ), ), Consumer( builder: (context, state, child) { return SliverStateHandler( paddingEmptyState: 0, state: state, centerEmptyState: false, emptyState: EmptyState( asset: Assets.emptyResult, height: 400, title: 'لیست خالی است', titleColor: const Color.fromARGB(255, 2, 126, 167), subtitle: 'در حال حاضر آیتمی در این بخش ثبت نشده است. هر زمان مورد جدیدی اضافه شود، در اینجا نمایش داده می‌شود.', ), enableEmptyState: archived ? state.archivedChats.isEmpty : state.chats.isEmpty, placeholder: const _HistoryPlaceholder(), placeholderCount: 8, builder: (context, state, index) { final chat = archived ? state.archivedChats[index] : state.chats[index]; TextEditingController title = TextEditingController(text: chat.title); return Dismissible( key: UniqueKey(), background: Container( color: Theme.of(context).colorScheme.error, alignment: Alignment.centerRight, padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Icon( DidvanIcons.trash_solid, color: Theme.of(context).colorScheme.white, ), ), secondaryBackground: Container( color: Theme.of(context).colorScheme.primary, alignment: Alignment.centerLeft, padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Icon( archived ? Icons.folder_delete : Icons.create_new_folder_rounded, color: Theme.of(context).colorScheme.white), ), movementDuration: const Duration(milliseconds: 600), confirmDismiss: (direction) async { bool result = false; if (direction == DismissDirection.startToEnd) { await ActionSheetUtils(context).openDialog( data: ActionSheetData( onConfirmed: () async { final state = context.read(); await state.deleteChat(chat.id!, index, archived: archived); result = true; }, content: Column( children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Icon( DidvanIcons.trash_solid, color: Theme.of(context) .colorScheme .error, ), const SizedBox( width: 8, ), SizedBox( child: DidvanText( 'پاک کردن گفت‌و‌گو', color: Theme.of(context) .colorScheme .error, fontSize: 20, ), ), ], ), const SizedBox( height: 12, ), SizedBox( child: RichText( text: TextSpan( text: 'آیا از پاک کردن گفت‌و‌گوی ', style: TextStyle( color: Theme.of(context) .colorScheme .text, fontFamily: DesignConfig .fontFamily), children: [ TextSpan( text: "\"${chat.title}\"", style: TextStyle( fontFamily: DesignConfig .fontFamily, fontWeight: FontWeight.bold)), TextSpan( style: TextStyle( fontFamily: DesignConfig .fontFamily), text: ' با هوشان اطمینان دارید؟ '), ]), ), ), ], ))); } else { result = await state.archivedChat(chat.id!, index, archived: archived); } return result; }, child: InkWell( onTap: () { if (chat.bot != null) { navigatorKey.currentState!.pushNamed( Routes.aiChat, arguments: AiChatArgs( bot: chat.bot!, chat: chat, assistantsName: chat.assistantsName)); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('امکان باز کردن این چت وجود ندارد.'), ), ); } }, onLongPress: () { if (archived) { state.archivedChats[index] = state .archivedChats[index] .copyWith(isEditing: true); } else { state.chats[index] = state.chats[index].copyWith(isEditing: true); } state.update(); }, child: Container( padding: const EdgeInsets.symmetric( vertical: 12, horizontal: 20), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Theme.of(context).colorScheme.border, ))), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ // SkeletonImage( // imageUrl: chat.bot!.image.toString(), // width: 46, // height: 46, // borderRadius: BorderRadius.circular(360), // ), // const SizedBox( // width: 18, // ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Row( // mainAxisAlignment: // MainAxisAlignment.spaceBetween, // children: [ // // DidvanText( // // chat.assistantsName ?? // // chat.bot!.name.toString(), // // fontWeight: FontWeight.bold, // // ), // ], // ), SizedBox( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ chat.isEditing != null && chat.isEditing! ? Row( children: [ Expanded( child: TextFormField( controller: title, style: const TextStyle( fontSize: 12), textAlignVertical: TextAlignVertical .bottom, maxLines: 1, decoration: const InputDecoration( isDense: true, contentPadding: EdgeInsets.symmetric( vertical: 5, horizontal: 10), border: OutlineInputBorder(), )), ), const SizedBox( width: 12, ), state.loadingchangeTitle ? const SizedBox( width: 12, height: 12, child: CircularProgressIndicator()) : InkWell( onTap: () async { if (title.text .toString() == chat.title .toString()) { chat.isEditing = false; state .update(); return; } if (title.text .isNotEmpty) { await state.changeNameChat( chat.id!, index, title .text); title.clear(); } if (chat.isEditing != null) { chat.isEditing = !chat .isEditing!; state .update(); return; } chat.isEditing = true; state.update(); }, child: const Icon( DidvanIcons .check_circle_solid), ) ], ) : Row( mainAxisAlignment: MainAxisAlignment .spaceBetween, children: [ Expanded( child: Column( mainAxisAlignment: MainAxisAlignment .start, crossAxisAlignment: CrossAxisAlignment .start, children: [ DidvanText( chat.title .toString(), maxLines: 1, overflow: TextOverflow .ellipsis, ), DidvanText( DateTime.parse(chat .updatedAt .toString()) .toPersianDateStr( monthString: ''), style: const TextStyle( fontSize: 12)), ], ), ), const SizedBox( width: 10, ), PopupMenuButton( icon: SvgPicture.asset( 'lib/assets/icons/more.svg'), shape: const RoundedRectangleBorder( borderRadius: BorderRadius .only( topRight: Radius.circular( 16), topLeft: Radius.circular( 0), bottomLeft: Radius.circular( 16), bottomRight: Radius.circular( 16), )), color: const Color .fromARGB( 255, 246, 246, 246), padding: EdgeInsets.zero, borderRadius: const BorderRadius .only( topRight: Radius.circular( 16), topLeft: Radius.circular( 0), bottomLeft: Radius.circular( 16), bottomRight: Radius.circular( 16), ), onSelected: (value) async { switch (value) { case 'حذف پیام': await state .deleteChat( chat.id!, index, archived: archived); break; case 'آرشیو': case 'خارج کردن از آرشیو': await state .archivedChat( chat.id!, index, archived: archived); break; default: } }, itemBuilder: (BuildContext context) => >[ PopupMenuItem( value: 'خارج کردن از آرشیو', padding: const EdgeInsets .symmetric( horizontal: 20, vertical: 12), child: SizedBox( width: 180, child: Column( children: [ Row( children: [ SvgPicture .asset( 'lib/assets/icons/direct-send.svg', height: 20, ), const SizedBox( width: 16), const Text( 'خارج کردن از آرشیو', style: TextStyle( fontSize: 13, color: Color.fromARGB( 255, 61, 61, 61)), ), ], ), const SizedBox( height: 20), const Divider( height: 1, color: Color .fromARGB( 255, 227, 226, 225), ) ], ), ), ), PopupMenuItem( value: 'حذف پیام', padding: const EdgeInsets .symmetric( horizontal: 20, vertical: 12), child: SizedBox( width: 180, child: Column( children: [ Row( children: [ SvgPicture .asset( 'lib/assets/icons/trash.svg', height: 20, color: const Color .fromARGB( 255, 0, 126, 167), ), const SizedBox( width: 16), const Text( 'پاک کردن', style: TextStyle( fontSize: 13, color: Color.fromARGB(255, 61, 61, 61))), ], ), ], ), ), ), ], ), // if (chat.prompts != null && // chat.prompts!.isNotEmpty && // chat.prompts![0].text != null) // DidvanText( // chat.prompts![0].text // .toString(), // maxLines: 1, // overflow: TextOverflow.ellipsis, // fontSize: 12, // ), ], ), ])) ], ), ), ], ), ), ), ); }, childCount: archived ? state.archivedChats.length : state.chats.length, onRetry: () => state.getChats(archived: archived)); }, ) ], ), ), ); } } class _HistoryPlaceholder extends StatelessWidget { const _HistoryPlaceholder({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const Padding( padding: EdgeInsets.symmetric(vertical: 18.0, horizontal: 20), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ ClipOval( child: ShimmerPlaceholder( height: 46, width: 46, ), ), SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ShimmerPlaceholder( height: 20, width: 100, ), ShimmerPlaceholder( height: 14, width: 100, ), ], ), SizedBox(height: 12), ShimmerPlaceholder( height: 16, width: double.infinity, ), SizedBox(height: 8), ShimmerPlaceholder( height: 16, width: double.infinity, ), ], ), ), ], ), ); } }