"Updated BotAssistantsReqModel, RequestHelper, AiChatState, BotAssistantsPage, CreateBotAssistantsPage, and CreateBotAssistantsState with various changes to fields, methods, and UI components."

This commit is contained in:
OkaykOrhmn 2024-11-17 12:07:40 +03:30
parent dfd57937fb
commit a2c8b5ddac
6 changed files with 323 additions and 269 deletions

View File

@ -11,6 +11,7 @@ class BotAssistantsReqModel {
final String? youtubeLink; final String? youtubeLink;
final List<String>? webLinks; final List<String>? webLinks;
final bool isPrivate; final bool isPrivate;
final bool? deleteImage;
BotAssistantsReqModel( BotAssistantsReqModel(
{required this.type, {required this.type,
@ -22,6 +23,7 @@ class BotAssistantsReqModel {
this.files, this.files,
this.youtubeLink, this.youtubeLink,
this.webLinks, this.webLinks,
this.deleteImage,
this.isPrivate = true}); this.isPrivate = true});
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -35,6 +37,9 @@ class BotAssistantsReqModel {
if (youtubeLink != null) { if (youtubeLink != null) {
data['youtubeLink'] = youtubeLink; data['youtubeLink'] = youtubeLink;
} }
if (deleteImage != null) {
data['deleteImage'] = deleteImage;
}
if (webLinks != null) { if (webLinks != null) {
data['webLinks'] = webLinks; data['webLinks'] = webLinks;
} }

View File

@ -231,14 +231,14 @@ class RequestHelper {
static String placeholder(int id) => '$baseUrl/ai/chat/$id/placeholder'; static String placeholder(int id) => '$baseUrl/ai/chat/$id/placeholder';
static String tools() => '$baseUrl/ai/tool'; static String tools() => '$baseUrl/ai/tool';
static String usersAssistants({final bool personal = false}) => static String usersAssistants({final bool personal = false}) =>
'$baseUrl/ai/bot/user${_urlConcatGenerator([ '$baseUrl/ai/user/bot${_urlConcatGenerator([
MapEntry('personal', personal), MapEntry('personal', personal),
])}'; ])}';
static String createAssistants() => '$baseUrl/ai/bot'; static String createAssistants() => '$baseUrl/ai/user/bot';
static String updateAssistants(int id) => '$baseUrl/ai/bot/$id'; static String updateAssistants(int id) => '$baseUrl/ai/user/bot/$id';
static String getAssistant(int id) => '$baseUrl/ai/bot/user/$id'; static String getAssistant(int id) => '$baseUrl/ai/user/bot/$id';
static String deleteAssistant(int id) => '$baseUrl/ai/bot/user/$id'; static String deleteAssistant(int id) => '$baseUrl/ai/user/bot/$id';
static String nameOfAssistant() => '$baseUrl/ai/bot/name'; static String nameOfAssistant() => '$baseUrl/ai/user/bot/name';
static String _urlConcatGenerator(List<MapEntry<String, dynamic>> additions) { static String _urlConcatGenerator(List<MapEntry<String, dynamic>> additions) {
String result = ''; String result = '';

View File

@ -157,7 +157,7 @@ class AiChatState extends CoreProvier {
// } // }
final req = await AiApiService.initial( final req = await AiApiService.initial(
url: '${isAssistants ? '/custom' : ''}/${bot.id}/${bot.name}' url: '${isAssistants ? '/user' : ''}/${bot.id}/${bot.name}'
.toLowerCase(), .toLowerCase(),
message: message, message: message,
chatId: chatId, chatId: chatId,

View File

@ -187,8 +187,10 @@ class _BotAssistantsPageState extends State<BotAssistantsPage> {
return Container( return Container(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 32), margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 32),
decoration: const BoxDecoration( decoration: BoxDecoration(
color: Colors.white, borderRadius: DesignConfig.lowBorderRadius), border: Border.all(color: const Color(0xffe0e0e0)),
color: Colors.white,
borderRadius: DesignConfig.lowBorderRadius),
child: Column( child: Column(
children: [ children: [
if (state.isMyAssistants) if (state.isMyAssistants)

View File

@ -14,6 +14,7 @@ import 'package:didvan/models/ai/bots_model.dart';
import 'package:didvan/models/ai/file_create_assistants_model.dart'; import 'package:didvan/models/ai/file_create_assistants_model.dart';
import 'package:didvan/models/enums.dart'; import 'package:didvan/models/enums.dart';
import 'package:didvan/models/view/action_sheet_data.dart'; import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/alert_data.dart';
import 'package:didvan/services/media/media.dart'; import 'package:didvan/services/media/media.dart';
import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/utils/extension.dart'; import 'package:didvan/utils/extension.dart';
@ -104,7 +105,8 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
resultFiles.add(file.file!); resultFiles.add(file.file!);
} }
} }
await state.createAssistants(
final success = await state.createAssistants(
id: widget.id, id: widget.id,
data: BotAssistantsReqModel( data: BotAssistantsReqModel(
type: selectedBotType, type: selectedBotType,
@ -116,11 +118,19 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
// youtubeLink: youtubeLink, // youtubeLink: youtubeLink,
isPrivate: isPrivate, isPrivate: isPrivate,
files: resultFiles, files: resultFiles,
deleteImage: assistant != null
? assistant!.image == null
: image.value == null,
image: image.value)); image: image.value));
if (success) {
context.read<BotAssistantsState>().getMyAssissmant(); context.read<BotAssistantsState>().getMyAssissmant();
context.read<CreateBotAssistantsState>().assistant = null; context.read<CreateBotAssistantsState>().assistant = null;
Navigator.pop(context); Navigator.pop(context);
} else {
ActionSheetUtils(context).showAlert(AlertData(
message: 'مشکلی در ارتباط با سرور پیش آمده دوباره تلاش کنید',
aLertType: ALertType.error));
}
} }
@override @override
@ -193,6 +203,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
child: CustomDropdown<String>( child: CustomDropdown<String>(
closedHeaderPadding: const EdgeInsets.all(12), closedHeaderPadding: const EdgeInsets.all(12),
items: botModels, items: botModels,
enabled: assistant == null,
initialItem: botModels[0], initialItem: botModels[0],
hideSelectedFieldWhenExpanded: false, hideSelectedFieldWhenExpanded: false,
decoration: CustomDropdownDecoration( decoration: CustomDropdownDecoration(
@ -286,12 +297,14 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
if (value.isEmpty) { if (value.isEmpty) {
return; return;
} }
_timer?.cancel(); if (assistant == null) {
_timer = _timer?.cancel();
Timer(const Duration(seconds: 1), () async { _timer =
await state.getAssistantsName(name: value); Timer(const Duration(seconds: 1), () async {
_formNameKey.currentState!.validate(); await state.getAssistantsName(name: value);
}); _formNameKey.currentState!.validate();
});
}
}, },
validator: (value) { validator: (value) {
String? result; String? result;
@ -299,7 +312,8 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
result = 'نام نباید خالی باشد'; result = 'نام نباید خالی باشد';
} else if (value.length < 4) { } else if (value.length < 4) {
result = 'نام نباید کمتر از 4 حرف باشد'; result = 'نام نباید کمتر از 4 حرف باشد';
} else if (!state.successName) { } else if (assistant == null &&
!state.successName) {
result = result =
'اسم دیگری انتخاب کنید این اسم موجود است'; 'اسم دیگری انتخاب کنید این اسم موجود است';
} }
@ -312,7 +326,6 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
const SizedBox( const SizedBox(
height: 8, height: 8,
), ),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -420,7 +433,6 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
}, },
), ),
), ),
const SizedBox( const SizedBox(
height: 24, height: 24,
), ),
@ -454,251 +466,276 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
const SizedBox( const SizedBox(
height: 24, height: 24,
), ),
if (selectedBotType == 'text') if (assistant == null)
Column( Column(
children: [ children: [
title(text: 'پایگاه دانش', isRequired: false), if (selectedBotType == 'text')
if (files.length != 3) Column(
SizedBox( children: [
height: 48, title(
child: ElevatedButton( text: 'پایگاه دانش', isRequired: false),
style: ElevatedButton.styleFrom( if (files.length != 3)
backgroundColor: Theme.of(context) SizedBox(
.colorScheme height: 48,
.disabledBackground, child: ElevatedButton(
shape: const RoundedRectangleBorder( style: ElevatedButton.styleFrom(
borderRadius: DesignConfig backgroundColor:
.lowBorderRadius)), Theme.of(context)
onPressed: () async { .colorScheme
final picks = .disabledBackground,
await MediaService.pickMultiFile(); shape:
if (picks != null) { const RoundedRectangleBorder(
for (var file in picks.xFiles) { borderRadius: DesignConfig
files.add(FileCreateAssistantsModel( .lowBorderRadius)),
fromNetwork: false, onPressed: () async {
file: file, final picks = await MediaService
url: null)); .pickMultiFile();
} if (picks != null) {
} for (var file in picks.xFiles) {
state.update(); files.add(
}, FileCreateAssistantsModel(
child: Row( fromNetwork: false,
mainAxisAlignment: file: file,
MainAxisAlignment.center, url: null));
children: [ }
Icon( }
CupertinoIcons.add, state.update();
color: Theme.of(context) },
.colorScheme child: Row(
.caption, mainAxisAlignment:
), MainAxisAlignment.center,
const SizedBox( children: [
width: 4, Icon(
), CupertinoIcons.add,
DidvanText(
'آپلود فایل (فایل صوتی، پی دی اف)',
color: Theme.of(context)
.colorScheme
.caption,
fontSize: 16,
)
],
)),
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
...List.generate(
files.length,
(index) {
return Stack(
children: [
Container(
width: MediaQuery.sizeOf(context)
.width /
5,
height: MediaQuery.sizeOf(context)
.width /
5,
margin:
const EdgeInsets.symmetric(
horizontal: 8,
vertical: 12),
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Theme.of(context) color: Theme.of(context)
.colorScheme .colorScheme
.disabledBackground, .caption,
borderRadius: DesignConfig
.lowBorderRadius),
child: Column(
children: [
Expanded(
child: files[index]
.fromNetwork
? files[index]
.url!
.isImage()
? CachedNetworkImage(
imageUrl:
files[index]
.url!)
: const Icon(
CupertinoIcons
.doc)
: files[index]
.file!
.path
.isImage()
? Image.file(File(
files[index]
.file!
.path))
: const Icon(
CupertinoIcons
.doc),
),
MarqueeText(
text: files[index]
.fromNetwork
? files[index]
.url!
.split('/')
.last
: files[index]
.file!
.name,
textDirection:
TextDirection.rtl,
style: Theme.of(context)
.textTheme
.labelSmall!)
],
)),
Positioned(
top: 8,
left: 4,
child: InkWell(
onTap: () {
files.removeAt(index);
state.update();
},
child: Container(
padding:
const EdgeInsets.all(6),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context)
.colorScheme
.error),
child: const Icon(
DidvanIcons.trash_solid,
color: Colors.white,
size: 18,
),
), ),
)) const SizedBox(
], width: 4,
); ),
}, DidvanText(
'آپلود فایل (فایل صوتی، پی دی اف)',
color: Theme.of(context)
.colorScheme
.caption,
fontSize: 16,
)
],
)),
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
...List.generate(
files.length,
(index) {
return Stack(
children: [
Container(
width: MediaQuery.sizeOf(
context)
.width /
5,
height: MediaQuery.sizeOf(
context)
.width /
5,
margin: const EdgeInsets
.symmetric(
horizontal: 8,
vertical: 12),
padding: const EdgeInsets
.all(8),
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.disabledBackground,
borderRadius: DesignConfig
.lowBorderRadius),
child: Column(
children: [
Expanded(
child: files[index]
.fromNetwork
? files[index]
.url!
.isImage()
? CachedNetworkImage(
imageUrl:
files[index]
.url!)
: const Icon(
CupertinoIcons
.doc)
: files[index]
.file!
.path
.isImage()
? Image.file(
File(files[
index]
.file!
.path))
: const Icon(
CupertinoIcons
.doc),
),
MarqueeText(
text: files[index]
.fromNetwork
? files[index]
.url!
.split('/')
.last
: files[index]
.file!
.name,
textDirection:
TextDirection
.rtl,
style: Theme.of(
context)
.textTheme
.labelSmall!)
],
)),
Positioned(
top: 8,
left: 4,
child: InkWell(
onTap: () {
files.removeAt(index);
state.update();
},
child: Container(
padding:
const EdgeInsets
.all(6),
decoration:
BoxDecoration(
shape: BoxShape
.circle,
color: Theme.of(
context)
.colorScheme
.error),
child: const Icon(
DidvanIcons
.trash_solid,
color: Colors.white,
size: 18,
),
),
))
],
);
},
)
],
),
const SizedBox(
height: 24,
),
],
),
// title(text: 'لینک یوتیوب', isRequired: false),
// Form(
// key: _formYouTubeKey,
// child: DidvanTextField(
// onChanged: (value) {
// youtubeLink = value;
// },
// validator: (value) =>
// value.startsWith('https://www.youtube.com') ||
// value.isEmpty
// ? null
// : 'باید لینک یوتیوب باشد',
// hintText: 'https://www.youtube.com/watch?v',
// ),
// ),
// const SizedBox(
// height: 24,
// ),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
title(
text: 'لینک وب سایت', isRequired: false),
Row(
children: [
if (countOfLink.length > 1)
DidvanIconButton(
icon:
CupertinoIcons.minus_circle_fill,
onPressed: () {
setState(() {
countOfLink.removeLast();
});
},
),
if (countOfLink.length != 3)
DidvanIconButton(
icon: CupertinoIcons.plus_circle_fill,
onPressed: () {
setState(() {
if (countOfLink.last.isNotEmpty) {
countOfLink.add('');
}
});
},
),
],
) )
], ],
), ),
ListView.builder(
shrinkWrap: true,
itemCount: countOfLink.length,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => Column(
children: [
DidvanTextField(
onChanged: (value) {
countOfLink.insert(index, value);
},
// validator: (value) {},
hintText:
'https://www.weforum.org/agenda/2024/08',
),
const SizedBox(
height: 8,
),
],
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
DidvanIcons.info_circle_light,
color:
Theme.of(context).colorScheme.caption,
),
const SizedBox(width: 4),
Expanded(
child: DidvanText(
'دستیار شما با استناد بر اطلاعات ارائه شده در پایگاه دانش، پیام کاربران را ارزیابی می‌کند.',
textAlign: TextAlign.right,
fontSize: 12,
color:
Theme.of(context).colorScheme.caption,
),
),
],
),
const SizedBox( const SizedBox(
height: 24, height: 24,
), ),
], ],
), ),
// title(text: 'لینک یوتیوب', isRequired: false),
// Form(
// key: _formYouTubeKey,
// child: DidvanTextField(
// onChanged: (value) {
// youtubeLink = value;
// },
// validator: (value) =>
// value.startsWith('https://www.youtube.com') ||
// value.isEmpty
// ? null
// : 'باید لینک یوتیوب باشد',
// hintText: 'https://www.youtube.com/watch?v',
// ),
// ),
// const SizedBox(
// height: 24,
// ),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
title(text: 'لینک وب سایت', isRequired: false),
Row(
children: [
if (countOfLink.length > 1)
DidvanIconButton(
icon: CupertinoIcons.minus_circle_fill,
onPressed: () {
setState(() {
countOfLink.removeLast();
});
},
),
if (countOfLink.length != 3)
DidvanIconButton(
icon: CupertinoIcons.plus_circle_fill,
onPressed: () {
setState(() {
if (countOfLink.last.isNotEmpty) {
countOfLink.add('');
}
});
},
),
],
)
],
),
ListView.builder(
shrinkWrap: true,
itemCount: countOfLink.length,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => Column(
children: [
DidvanTextField(
onChanged: (value) {
countOfLink.insert(index, value);
},
// validator: (value) {},
hintText:
'https://www.weforum.org/agenda/2024/08',
),
const SizedBox(
height: 8,
),
],
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
DidvanIcons.info_circle_light,
color: Theme.of(context).colorScheme.caption,
),
const SizedBox(width: 4),
Expanded(
child: DidvanText(
'دستیار شما با استناد بر اطلاعات ارائه شده در پایگاه دانش، پیام کاربران را ارزیابی می‌کند.',
textAlign: TextAlign.right,
fontSize: 12,
color: Theme.of(context).colorScheme.caption,
),
),
],
),
const SizedBox(
height: 24,
),
Row( Row(
children: [ children: [
Expanded( Expanded(
@ -732,7 +769,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
value: !isPrivate, value: !isPrivate,
title: '', title: '',
onChanged: (value) { onChanged: (value) {
isPrivate = value; isPrivate = !value;
}, },
), ),
), ),
@ -751,7 +788,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
children: [ children: [
DidvanButton( DidvanButton(
title: state.loadingCreate title: state.loadingCreate
? '' ? ' '
: 'ذخیره تغییرات', : 'ذخیره تغییرات',
onPressed: () async => onPressed: () async =>
onConfirm(state, selectedBotId), onConfirm(state, selectedBotId),
@ -795,13 +832,20 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
], ],
), ),
onConfirmed: () async { onConfirmed: () async {
await state.deleteAssistants( final success =
id: widget.id!); await state.deleteAssistants(
context id: widget.id!);
.read< if (success) {
CreateBotAssistantsState>() context
.assistant = null; .read<BotAssistantsState>()
Navigator.pop(context); .getMyAssissmant();
context
.read<
CreateBotAssistantsState>()
.assistant = null;
Navigator.pop(context);
}
}, },
)); ));
}, },
@ -812,7 +856,8 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
: Column( : Column(
children: [ children: [
DidvanButton( DidvanButton(
title: state.loadingCreate ? '' : 'ذخیره', title:
state.loadingCreate ? ' ' : 'ذخیره',
onPressed: () async => onPressed: () async =>
onConfirm(state, selectedBotId)), onConfirm(state, selectedBotId)),
if (state.loadingCreate) if (state.loadingCreate)

View File

@ -41,7 +41,7 @@ class CreateBotAssistantsState extends CoreProvier {
update(); update();
} }
Future createAssistants( Future<bool> createAssistants(
{required final BotAssistantsReqModel data, final int? id}) async { {required final BotAssistantsReqModel data, final int? id}) async {
loadingCreate = true; loadingCreate = true;
update(); update();
@ -59,11 +59,12 @@ class CreateBotAssistantsState extends CoreProvier {
appState = AppState.idle; appState = AppState.idle;
loadingCreate = false; loadingCreate = false;
update(); update();
return; return true;
} }
appState = AppState.failed; appState = AppState.failed;
loadingCreate = false; loadingCreate = false;
update(); update();
return false;
} }
Future getAnAssistant({required final int id}) async { Future getAnAssistant({required final int id}) async {
@ -86,7 +87,7 @@ class CreateBotAssistantsState extends CoreProvier {
update(); update();
} }
Future deleteAssistants({required final int id}) async { Future<bool> deleteAssistants({required final int id}) async {
loadingCreate = true; loadingCreate = true;
update(); update();
@ -96,11 +97,12 @@ class CreateBotAssistantsState extends CoreProvier {
appState = AppState.idle; appState = AppState.idle;
loadingCreate = false; loadingCreate = false;
update(); update();
return; return true;
} }
appState = AppState.failed; appState = AppState.failed;
loadingCreate = false; loadingCreate = false;
update(); update();
return false;
} }
Future getAssistantsName({required final String name}) async { Future getAssistantsName({required final String name}) async {