didvan-app/lib/views/ai/history_ai_chat_page.dart

544 lines
26 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ignore_for_file: library_private_types_in_public_api, deprecated_member_use
import 'dart:async';
import 'package:cached_network_image/cached_network_image.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/models/view/app_bar_data.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/utils/date_time.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/widgets/didvan/scaffold.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/search_field.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: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<HistoryAiChatPage> {
final ScrollController scrollController = ScrollController();
Timer? _timer;
late bool archived = widget.archived ?? false;
@override
void initState() {
final state = context.read<HistoryAiChatState>();
Future.delayed(
Duration.zero,
() => state.getChats(archived: archived),
);
super.initState();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (context.read<HistoryAiChatState>().refresh) {
context.read<HistoryAiChatState>().getChats();
context.read<HistoryAiChatState>().refresh = false;
}
return true;
},
child: DidvanScaffold(
hidePlayer: true,
physics: const BouncingScrollPhysics(),
// floatingActionButton: openAiListBtn(context),
padding: EdgeInsets.zero,
scrollController: scrollController,
showSliversFirst: false,
slivers: [
SliverAppBar(
backgroundColor: Theme.of(context).colorScheme.surface,
scrolledUnderElevation: 0,
automaticallyImplyLeading: false,
pinned: true,
flexibleSpace: Container(
color: Theme.of(context).colorScheme.surface,
padding: const EdgeInsets.only(right: 20, left: 20, bottom: 24),
child: SearchField(
title: 'گفت‌و‌گو‌ها',
onChanged: (value) {
final state = context.read<HistoryAiChatState>();
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()),
),
),
Consumer<HistoryAiChatState>(
builder: (context, state, child) {
return SliverStateHandler(
state: state,
emptyState: EmptyState(
asset: Assets.emptyResult,
title: 'لیست خالی است',
),
enableEmptyState: archived
? state.archivedChats.isEmpty
: state.chats.isEmpty,
placeholder: const _HistoryPlaceholder(),
placeholderCount: 8,
// builder: (context, state, index) => _HistoryPlaceholder(),
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<HistoryAiChatState>();
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),
children: [
TextSpan(
text: "\"${chat.title}\"",
style: const TextStyle(
fontWeight:
FontWeight.bold)),
const TextSpan(
text:
' با هوشان اطمینان دارید؟ '),
]),
),
),
],
)));
} else {
result = await state.archivedChat(chat.id!, index,
archived: archived);
}
return result;
},
child: InkWell(
onTap: () {
// if (state.chatsToDelete.isEmpty) {
navigatorKey.currentState!.pushNamed(Routes.aiChat,
arguments:
AiChatArgs(bot: chat.bot!, chat: chat));
// } else {
// if (state.chatsToDelete.contains(chat.id)) {
// state.chatsToDelete.remove(chat.id!);
// } else {
// state.chatsToDelete.add(chat.id!);
// }
// }
// state.update();
},
onLongPress: () {
if (archived) {
state.archivedChats[index] = state
.archivedChats[index]
.copyWith(isEditing: true);
} else {
state.chats[index] =
state.chats[index].copyWith(isEditing: true);
}
state.update();
// if (state.chatsToDelete.isEmpty) {
// state.chatsToDelete.add(chat.id!);
// }
// 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: [
SizedBox(
width: 46,
height: 46,
child: ClipOval(
child: CachedNetworkImage(
imageUrl: chat.bot!.image.toString(),
),
),
),
const SizedBox(
width: 18,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
DidvanText(
chat.bot!.name.toString(),
fontWeight: FontWeight.bold,
// fontSize: 18,
),
DidvanText(
DateTimeUtils.momentGenerator(
chat.updatedAt.toString()),
style:
const TextStyle(fontSize: 12)),
],
),
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),
)
],
)
: DidvanText(
chat.title.toString(),
maxLines: 1,
overflow:
TextOverflow.ellipsis,
// fontWeight: FontWeight.bold,
// fontSize: 16,
),
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));
},
)
],
appBarData: AppBarData(
title: archived ? 'آرشیو‌ها' : 'تاریخچه گفت‌وگوها',
hasBack: true,
hasElevation: true,
backClick: () {
if (context.read<HistoryAiChatState>().refresh) {
context.read<HistoryAiChatState>().getChats();
context.read<HistoryAiChatState>().refresh = false;
}
},
isSmall: false,
trailing: archived
? null
: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: InkWell(
onTap: () async {
await ActionSheetUtils(context).openDialog(
data: ActionSheetData(
onConfirmed: () async {
final state =
context.read<HistoryAiChatState>();
archived ? null : await state.deleteAllChat();
},
content: Column(
children: [
Row(
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Icon(
DidvanIcons.trash_solid,
color: Theme.of(context)
.colorScheme
.error,
),
const SizedBox(
width: 8,
),
DidvanText(
archived
? 'خارج کردن همه آرشیو ها'
: 'پاک کردن همه گفت‌وگوها',
color: Theme.of(context)
.colorScheme
.error,
fontSize: 20,
),
],
),
const SizedBox(
height: 12,
),
const DidvanText(
'آیا از پاک کردن تمامی گفت‌وگوهای انجام شده با هوشان اطمینان دارید؟'),
],
)));
},
child: DidvanText(
archived ? 'خارج کردن همه' : 'حذف همه',
color: Theme.of(context).colorScheme.error,
),
),
)),
),
);
}
// Widget openAiListBtn(BuildContext context) {
// final watch = context.watch<HistoryAiChatState>();
// final state = context.read<HistoryAiChatState>();
// return FloatingActionButton(
// backgroundColor: watch.chatsToDelete.isEmpty
// ? Theme.of(context).colorScheme.primary
// : Theme.of(context).colorScheme.error,
// shape: const OvalBorder(),
// mini: true,
// onPressed: () {
// if (watch.chatsToDelete.isEmpty) {
// state.getBots();
// state.search = '';
// _botsDialogSelect(context);
// } else {
// state.addChatToDelete();
// }
// },
// child: watch.chatsToDelete.isEmpty
// ? const Icon(DidvanIcons.add_regular)
// : const Icon(DidvanIcons.trash_regular),
// );
// }
}
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,
),
],
),
),
],
),
);
}
}