diff --git a/lib/models/ai/bot_assistants_req_model.dart b/lib/models/ai/bot_assistants_req_model.dart index f4b38ff..0127964 100644 --- a/lib/models/ai/bot_assistants_req_model.dart +++ b/lib/models/ai/bot_assistants_req_model.dart @@ -11,6 +11,7 @@ class BotAssistantsReqModel { final String? youtubeLink; final List? webLinks; final bool isPrivate; + final bool? deleteImage; BotAssistantsReqModel( {required this.type, @@ -22,6 +23,7 @@ class BotAssistantsReqModel { this.files, this.youtubeLink, this.webLinks, + this.deleteImage, this.isPrivate = true}); Map toJson() { @@ -35,6 +37,9 @@ class BotAssistantsReqModel { if (youtubeLink != null) { data['youtubeLink'] = youtubeLink; } + if (deleteImage != null) { + data['deleteImage'] = deleteImage; + } if (webLinks != null) { data['webLinks'] = webLinks; } diff --git a/lib/services/network/request_helper.dart b/lib/services/network/request_helper.dart index 40e3dca..6837695 100644 --- a/lib/services/network/request_helper.dart +++ b/lib/services/network/request_helper.dart @@ -231,14 +231,14 @@ class RequestHelper { static String placeholder(int id) => '$baseUrl/ai/chat/$id/placeholder'; static String tools() => '$baseUrl/ai/tool'; static String usersAssistants({final bool personal = false}) => - '$baseUrl/ai/bot/user${_urlConcatGenerator([ + '$baseUrl/ai/user/bot${_urlConcatGenerator([ MapEntry('personal', personal), ])}'; - static String createAssistants() => '$baseUrl/ai/bot'; - static String updateAssistants(int id) => '$baseUrl/ai/bot/$id'; - static String getAssistant(int id) => '$baseUrl/ai/bot/user/$id'; - static String deleteAssistant(int id) => '$baseUrl/ai/bot/user/$id'; - static String nameOfAssistant() => '$baseUrl/ai/bot/name'; + static String createAssistants() => '$baseUrl/ai/user/bot'; + static String updateAssistants(int id) => '$baseUrl/ai/user/bot/$id'; + static String getAssistant(int id) => '$baseUrl/ai/user/bot/$id'; + static String deleteAssistant(int id) => '$baseUrl/ai/user/bot/$id'; + static String nameOfAssistant() => '$baseUrl/ai/user/bot/name'; static String _urlConcatGenerator(List> additions) { String result = ''; diff --git a/lib/views/ai/ai_chat_state.dart b/lib/views/ai/ai_chat_state.dart index 8b7ed73..3b02358 100644 --- a/lib/views/ai/ai_chat_state.dart +++ b/lib/views/ai/ai_chat_state.dart @@ -157,7 +157,7 @@ class AiChatState extends CoreProvier { // } final req = await AiApiService.initial( - url: '${isAssistants ? '/custom' : ''}/${bot.id}/${bot.name}' + url: '${isAssistants ? '/user' : ''}/${bot.id}/${bot.name}' .toLowerCase(), message: message, chatId: chatId, diff --git a/lib/views/ai/bot_assistants_page.dart b/lib/views/ai/bot_assistants_page.dart index c899f74..f4c3375 100644 --- a/lib/views/ai/bot_assistants_page.dart +++ b/lib/views/ai/bot_assistants_page.dart @@ -187,8 +187,10 @@ class _BotAssistantsPageState extends State { return Container( padding: const EdgeInsets.all(12), margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 32), - decoration: const BoxDecoration( - color: Colors.white, borderRadius: DesignConfig.lowBorderRadius), + decoration: BoxDecoration( + border: Border.all(color: const Color(0xffe0e0e0)), + color: Colors.white, + borderRadius: DesignConfig.lowBorderRadius), child: Column( children: [ if (state.isMyAssistants) diff --git a/lib/views/ai/create_bot_assistants_page.dart b/lib/views/ai/create_bot_assistants_page.dart index 6d11a02..fe6421d 100644 --- a/lib/views/ai/create_bot_assistants_page.dart +++ b/lib/views/ai/create_bot_assistants_page.dart @@ -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/enums.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/utils/action_sheet.dart'; import 'package:didvan/utils/extension.dart'; @@ -104,7 +105,8 @@ class _CreateBotAssistantsPageState extends State { resultFiles.add(file.file!); } } - await state.createAssistants( + + final success = await state.createAssistants( id: widget.id, data: BotAssistantsReqModel( type: selectedBotType, @@ -116,11 +118,19 @@ class _CreateBotAssistantsPageState extends State { // youtubeLink: youtubeLink, isPrivate: isPrivate, files: resultFiles, + deleteImage: assistant != null + ? assistant!.image == null + : image.value == null, image: image.value)); - - context.read().getMyAssissmant(); - context.read().assistant = null; - Navigator.pop(context); + if (success) { + context.read().getMyAssissmant(); + context.read().assistant = null; + Navigator.pop(context); + } else { + ActionSheetUtils(context).showAlert(AlertData( + message: 'مشکلی در ارتباط با سرور پیش آمده دوباره تلاش کنید', + aLertType: ALertType.error)); + } } @override @@ -193,6 +203,7 @@ class _CreateBotAssistantsPageState extends State { child: CustomDropdown( closedHeaderPadding: const EdgeInsets.all(12), items: botModels, + enabled: assistant == null, initialItem: botModels[0], hideSelectedFieldWhenExpanded: false, decoration: CustomDropdownDecoration( @@ -286,12 +297,14 @@ class _CreateBotAssistantsPageState extends State { if (value.isEmpty) { return; } - _timer?.cancel(); - _timer = - Timer(const Duration(seconds: 1), () async { - await state.getAssistantsName(name: value); - _formNameKey.currentState!.validate(); - }); + if (assistant == null) { + _timer?.cancel(); + _timer = + Timer(const Duration(seconds: 1), () async { + await state.getAssistantsName(name: value); + _formNameKey.currentState!.validate(); + }); + } }, validator: (value) { String? result; @@ -299,7 +312,8 @@ class _CreateBotAssistantsPageState extends State { result = 'نام نباید خالی باشد'; } else if (value.length < 4) { result = 'نام نباید کمتر از 4 حرف باشد'; - } else if (!state.successName) { + } else if (assistant == null && + !state.successName) { result = 'اسم دیگری انتخاب کنید این اسم موجود است'; } @@ -312,7 +326,6 @@ class _CreateBotAssistantsPageState extends State { const SizedBox( height: 8, ), - Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -420,7 +433,6 @@ class _CreateBotAssistantsPageState extends State { }, ), ), - const SizedBox( height: 24, ), @@ -454,251 +466,276 @@ class _CreateBotAssistantsPageState extends State { const SizedBox( height: 24, ), - if (selectedBotType == 'text') + if (assistant == null) Column( children: [ - title(text: 'پایگاه دانش', isRequired: false), - if (files.length != 3) - SizedBox( - height: 48, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context) - .colorScheme - .disabledBackground, - shape: const RoundedRectangleBorder( - borderRadius: DesignConfig - .lowBorderRadius)), - onPressed: () async { - final picks = - await MediaService.pickMultiFile(); - if (picks != null) { - for (var file in picks.xFiles) { - files.add(FileCreateAssistantsModel( - fromNetwork: false, - file: file, - url: null)); - } - } - state.update(); - }, - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Icon( - CupertinoIcons.add, - color: Theme.of(context) - .colorScheme - .caption, - ), - 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( + if (selectedBotType == 'text') + Column( + children: [ + title( + text: 'پایگاه دانش', isRequired: false), + if (files.length != 3) + SizedBox( + height: 48, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: + Theme.of(context) + .colorScheme + .disabledBackground, + shape: + const RoundedRectangleBorder( + borderRadius: DesignConfig + .lowBorderRadius)), + onPressed: () async { + final picks = await MediaService + .pickMultiFile(); + if (picks != null) { + for (var file in picks.xFiles) { + files.add( + FileCreateAssistantsModel( + fromNetwork: false, + file: file, + url: null)); + } + } + state.update(); + }, + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + CupertinoIcons.add, 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, - ), + .caption, ), - )) - ], - ); - }, + 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( 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( children: [ Expanded( @@ -732,7 +769,7 @@ class _CreateBotAssistantsPageState extends State { value: !isPrivate, title: '', onChanged: (value) { - isPrivate = value; + isPrivate = !value; }, ), ), @@ -751,7 +788,7 @@ class _CreateBotAssistantsPageState extends State { children: [ DidvanButton( title: state.loadingCreate - ? '' + ? ' ' : 'ذخیره تغییرات', onPressed: () async => onConfirm(state, selectedBotId), @@ -795,13 +832,20 @@ class _CreateBotAssistantsPageState extends State { ], ), onConfirmed: () async { - await state.deleteAssistants( - id: widget.id!); - context - .read< - CreateBotAssistantsState>() - .assistant = null; - Navigator.pop(context); + final success = + await state.deleteAssistants( + id: widget.id!); + if (success) { + context + .read() + .getMyAssissmant(); + + context + .read< + CreateBotAssistantsState>() + .assistant = null; + Navigator.pop(context); + } }, )); }, @@ -812,7 +856,8 @@ class _CreateBotAssistantsPageState extends State { : Column( children: [ DidvanButton( - title: state.loadingCreate ? '' : 'ذخیره', + title: + state.loadingCreate ? ' ' : 'ذخیره', onPressed: () async => onConfirm(state, selectedBotId)), if (state.loadingCreate) diff --git a/lib/views/ai/create_bot_assistants_state.dart b/lib/views/ai/create_bot_assistants_state.dart index a374fcb..5ea65ee 100644 --- a/lib/views/ai/create_bot_assistants_state.dart +++ b/lib/views/ai/create_bot_assistants_state.dart @@ -41,7 +41,7 @@ class CreateBotAssistantsState extends CoreProvier { update(); } - Future createAssistants( + Future createAssistants( {required final BotAssistantsReqModel data, final int? id}) async { loadingCreate = true; update(); @@ -59,11 +59,12 @@ class CreateBotAssistantsState extends CoreProvier { appState = AppState.idle; loadingCreate = false; update(); - return; + return true; } appState = AppState.failed; loadingCreate = false; update(); + return false; } Future getAnAssistant({required final int id}) async { @@ -86,7 +87,7 @@ class CreateBotAssistantsState extends CoreProvier { update(); } - Future deleteAssistants({required final int id}) async { + Future deleteAssistants({required final int id}) async { loadingCreate = true; update(); @@ -96,11 +97,12 @@ class CreateBotAssistantsState extends CoreProvier { appState = AppState.idle; loadingCreate = false; update(); - return; + return true; } appState = AppState.failed; loadingCreate = false; update(); + return false; } Future getAssistantsName({required final String name}) async {