From 689252c17f33174d2615d8f6e8e0563aa3205fa3 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 21 Oct 2024 12:54:28 -0400 Subject: [PATCH 1/2] initial work on updating bot settings UI --- assets/l10n/intl_en.arb | 13 +- lib/pangea/constants/model_keys.dart | 3 + lib/pangea/models/bot_options_model.dart | 14 + ...sation_bot_custom_system_prompt_input.dart | 95 ----- .../conversation_bot_custom_zone.dart | 57 --- ...rsation_bot_discussion_keywords_input.dart | 74 ---- ...nversation_bot_discussion_topic_input.dart | 73 ---- .../conversation_bot_discussion_zone.dart | 70 ---- .../conversation_bot_dynamic_zone_label.dart | 27 -- .../conversation_bot_dynamic_zone_title.dart | 31 -- .../conversation_bot_mode_dynamic_zone.dart | 76 ++-- .../conversation_bot_mode_select.dart | 69 ++-- .../conversation_bot_settings.dart | 358 +++++++++++------- .../conversation_bot_settings_form.dart | 98 +++-- .../conversation_bot_text_adventure_zone.dart | 11 +- .../space/language_level_dropdown.dart | 81 ++-- 16 files changed, 410 insertions(+), 740 deletions(-) delete mode 100644 lib/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart delete mode 100644 lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart delete mode 100644 lib/pangea/widgets/conversation_bot/conversation_bot_discussion_keywords_input.dart delete mode 100644 lib/pangea/widgets/conversation_bot/conversation_bot_discussion_topic_input.dart delete mode 100644 lib/pangea/widgets/conversation_bot/conversation_bot_discussion_zone.dart delete mode 100644 lib/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_label.dart delete mode 100644 lib/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_title.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 83de9e423..555f319de 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3904,7 +3904,6 @@ "listen": "Listen", "addConversationBot": "Enable Conversation Bot", "addConversationBotDesc": "Add a bot to this chat", - "convoBotSettingsTitle": "Conversation Bot Settings", "convoBotSettingsDescription": "Edit conversation topic and difficulty", "enterAConversationTopic": "Enter a conversation topic", "conversationTopic": "Conversation topic", @@ -4009,7 +4008,7 @@ "accuracy": "Accuracy", "points": "Points", "noPaymentInfo": "No payment info necessary!", - "conversationBotModeSelectDescription": "Bot mode", + "conversationBotModeSelectDescription": "Chat Activity", "conversationBotModeSelectOption_discussion": "Discussion", "conversationBotModeSelectOption_custom": "Custom", "conversationBotModeSelectOption_conversation": "Conversation", @@ -4030,7 +4029,7 @@ "conversationBotCustomZone_customSystemPromptPlaceholder": "Set custom system prompt", "conversationBotCustomZone_customSystemPromptEmptyError": "Missing custom system prompt", "conversationBotCustomZone_customTriggerReactionEnabledLabel": "Responds on ⏩ reaction", - "botConfig": "Conversation Bot Settings", + "botConfig": "Chat Settings", "addConversationBotDialogTitleInvite": "Confirm inviting conversation bot", "addConversationBotButtonInvite": "Invite", "addConversationBotDialogInviteConfirmation": "Invite", @@ -4038,7 +4037,7 @@ "addConversationBotButtonRemove": "Remove", "addConversationBotDialogRemoveConfirmation": "Remove", "conversationBotConfigConfirmChange": "Confirm", - "conversationBotStatus": "Bot Status", + "conversationBotStatus": "Invite bot", "conversationBotTextAdventureZone_title": "Text Adventure", "conversationBotTextAdventureZone_instructionLabel": "Game Master Instructions", "conversationBotTextAdventureZone_instructionPlaceholder": "Set game master instructions", @@ -4356,5 +4355,9 @@ "grammarCopyCase": "Case", "grammarCopyDefinite": "Definiteness", "grammarCopyNumForm": "Numeral Form", - "grammarCopyUnknown": "Unknown" + "grammarCopyUnknown": "Unknown", + "enterPrompt": "Please enter a system prompt", + "selectBotLanguage": "Select bot language", + "chooseVoice": "Choose a voice", + "enterLanguageLevel": "Please enter a language level" } \ No newline at end of file diff --git a/lib/pangea/constants/model_keys.dart b/lib/pangea/constants/model_keys.dart index 962532c9f..424c07830 100644 --- a/lib/pangea/constants/model_keys.dart +++ b/lib/pangea/constants/model_keys.dart @@ -121,6 +121,9 @@ class ModelKey { static const String textAdventureGameMasterInstructions = "text_adventure_game_master_instructions"; + static const String targetLanguage = "target_language"; + static const String targetVoice = "target_voice"; + static const String prevEventId = "prev_event_id"; static const String prevLastUpdated = "prev_last_updated"; diff --git a/lib/pangea/models/bot_options_model.dart b/lib/pangea/models/bot_options_model.dart index db2725edc..5bae119c3 100644 --- a/lib/pangea/models/bot_options_model.dart +++ b/lib/pangea/models/bot_options_model.dart @@ -21,6 +21,8 @@ class BotOptionsModel { bool? customTriggerReactionEnabled; String? customTriggerReactionKey; String? textAdventureGameMasterInstructions; + String? targetLanguage; + String? targetVoice; BotOptionsModel({ //////////////////////////////////////////////////////////////////////////// @@ -31,6 +33,8 @@ class BotOptionsModel { this.keywords = const [], this.safetyModeration = true, this.mode = BotMode.discussion, + this.targetLanguage, + this.targetVoice, //////////////////////////////////////////////////////////////////////////// // Discussion Mode Options @@ -63,6 +67,8 @@ class BotOptionsModel { : null, safetyModeration: json[ModelKey.safetyModeration] ?? true, mode: json[ModelKey.mode] ?? BotMode.discussion, + targetLanguage: json[ModelKey.targetLanguage], + targetVoice: json[ModelKey.targetVoice], ////////////////////////////////////////////////////////////////////////// // Discussion Mode Options @@ -97,6 +103,8 @@ class BotOptionsModel { data[ModelKey.languageLevel] = languageLevel; data[ModelKey.safetyModeration] = safetyModeration; data[ModelKey.mode] = mode; + data[ModelKey.targetLanguage] = targetLanguage; + data[ModelKey.targetVoice] = targetVoice; data[ModelKey.discussionTopic] = discussionTopic; data[ModelKey.discussionKeywords] = discussionKeywords; data[ModelKey.discussionTriggerReactionEnabled] = @@ -153,6 +161,12 @@ class BotOptionsModel { case ModelKey.textAdventureGameMasterInstructions: textAdventureGameMasterInstructions = value; break; + case ModelKey.targetLanguage: + targetLanguage = value; + break; + case ModelKey.targetVoice: + targetVoice = value; + break; default: throw Exception('Invalid key for bot options - $key'); } diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart deleted file mode 100644 index 2e79e0677..000000000 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'package:fluffychat/pangea/models/bot_options_model.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -class ConversationBotCustomSystemPromptInput extends StatelessWidget { - final BotOptionsModel initialBotOptions; - // call this to update propagate changes to parents - final void Function(BotOptionsModel) onChanged; - - const ConversationBotCustomSystemPromptInput({ - super.key, - required this.initialBotOptions, - required this.onChanged, - }); - - @override - Widget build(BuildContext context) { - String customSystemPrompt = initialBotOptions.customSystemPrompt ?? ""; - - final TextEditingController textFieldController = - TextEditingController(text: customSystemPrompt); - - final GlobalKey customSystemPromptFormKey = - GlobalKey(); - - void setBotCustomSystemPromptAction() async { - showDialog( - context: context, - useRootNavigator: false, - builder: (BuildContext context) => AlertDialog( - title: Text( - L10n.of(context)!.conversationBotCustomZone_customSystemPromptLabel, - ), - content: Form( - key: customSystemPromptFormKey, - child: TextFormField( - minLines: 1, - maxLines: 10, - maxLength: 1000, - controller: textFieldController, - onChanged: (value) { - if (value.isNotEmpty) { - customSystemPrompt = value; - } - }, - validator: (value) { - if (value == null || value.isEmpty) { - return 'This field cannot be empty'; - } - return null; - }, - ), - ), - actions: [ - TextButton( - child: Text(L10n.of(context)!.cancel), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - TextButton( - child: Text(L10n.of(context)!.ok), - onPressed: () { - if (customSystemPromptFormKey.currentState!.validate()) { - if (customSystemPrompt != - initialBotOptions.customSystemPrompt) { - initialBotOptions.customSystemPrompt = customSystemPrompt; - onChanged.call(initialBotOptions); - } - Navigator.of(context).pop(); - } - }, - ), - ], - ), - ); - } - - return ListTile( - onTap: setBotCustomSystemPromptAction, - title: Text( - initialBotOptions.customSystemPrompt ?? - L10n.of(context)! - .conversationBotCustomZone_customSystemPromptPlaceholder, - ), - subtitle: customSystemPrompt.isEmpty - ? Text( - L10n.of(context)! - .conversationBotCustomZone_customSystemPromptEmptyError, - style: const TextStyle(color: Colors.red), - ) - : null, - ); - } -} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart deleted file mode 100644 index 14b05dc90..000000000 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:fluffychat/pangea/models/bot_options_model.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_label.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_title.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -class ConversationBotCustomZone extends StatelessWidget { - final BotOptionsModel initialBotOptions; - // call this to update propagate changes to parents - final void Function(BotOptionsModel) onChanged; - - const ConversationBotCustomZone({ - super.key, - required this.initialBotOptions, - required this.onChanged, - }); - - @override - Widget build(BuildContext context) { - return Column( - children: [ - ConversationBotDynamicZoneTitle( - title: L10n.of(context)!.conversationBotCustomZone_title, - ), - ConversationBotDynamicZoneLabel( - label: L10n.of(context)! - .conversationBotCustomZone_customSystemPromptLabel, - ), - Padding( - padding: const EdgeInsets.all(8), - child: ConversationBotCustomSystemPromptInput( - initialBotOptions: initialBotOptions, - onChanged: onChanged, - ), - ), - const SizedBox(height: 12), - CheckboxListTile( - title: Text( - L10n.of(context)! - .conversationBotCustomZone_customTriggerReactionEnabledLabel, - ), - enabled: false, - value: initialBotOptions.customTriggerReactionEnabled ?? true, - onChanged: (value) { - initialBotOptions.customTriggerReactionEnabled = value ?? true; - initialBotOptions.customTriggerReactionKey = - "⏩"; // hard code this for now - onChanged.call(initialBotOptions); - }, - // make this input disabled always - ), - const SizedBox(height: 12), - ], - ); - } -} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_keywords_input.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_keywords_input.dart deleted file mode 100644 index fa08a860d..000000000 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_keywords_input.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:fluffychat/pangea/models/bot_options_model.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -class ConversationBotDiscussionKeywordsInput extends StatelessWidget { - final BotOptionsModel initialBotOptions; - // call this to update propagate changes to parents - final void Function(BotOptionsModel) onChanged; - - const ConversationBotDiscussionKeywordsInput({ - super.key, - required this.initialBotOptions, - required this.onChanged, - }); - - @override - Widget build(BuildContext context) { - String discussionKeywords = initialBotOptions.discussionKeywords ?? ""; - - final TextEditingController textFieldController = - TextEditingController(text: discussionKeywords); - - void setBotDiscussionKeywordsAction() async { - showDialog( - context: context, - useRootNavigator: false, - builder: (BuildContext context) => AlertDialog( - title: Text( - L10n.of(context)! - .conversationBotDiscussionZone_discussionKeywordsLabel, - ), - content: TextField( - minLines: 1, - maxLines: 10, - maxLength: 1000, - controller: textFieldController, - onChanged: (value) { - discussionKeywords = value; - }, - ), - actions: [ - TextButton( - child: Text(L10n.of(context)!.cancel), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - TextButton( - child: Text(L10n.of(context)!.ok), - onPressed: () { - if (discussionKeywords == "") return; - if (discussionKeywords != - initialBotOptions.discussionKeywords) { - initialBotOptions.discussionKeywords = discussionKeywords; - onChanged.call(initialBotOptions); - Navigator.of(context).pop(); - } - }, - ), - ], - ), - ); - } - - return ListTile( - onTap: setBotDiscussionKeywordsAction, - title: Text( - initialBotOptions.discussionKeywords ?? - L10n.of(context)! - .conversationBotDiscussionZone_discussionKeywordsPlaceholder, - ), - ); - } -} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_topic_input.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_topic_input.dart deleted file mode 100644 index c2d4eefcc..000000000 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_topic_input.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'package:fluffychat/pangea/models/bot_options_model.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -class ConversationBotDiscussionTopicInput extends StatelessWidget { - final BotOptionsModel initialBotOptions; - // call this to update propagate changes to parents - final void Function(BotOptionsModel) onChanged; - - const ConversationBotDiscussionTopicInput({ - super.key, - required this.initialBotOptions, - required this.onChanged, - }); - - @override - Widget build(BuildContext context) { - String discussionTopic = initialBotOptions.discussionTopic ?? ""; - - final TextEditingController textFieldController = - TextEditingController(text: discussionTopic); - - void setBotDiscussionTopicAction() async { - showDialog( - context: context, - useRootNavigator: false, - builder: (BuildContext context) => AlertDialog( - title: Text( - L10n.of(context)! - .conversationBotDiscussionZone_discussionTopicLabel, - ), - content: TextField( - minLines: 1, - maxLines: 10, - maxLength: 1000, - controller: textFieldController, - onChanged: (value) { - discussionTopic = value; - }, - ), - actions: [ - TextButton( - child: Text(L10n.of(context)!.cancel), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - TextButton( - child: Text(L10n.of(context)!.ok), - onPressed: () { - if (discussionTopic == "") return; - if (discussionTopic != initialBotOptions.discussionTopic) { - initialBotOptions.discussionTopic = discussionTopic; - onChanged.call(initialBotOptions); - Navigator.of(context).pop(); - } - }, - ), - ], - ), - ); - } - - return ListTile( - onTap: setBotDiscussionTopicAction, - title: Text( - initialBotOptions.discussionTopic ?? - L10n.of(context)! - .conversationBotDiscussionZone_discussionTopicPlaceholder, - ), - ); - } -} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_zone.dart deleted file mode 100644 index 6035faf4d..000000000 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_zone.dart +++ /dev/null @@ -1,70 +0,0 @@ -import 'package:fluffychat/pangea/models/bot_options_model.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_discussion_keywords_input.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_discussion_topic_input.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_label.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_title.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -class ConversationBotDiscussionZone extends StatelessWidget { - final BotOptionsModel initialBotOptions; - // call this to update propagate changes to parents - final void Function(BotOptionsModel) onChanged; - - const ConversationBotDiscussionZone({ - super.key, - required this.initialBotOptions, - required this.onChanged, - }); - - @override - Widget build(BuildContext context) { - return Column( - children: [ - ConversationBotDynamicZoneTitle( - title: L10n.of(context)!.conversationBotDiscussionZone_title, - ), - ConversationBotDynamicZoneLabel( - label: L10n.of(context)! - .conversationBotDiscussionZone_discussionTopicLabel, - ), - Padding( - padding: const EdgeInsets.all(8), - child: ConversationBotDiscussionTopicInput( - initialBotOptions: initialBotOptions, - onChanged: onChanged, - ), - ), - const SizedBox(height: 12), - ConversationBotDynamicZoneLabel( - label: L10n.of(context)! - .conversationBotDiscussionZone_discussionKeywordsLabel, - ), - Padding( - padding: const EdgeInsets.all(8), - child: ConversationBotDiscussionKeywordsInput( - initialBotOptions: initialBotOptions, - onChanged: onChanged, - ), - ), - const SizedBox(height: 12), - CheckboxListTile( - title: Text( - L10n.of(context)! - .conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel, - ), - enabled: false, - value: initialBotOptions.discussionTriggerReactionEnabled ?? true, - onChanged: (value) { - initialBotOptions.discussionTriggerReactionEnabled = value ?? true; - initialBotOptions.discussionTriggerReactionKey = - "⏩"; // hard code this for now - onChanged.call(initialBotOptions); - }, - // make this input disabled always - ), - const SizedBox(height: 12), - ], - ); - } -} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_label.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_label.dart deleted file mode 100644 index 6c2043dcd..000000000 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_label.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter/material.dart'; - -class ConversationBotDynamicZoneLabel extends StatelessWidget { - final String label; - - const ConversationBotDynamicZoneLabel({ - super.key, - required this.label, - }); - - @override - Widget build(BuildContext context) { - return Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.fromLTRB(12, 0, 0, 0), - child: Text( - label, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - ), - ); - } -} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_title.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_title.dart deleted file mode 100644 index dbfbb00dc..000000000 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_title.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flutter/material.dart'; - -class ConversationBotDynamicZoneTitle extends StatelessWidget { - final String title; - - const ConversationBotDynamicZoneTitle({ - super.key, - required this.title, - }); - - @override - Widget build(BuildContext context) { - return Column( - children: [ - const SizedBox(height: 12), - Text( - title, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - const Divider( - color: Colors.grey, - thickness: 1, - ), - const SizedBox(height: 12), - ], - ); - } -} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart index 90d7ed789..76aec7d62 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart @@ -1,44 +1,74 @@ import 'package:fluffychat/pangea/constants/bot_mode.dart'; import 'package:fluffychat/pangea/models/bot_options_model.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart'; import 'package:flutter/material.dart'; - -import 'conversation_bot_discussion_zone.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; class ConversationBotModeDynamicZone extends StatelessWidget { final BotOptionsModel initialBotOptions; - final void Function(BotOptionsModel) onChanged; + final GlobalKey formKey; + + final TextEditingController discussionTopicController; + final TextEditingController discussionKeywordsController; + final TextEditingController customSystemPromptController; const ConversationBotModeDynamicZone({ super.key, required this.initialBotOptions, - required this.onChanged, + required this.formKey, + required this.discussionTopicController, + required this.discussionKeywordsController, + required this.customSystemPromptController, }); @override Widget build(BuildContext context) { - final zoneMap = { - BotMode.discussion: ConversationBotDiscussionZone( - initialBotOptions: initialBotOptions, - onChanged: onChanged, + final discussionChildren = [ + TextFormField( + decoration: InputDecoration( + hintText: L10n.of(context)! + .conversationBotDiscussionZone_discussionTopicPlaceholder, + ), + controller: discussionTopicController, ), - BotMode.custom: ConversationBotCustomZone( - initialBotOptions: initialBotOptions, - onChanged: onChanged, + const SizedBox(height: 12), + TextFormField( + decoration: InputDecoration( + hintText: L10n.of(context)! + .conversationBotDiscussionZone_discussionKeywordsPlaceholder, + ), + controller: discussionKeywordsController, ), - }; - if (!zoneMap.containsKey(initialBotOptions.mode)) { - return Container(); - } - return Container( - decoration: BoxDecoration( - border: Border.all( - color: Theme.of(context).colorScheme.secondary, - width: 0.5, + ]; + + final customChildren = [ + TextFormField( + decoration: InputDecoration( + hintText: L10n.of(context)! + .conversationBotCustomZone_customSystemPromptPlaceholder, ), - borderRadius: const BorderRadius.all(Radius.circular(10)), + validator: (value) => value == null || value.isEmpty + ? L10n.of(context)!.enterPrompt + : null, + controller: customSystemPromptController, ), - child: zoneMap[initialBotOptions.mode], + ]; + + return Column( + children: [ + if (initialBotOptions.mode == BotMode.discussion) ...discussionChildren, + if (initialBotOptions.mode == BotMode.custom) ...customChildren, + const SizedBox(height: 12), + CheckboxListTile( + title: Text( + L10n.of(context)! + .conversationBotCustomZone_customTriggerReactionEnabledLabel, + ), + enabled: false, + value: initialBotOptions.customTriggerReactionEnabled ?? true, + onChanged: null, + ), + const SizedBox(height: 12), + ], ); } } diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart index 753a8a8a8..c22801d25 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart @@ -24,56 +24,35 @@ class ConversationBotModeSelect extends StatelessWidget { // L10n.of(context)!.conversationBotModeSelectOption_storyGame, }; - return Padding( - padding: const EdgeInsets.all(12.0), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Theme.of(context).colorScheme.secondary, - width: 0.5, - ), - borderRadius: const BorderRadius.all(Radius.circular(10)), - ), - child: DropdownButton( - // Initial Value - hint: Padding( - padding: const EdgeInsets.only(left: 15), + String? mode = initialMode; + if (!options.containsKey(initialMode)) { + mode = null; + } + + return DropdownButtonFormField( + // Initial Value + hint: Text( + options[mode ?? BotMode.discussion]!, + overflow: TextOverflow.clip, + textAlign: TextAlign.center, + ), + // ), + isExpanded: true, + // Down Arrow Icon + icon: const Icon(Icons.keyboard_arrow_down), + // Array list of items + items: [ + for (final entry in options.entries) + DropdownMenuItem( + value: entry.key, child: Text( - options[initialMode ?? BotMode.discussion]!, - style: const TextStyle().copyWith( - color: Theme.of(context).textTheme.bodyLarge!.color, - fontSize: 14, - ), + entry.value, overflow: TextOverflow.clip, textAlign: TextAlign.center, ), ), - isExpanded: true, - underline: Container(), - // Down Arrow Icon - icon: const Icon(Icons.keyboard_arrow_down), - // Array list of items - items: [ - for (final entry in options.entries) - DropdownMenuItem( - value: entry.key, - child: Padding( - padding: const EdgeInsets.only(left: 15), - child: Text( - entry.value, - style: const TextStyle().copyWith( - color: Theme.of(context).textTheme.bodyLarge!.color, - fontSize: 14, - ), - overflow: TextOverflow.clip, - textAlign: TextAlign.center, - ), - ), - ), - ], - onChanged: onChanged, - ), - ), + ], + onChanged: onChanged, ); } } diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart index fe85b48c7..3a8cc53ff 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart @@ -39,6 +39,13 @@ class ConversationBotSettingsState extends State { ConversationBotSettingsState({Key? key}); + final TextEditingController discussionTopicController = + TextEditingController(); + final TextEditingController discussionKeywordsController = + TextEditingController(); + final TextEditingController customSystemPromptController = + TextEditingController(); + @override void initState() { super.initState(); @@ -55,6 +62,10 @@ class ConversationBotSettingsState extends State { ? Matrix.of(context).client.getRoomById(widget.activeSpaceId!) : null; isCreating = widget.room == null; + + discussionKeywordsController.text = botOptions.discussionKeywords ?? ""; + discussionTopicController.text = botOptions.discussionTopic ?? ""; + customSystemPromptController.text = botOptions.customSystemPrompt ?? ""; } Future setBotOption() async { @@ -88,6 +99,106 @@ class ConversationBotSettingsState extends State { ); } + Future showBotOptionsDialog() async { + if (isCreating) return; + final bool? confirm = await showDialog( + context: context, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (context, setState) => Dialog( + child: Form( + key: formKey, + child: Container( + padding: const EdgeInsets.all(16), + constraints: const BoxConstraints( + maxWidth: 450, + maxHeight: 725, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20.0), + child: ConversationBotSettingsDialog( + addBot: addBot, + botOptions: botOptions, + formKey: formKey, + updateAddBot: (bool value) => + setState(() => addBot = value), + discussionKeywordsController: discussionKeywordsController, + discussionTopicController: discussionTopicController, + customSystemPromptController: customSystemPromptController, + ), + ), + ), + ), + ), + ); + }, + ); + + if (confirm == true) { + botOptions.discussionTopic = discussionTopicController.text; + botOptions.discussionKeywords = discussionKeywordsController.text; + botOptions.customSystemPrompt = customSystemPromptController.text; + + updateBotOption(() => botOptions = botOptions); + + final bool isBotRoomMember = await widget.room?.botIsInRoom ?? false; + if (addBot && !isBotRoomMember) { + await widget.room?.invite(BotName.byEnvironment); + } else if (!addBot && isBotRoomMember) { + await widget.room?.kick(BotName.byEnvironment); + } + } + } + + Future showNewRoomBotOptionsDialog() async { + final bool? confirm = await showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: addBot + ? Text( + L10n.of(context)!.addConversationBotButtonTitleRemove, + ) + : Text( + L10n.of(context)!.addConversationBotDialogTitleInvite, + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(false); + }, + child: Text(L10n.of(context)!.cancel), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(!addBot); + }, + child: addBot + ? Text( + L10n.of(context)! + .addConversationBotDialogRemoveConfirmation, + ) + : Text( + L10n.of(context)! + .addConversationBotDialogInviteConfirmation, + ), + ), + ], + ); + }, + ); + + if (confirm == true) { + setState(() => addBot = true); + widget.room?.invite(BotName.byEnvironment); + } else { + setState(() => addBot = false); + widget.room?.kick(BotName.byEnvironment); + } + } + + final GlobalKey formKey = GlobalKey(); + @override Widget build(BuildContext context) { return AnimatedContainer( @@ -119,162 +230,115 @@ class ConversationBotSettingsState extends State { ), trailing: isCreating ? ElevatedButton( - onPressed: () async { - final bool? confirm = await showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: addBot - ? Text( - L10n.of(context)! - .addConversationBotButtonTitleRemove, - ) - : Text( - L10n.of(context)! - .addConversationBotDialogTitleInvite, - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(false); - }, - child: Text(L10n.of(context)!.cancel), - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(!addBot); - }, - child: addBot - ? Text( - L10n.of(context)! - .addConversationBotDialogRemoveConfirmation, - ) - : Text( - L10n.of(context)! - .addConversationBotDialogInviteConfirmation, - ), - ), - ], - ); - }, - ); - - if (confirm == true) { - setState(() => addBot = true); - widget.room?.invite(BotName.byEnvironment); - } else { - setState(() => addBot = false); - widget.room?.kick(BotName.byEnvironment); - } - }, - child: addBot - ? Text( - L10n.of(context)!.addConversationBotButtonRemove, - ) - : Text( - L10n.of(context)!.addConversationBotButtonInvite, - ), + onPressed: showNewRoomBotOptionsDialog, + child: Text( + addBot + ? L10n.of(context)!.addConversationBotButtonRemove + : L10n.of(context)!.addConversationBotButtonInvite, + ), ) : const Icon(Icons.settings), - onTap: isCreating - ? null - : () async { - final bool? confirm = await showDialog( - context: context, - builder: (BuildContext context) { - return StatefulBuilder( - builder: (context, setState) => AlertDialog( - title: Text( - L10n.of(context)!.botConfig, - ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: - const EdgeInsets.fromLTRB(0, 0, 0, 12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - L10n.of(context)!.conversationBotStatus, - ), - Switch( - value: addBot, - onChanged: (value) { - setState( - () => addBot = value, - ); - }, - ), - ], - ), - ), - if (addBot) - Flexible( - child: SingleChildScrollView( - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Theme.of(context) - .colorScheme - .secondary, - width: 0.5, - ), - borderRadius: const BorderRadius.all( - Radius.circular(10), - ), - ), - child: ConversationBotSettingsForm( - botOptions: botOptions, - ), - ), - ), - ), - ], - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(false); - }, - child: Text(L10n.of(context)!.cancel), - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(true); - }, - child: Text( - L10n.of(context)! - .conversationBotConfigConfirmChange, - ), - ), - ], - ), - ); - }, - ); - if (confirm == true) { - updateBotOption(() { - botOptions = botOptions; - }); - final bool isBotRoomMember = - await widget.room?.botIsInRoom ?? false; - if (addBot && !isBotRoomMember) { - await widget.room?.invite(BotName.byEnvironment); - } else if (!addBot && isBotRoomMember) { - await widget.room?.kick(BotName.byEnvironment); - } - } - }, + onTap: showBotOptionsDialog, ), if (isCreating && addBot) ConversationBotSettingsForm( botOptions: botOptions, + formKey: formKey, + discussionKeywordsController: discussionKeywordsController, + discussionTopicController: discussionTopicController, + customSystemPromptController: customSystemPromptController, ), ], ), ); } } + +class ConversationBotSettingsDialog extends StatelessWidget { + final bool addBot; + final BotOptionsModel botOptions; + final GlobalKey formKey; + + final void Function(bool) updateAddBot; + + final TextEditingController discussionTopicController; + final TextEditingController discussionKeywordsController; + final TextEditingController customSystemPromptController; + + const ConversationBotSettingsDialog({ + super.key, + required this.addBot, + required this.botOptions, + required this.formKey, + required this.updateAddBot, + required this.discussionTopicController, + required this.discussionKeywordsController, + required this.customSystemPromptController, + }); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 12, + ), + child: Text( + L10n.of(context)!.botConfig, + style: Theme.of(context).textTheme.titleLarge, + ), + ), + ), + SwitchListTile( + title: Text( + L10n.of(context)!.conversationBotStatus, + ), + value: addBot, + onChanged: updateAddBot, + contentPadding: const EdgeInsets.all(4), + ), + if (addBot) + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 20), + ConversationBotSettingsForm( + botOptions: botOptions, + formKey: formKey, + discussionKeywordsController: discussionKeywordsController, + discussionTopicController: discussionTopicController, + customSystemPromptController: customSystemPromptController, + ), + ], + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(false); + }, + child: Text(L10n.of(context)!.cancel), + ), + const SizedBox(width: 20), + TextButton( + onPressed: () { + final isValid = formKey.currentState!.validate(); + if (!isValid) return; + Navigator.of(context).pop(true); + }, + child: Text(L10n.of(context)!.confirm), + ), + ], + ), + ], + ); + } +} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart index b630f608b..fb482ab1c 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart @@ -3,15 +3,25 @@ import 'package:fluffychat/pangea/models/bot_options_model.dart'; import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart'; import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart'; import 'package:fluffychat/pangea/widgets/space/language_level_dropdown.dart'; +import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; class ConversationBotSettingsForm extends StatefulWidget { final BotOptionsModel botOptions; + final GlobalKey formKey; + + final TextEditingController discussionTopicController; + final TextEditingController discussionKeywordsController; + final TextEditingController customSystemPromptController; const ConversationBotSettingsForm({ super.key, required this.botOptions, + required this.formKey, + required this.discussionTopicController, + required this.discussionKeywordsController, + required this.customSystemPromptController, }); @override @@ -21,8 +31,6 @@ class ConversationBotSettingsForm extends StatefulWidget { class ConversationBotSettingsFormState extends State { - final formKey = GlobalKey(); - late BotOptionsModel botOptions; @override @@ -35,17 +43,48 @@ class ConversationBotSettingsFormState Widget build(BuildContext context) { return Column( children: [ - Padding( - padding: const EdgeInsets.all(12.0), - child: Text( - L10n.of(context)!.conversationLanguageLevel, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - fontSize: 16, - ), + DropdownButtonFormField( + // Initial Value + hint: Text( + L10n.of(context)!.selectBotLanguage, + overflow: TextOverflow.clip, + textAlign: TextAlign.center, ), + value: botOptions.targetLanguage, + isExpanded: true, + icon: const Icon(Icons.keyboard_arrow_down), + items: MatrixState.pangeaController.pLanguageStore.targetOptions + .map((language) { + return DropdownMenuItem( + value: language.langCode, + child: Text( + language.getDisplayName(context) ?? language.langCode, + overflow: TextOverflow.clip, + textAlign: TextAlign.center, + ), + ); + }).toList(), + onChanged: (String? newValue) => { + setState(() => botOptions.targetLanguage = newValue!), + }, ), + const SizedBox(height: 12), + DropdownButtonFormField( + // Initial Value + hint: Text( + L10n.of(context)!.chooseVoice, + overflow: TextOverflow.clip, + textAlign: TextAlign.center, + ), + value: botOptions.targetVoice, + isExpanded: true, + icon: const Icon(Icons.keyboard_arrow_down), + items: const [], + onChanged: (String? newValue) => { + setState(() => botOptions.targetVoice = newValue!), + }, + ), + const SizedBox(height: 12), LanguageLevelDropdown( initialLevel: botOptions.languageLevel, onChanged: (int? newValue) => { @@ -53,15 +92,21 @@ class ConversationBotSettingsFormState botOptions.languageLevel = newValue!; }), }, + validator: (value) => + value == null ? L10n.of(context)!.enterLanguageLevel : null, ), - Text( - L10n.of(context)!.conversationBotModeSelectDescription, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - fontSize: 16, + const SizedBox(height: 20), + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Text( + L10n.of(context)!.conversationBotModeSelectDescription, + style: Theme.of(context).textTheme.titleLarge, + ), ), ), + const SizedBox(height: 12), ConversationBotModeSelect( initialMode: botOptions.mode, onChanged: (String? mode) => { @@ -70,18 +115,13 @@ class ConversationBotSettingsFormState }), }, ), - Padding( - padding: const EdgeInsets.all(12), - child: ConversationBotModeDynamicZone( - initialBotOptions: botOptions, - onChanged: (BotOptionsModel? newOptions) { - if (newOptions != null) { - setState(() { - botOptions = newOptions; - }); - } - }, - ), + const SizedBox(height: 12), + ConversationBotModeDynamicZone( + initialBotOptions: botOptions, + discussionTopicController: widget.discussionTopicController, + discussionKeywordsController: widget.discussionKeywordsController, + customSystemPromptController: widget.customSystemPromptController, + formKey: widget.formKey, ), ], ); diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_text_adventure_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_text_adventure_zone.dart index effbf70ee..ed2c41486 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_text_adventure_zone.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_text_adventure_zone.dart @@ -1,10 +1,8 @@ import 'package:fluffychat/pangea/models/bot_options_model.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_label.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_dynamic_zone_title.dart'; import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_text_adventure_game_master_instruction_input.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; +// TODO check how this looks class ConversationBotTextAdventureZone extends StatelessWidget { final BotOptionsModel initialBotOptions; // call this to update propagate changes to parents @@ -20,13 +18,6 @@ class ConversationBotTextAdventureZone extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ - ConversationBotDynamicZoneTitle( - title: L10n.of(context)!.conversationBotTextAdventureZone_title, - ), - ConversationBotDynamicZoneLabel( - label: L10n.of(context)! - .conversationBotTextAdventureZone_instructionLabel, - ), Padding( padding: const EdgeInsets.all(8), child: ConversationBotGameMasterInstructionsInput( diff --git a/lib/pangea/widgets/space/language_level_dropdown.dart b/lib/pangea/widgets/space/language_level_dropdown.dart index aeb1cfd36..0964a49ab 100644 --- a/lib/pangea/widgets/space/language_level_dropdown.dart +++ b/lib/pangea/widgets/space/language_level_dropdown.dart @@ -6,71 +6,44 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; class LanguageLevelDropdown extends StatelessWidget { final int? initialLevel; final void Function(int?)? onChanged; + final String? Function(int?)? validator; const LanguageLevelDropdown({ super.key, this.initialLevel, this.onChanged, + this.validator, }); @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(12.0), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Theme.of(context).colorScheme.secondary, - width: 0.5, - ), - borderRadius: const BorderRadius.all(Radius.circular(10)), - ), - child: DropdownButton( - // Initial Value - hint: Padding( - padding: const EdgeInsets.only(left: 15), - child: Text( - initialLevel == null - ? L10n.of(context)!.selectLanguageLevel - : LanguageLevelTextPicker.languageLevelText( - context, - initialLevel!, - ), - style: const TextStyle().copyWith( - color: Theme.of(context).textTheme.bodyLarge!.color, - fontSize: 14, - ), - overflow: TextOverflow.clip, - textAlign: TextAlign.center, + return DropdownButtonFormField( + // Initial Value + hint: Text( + L10n.of(context)!.selectLanguageLevel, + overflow: TextOverflow.clip, + textAlign: TextAlign.center, + ), + value: initialLevel, + isExpanded: true, + // Down Arrow Icon + icon: const Icon(Icons.keyboard_arrow_down), + // Array list of items + items: LanguageLevelType.allInts.map((int levelOption) { + return DropdownMenuItem( + value: levelOption, + child: Text( + LanguageLevelTextPicker.languageLevelText( + context, + levelOption, ), + overflow: TextOverflow.clip, + textAlign: TextAlign.center, ), - isExpanded: true, - underline: Container(), - // Down Arrow Icon - icon: const Icon(Icons.keyboard_arrow_down), - // Array list of items - items: LanguageLevelType.allInts.map((int levelOption) { - return DropdownMenuItem( - value: levelOption, - child: Text( - LanguageLevelTextPicker.languageLevelText( - context, - levelOption, - ), - style: const TextStyle().copyWith( - color: Theme.of(context).textTheme.bodyLarge!.color, - fontSize: 14, - ), - overflow: TextOverflow.clip, - textAlign: TextAlign.center, - ), - ); - }).toList(), - // After selecting the desired option,it will - // change button value to selected value - onChanged: onChanged, - ), - ), + ); + }).toList(), + onChanged: onChanged, + validator: validator, ); } } From 3a6d6de7c592eeab0593705659b1e608b0226391 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 21 Oct 2024 14:46:03 -0400 Subject: [PATCH 2/2] UI fixes for new groups, form validation for discussion topic --- assets/l10n/intl_en.arb | 3 +- lib/pages/new_group/new_group.dart | 14 ++++++ .../conversation_bot_mode_dynamic_zone.dart | 3 ++ .../conversation_bot_settings.dart | 45 ++++++++++++++----- .../conversation_bot_settings_form.dart | 3 +- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 555f319de..648153894 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4359,5 +4359,6 @@ "enterPrompt": "Please enter a system prompt", "selectBotLanguage": "Select bot language", "chooseVoice": "Choose a voice", - "enterLanguageLevel": "Please enter a language level" + "enterLanguageLevel": "Please enter a language level", + "enterDiscussionTopic": "Please enter a discussion topic" } \ No newline at end of file diff --git a/lib/pages/new_group/new_group.dart b/lib/pages/new_group/new_group.dart index 3d8301ec5..5d6a17012 100644 --- a/lib/pages/new_group/new_group.dart +++ b/lib/pages/new_group/new_group.dart @@ -106,6 +106,20 @@ class NewGroupController extends State { // #Pangea // validate init bot options + if (addConversationBotKey.currentState?.formKey.currentState != null) { + final isValid = addConversationBotKey + .currentState!.formKey.currentState! + .validate(); + if (isValid == false) { + setState(() { + error = L10n.of(context)! + .conversationBotCustomZone_customSystemPromptEmptyError; + loading = false; + }); + return; + } + } + addConversationBotKey.currentState?.updateAllBotOptions(); final addBot = addConversationBotKey.currentState?.addBot ?? false; if (addBot) { final botOptions = addConversationBotKey.currentState!.botOptions; diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart index 76aec7d62..dc1997a20 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart @@ -29,6 +29,9 @@ class ConversationBotModeDynamicZone extends StatelessWidget { .conversationBotDiscussionZone_discussionTopicPlaceholder, ), controller: discussionTopicController, + validator: (value) => value == null || value.isEmpty + ? L10n.of(context)!.enterDiscussionTopic + : null, ), const SizedBox(height: 12), TextFormField( diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart index 3a8cc53ff..963949a78 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart @@ -99,6 +99,12 @@ class ConversationBotSettingsState extends State { ); } + void updateAllBotOptions() { + botOptions.discussionTopic = discussionTopicController.text; + botOptions.discussionKeywords = discussionKeywordsController.text; + botOptions.customSystemPrompt = customSystemPromptController.text; + } + Future showBotOptionsDialog() async { if (isCreating) return; final bool? confirm = await showDialog( @@ -135,10 +141,7 @@ class ConversationBotSettingsState extends State { ); if (confirm == true) { - botOptions.discussionTopic = discussionTopicController.text; - botOptions.discussionKeywords = discussionKeywordsController.text; - botOptions.customSystemPrompt = customSystemPromptController.text; - + updateAllBotOptions(); updateBotOption(() => botOptions = botOptions); final bool isBotRoomMember = await widget.room?.botIsInRoom ?? false; @@ -241,12 +244,34 @@ class ConversationBotSettingsState extends State { onTap: showBotOptionsDialog, ), if (isCreating && addBot) - ConversationBotSettingsForm( - botOptions: botOptions, - formKey: formKey, - discussionKeywordsController: discussionKeywordsController, - discussionTopicController: discussionTopicController, - customSystemPromptController: customSystemPromptController, + Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Text( + L10n.of(context)!.botConfig, + style: Theme.of(context).textTheme.titleLarge, + ), + ), + ), + Form( + key: formKey, + child: ConversationBotSettingsForm( + botOptions: botOptions, + formKey: formKey, + discussionKeywordsController: + discussionKeywordsController, + discussionTopicController: discussionTopicController, + customSystemPromptController: + customSystemPromptController, + ), + ), + ], + ), ), ], ), diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart index fb482ab1c..5447b67bb 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart @@ -95,7 +95,7 @@ class ConversationBotSettingsFormState validator: (value) => value == null ? L10n.of(context)!.enterLanguageLevel : null, ), - const SizedBox(height: 20), + const SizedBox(height: 12), Align( alignment: Alignment.centerLeft, child: Padding( @@ -106,7 +106,6 @@ class ConversationBotSettingsFormState ), ), ), - const SizedBox(height: 12), ConversationBotModeSelect( initialMode: botOptions.mode, onChanged: (String? mode) => {