didvan-app/lib/views/ai/widgets/hoshan_drawer.dart

434 lines
17 KiB
Dart

import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/main.dart';
import 'package:didvan/models/ai/ai_chat_args.dart';
import 'package:didvan/models/ai/chats_model.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/alert_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/widgets/didvan/divider.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/shimmer_placeholder.dart';
import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:didvan/views/widgets/state_handlers/empty_list.dart';
import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class HoshanDrawer extends StatefulWidget {
final GlobalKey<ScaffoldState>? scaffKey;
const HoshanDrawer({Key? key, this.scaffKey}) : super(key: key);
@override
State<HoshanDrawer> createState() => _HoshanDrawerState();
}
class _HoshanDrawerState extends State<HoshanDrawer> {
@override
initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Drawer(
child: Consumer<HistoryAiChatState>(
builder: (context, state, child) {
return Column(
children: [
const SizedBox(
height: 8,
),
Padding(
padding: const EdgeInsets.only(left: 20.0, top: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
InkWell(
onTap: () => widget.scaffKey?.currentState?.closeDrawer(),
child: const Icon(
DidvanIcons.close_regular,
),
)
],
),
),
Icon(
DidvanIcons.ai_solid,
size: MediaQuery.sizeOf(context).width / 5,
color: Theme.of(context).colorScheme.title,
),
DidvanText(
'هوشان',
color: Theme.of(context).colorScheme.title,
),
const SizedBox(
height: 24,
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
children: [
const DidvanDivider(),
drawerBtn(
icon: DidvanIcons.chats_regular,
text: 'تاریخچه همه گفتگوها',
label: 'حذف همه',
click: () {
Navigator.of(context)
.pushNamed(Routes.aiHistory);
},
labelClick: state.chats.isEmpty
? null
: () async {
await ActionSheetUtils(context)
.openDialog(
data: ActionSheetData(
onConfirmed: () async {
await state.deleteAllChat(
refresh: false);
},
content: Column(
children: [
Row(
crossAxisAlignment:
CrossAxisAlignment
.center,
children: [
Icon(
DidvanIcons
.trash_solid,
color: Theme.of(
context)
.colorScheme
.error,
),
const SizedBox(
width: 8,
),
DidvanText(
'پاک کردن همه گفت‌وگوها',
color: Theme.of(
context)
.colorScheme
.error,
fontSize: 20,
),
],
),
const SizedBox(
height: 12,
),
const DidvanText(
'آیا از پاک کردن تمامی گفت‌وگوهای انجام شده با هوشان اطمینان دارید؟'),
],
)));
},
),
const SizedBox(
height: 12,
),
Expanded(
child: CustomScrollView(
slivers: [
SliverStateHandler(
state: state,
centerEmptyState: false,
emptyState: const EmptyList(),
placeholder: chatRowPlaceholder(),
placeholderCount: 10,
builder: (context, state, index) {
final chat = state.chats[index];
TextEditingController title =
TextEditingController(
text: chat.title);
return chatRow(chat, title, state, index);
},
childCount: state.chats.length,
onRetry: () => state.getChats())
],
)),
],
),
),
Column(
children: [
const DidvanDivider(),
drawerBtn(
icon: Icons.folder_copy_outlined,
text: 'گفت‌وگوهای آرشیو شده',
click: () {
Navigator.of(context)
.pushNamed(Routes.aiHistory, arguments: true);
},
),
const SizedBox(
height: 12,
),
drawerBtn(
icon: DidvanIcons.support_regular,
text: 'پیام به پشتیبانی',
click: () {
Navigator.of(context).pushNamed(
Routes.direct,
arguments: {'type': 'پشتیبانی اپلیکیشن'},
);
},
),
],
)
],
),
),
),
const SizedBox(
height: 32,
)
],
);
},
),
);
}
Padding chatRowPlaceholder() {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 12.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipOval(
child: ShimmerPlaceholder(
height: 24,
width: 24,
),
),
SizedBox(width: 12),
Expanded(
child: ShimmerPlaceholder(
height: 24,
),
),
SizedBox(width: 12),
ShimmerPlaceholder(
height: 24,
width: 24,
),
SizedBox(width: 8),
ShimmerPlaceholder(
height: 24,
width: 12,
),
],
),
);
}
Widget drawerBtn(
{final CrossAxisAlignment? crossAxisAlignment,
required final IconData icon,
required final String text,
final bool enable = true,
final String? label,
final Function()? labelClick,
final Function()? click}) {
return InkWell(
onTap: enable
? click
: () {
ActionSheetUtils(context).showAlert(
AlertData(message: 'درحال توسعه', aLertType: ALertType.info));
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
crossAxisAlignment:
crossAxisAlignment ?? CrossAxisAlignment.center,
children: [
Icon(
icon,
color: enable
? Theme.of(context).colorScheme.title
: Theme.of(context).colorScheme.disabledText,
),
const SizedBox(
width: 8,
),
Column(
children: [
DidvanText(text,
fontSize: 16,
color: enable
? Theme.of(context).colorScheme.title
: Theme.of(context).colorScheme.disabledText),
],
)
],
),
if (label != null)
InkWell(
onTap: labelClick,
child: DidvanText(
label,
color: Theme.of(context).colorScheme.primary,
fontSize: 12,
),
)
],
),
),
);
}
Padding chatRow(ChatsModel chat, TextEditingController title,
HistoryAiChatState state, int index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
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('امکان باز کردن این چت وجود ندارد.'),
),
);
}
},
child: Row(
children: [
SkeletonImage(
imageUrl: chat.bot!.image.toString(),
width: 24,
height: 24,
borderRadius: BorderRadius.circular(360),
),
const SizedBox(
width: 12,
),
Expanded(
child: Text(
chat.title.toString(),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
const SizedBox(
width: 24,
),
Row(
children: [
InkWell(
onTap: () async {
ActionSheetUtils(context).openDialog(
data: ActionSheetData(
content: Center(
child: TextFormField(
controller: title,
style: const TextStyle(fontSize: 12),
textAlignVertical: TextAlignVertical.bottom,
maxLines: 3,
decoration: const InputDecoration(
isDense: true,
contentPadding: EdgeInsets.symmetric(
vertical: 5, horizontal: 10),
border: OutlineInputBorder(),
)),
),
title: 'تغییر نام',
onConfirmed: () async {
if (title.text.isNotEmpty) {
await state.changeNameChat(
chat.id!, index, title.text,
refresh: false);
title.clear();
}
if (chat.isEditing != null) {
chat.isEditing = !chat.isEditing!;
state.update();
return;
}
state.update();
},
));
},
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.edit_outlined,
size: 20,
),
),
),
const SizedBox(
width: 4,
),
PopupMenuButton(
onSelected: (value) async {
switch (value) {
case 'حذف پیام':
await state.deleteChat(chat.id!, index, refresh: false);
break;
case 'آرشیو':
await state.archivedChat(chat.id!, index,
refresh: false);
break;
default:
}
state.update();
},
itemBuilder: (BuildContext context) {
return <PopupMenuEntry>[
ActionSheetUtils.popUpBtns(
value: 'حذف پیام',
icon: DidvanIcons.trash_regular,
color: Theme.of(context).colorScheme.error,
height: 32,
size: 16),
ActionSheetUtils.popUpBtns(
value: 'آرشیو',
icon: Icons.folder_copy,
height: 32,
size: 16,
),
];
},
offset: const Offset(0, 0),
position: PopupMenuPosition.under,
useRootNavigator: true,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.more_vert,
size: 20,
),
),
),
],
)
],
),
),
);
}
}