diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 58db298d0..9674f45fc 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4497,5 +4497,6 @@ "enterDiscussionTopic": "Please enter a discussion topic", "selectBotChatMode": "Select chat mode", "messageNotInTargetLang": "Message not in target language", - "other": "Other" + "other": "Other", + "botModeValidation": "Please select a chat mode" } \ No newline at end of file diff --git a/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart index 4199e6f64..c9baaacaa 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart @@ -62,9 +62,9 @@ extension RoomSettingsRoomExtension on Room { BotOptionsModel? get _botOptions { if (isSpace) return null; - return BotOptionsModel.fromJson( - getState(PangeaEventTypes.botOptions)?.content ?? {}, - ); + final stateEvent = getState(PangeaEventTypes.botOptions); + if (stateEvent == null) return null; + return BotOptionsModel.fromJson(stateEvent.content); } Future _isSuggested() async { 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 e691cbcb5..69a2dd9b2 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,10 +1,9 @@ import 'package:fluffychat/pangea/constants/bot_mode.dart'; -import 'package:fluffychat/pangea/models/bot_options_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; class ConversationBotModeDynamicZone extends StatelessWidget { - final BotOptionsModel botOptions; + final String? mode; final TextEditingController discussionTopicController; final TextEditingController discussionKeywordsController; final TextEditingController customSystemPromptController; @@ -13,11 +12,11 @@ class ConversationBotModeDynamicZone extends StatelessWidget { const ConversationBotModeDynamicZone({ super.key, - required this.botOptions, required this.discussionTopicController, required this.discussionKeywordsController, required this.customSystemPromptController, this.enabled = true, + this.mode, }); @override @@ -33,7 +32,7 @@ class ConversationBotModeDynamicZone extends StatelessWidget { ), controller: discussionTopicController, validator: (value) => enabled && - botOptions.mode == BotMode.discussion && + mode == BotMode.discussion && (value == null || value.isEmpty) ? L10n.of(context)!.enterDiscussionTopic : null, @@ -67,7 +66,7 @@ class ConversationBotModeDynamicZone extends StatelessWidget { contentPadding: const EdgeInsets.symmetric(horizontal: 28.0), ), validator: (value) => enabled && - botOptions.mode == BotMode.custom && + mode == BotMode.custom && (value == null || value.isEmpty) ? L10n.of(context)!.enterPrompt : null, @@ -81,8 +80,8 @@ class ConversationBotModeDynamicZone extends StatelessWidget { return Column( children: [ - if (botOptions.mode == BotMode.discussion) ...discussionChildren, - if (botOptions.mode == BotMode.custom) ...customChildren, + if (mode == BotMode.discussion) ...discussionChildren, + if (mode == BotMode.custom) ...customChildren, const SizedBox(height: 12), CheckboxListTile( title: Text( @@ -90,7 +89,7 @@ class ConversationBotModeDynamicZone extends StatelessWidget { .conversationBotCustomZone_customTriggerReactionEnabledLabel, ), enabled: false, - value: botOptions.customTriggerReactionEnabled ?? true, + value: 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 408e6560e..50565d85b 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart @@ -7,12 +7,14 @@ class ConversationBotModeSelect extends StatelessWidget { final String? initialMode; final void Function(String?) onChanged; final bool enabled; + final String? Function(String?)? validator; const ConversationBotModeSelect({ super.key, this.initialMode, required this.onChanged, this.enabled = true, + this.validator, }); @override @@ -41,6 +43,8 @@ class ConversationBotModeSelect extends StatelessWidget { ), ], onChanged: enabled ? onChanged : null, + validator: validator, + value: initialMode, ); } } diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart index e30429214..e6530ad3e 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart @@ -112,6 +112,8 @@ class ConversationBotSettingsDialogState final TextEditingController customSystemPromptController = TextEditingController(); + bool hasUpdatedMode = false; + @override void initState() { super.initState(); @@ -126,6 +128,8 @@ class ConversationBotSettingsDialogState discussionKeywordsController.text = botOptions.discussionKeywords ?? ""; discussionTopicController.text = botOptions.discussionTopic ?? ""; customSystemPromptController.text = botOptions.customSystemPrompt ?? ""; + + hasUpdatedMode = widget.room.botOptions != null; } final GlobalKey formKey = GlobalKey(); @@ -137,6 +141,7 @@ class ConversationBotSettingsDialogState } void onUpdateChatMode(String? mode) { + hasUpdatedMode = true; setState(() => botOptions.mode = mode ?? BotMode.discussion); } @@ -217,6 +222,7 @@ class ConversationBotSettingsDialogState customSystemPromptController: customSystemPromptController, enabled: addBot, + hasUpdatedMode: hasUpdatedMode, onUpdateBotMode: onUpdateChatMode, onUpdateBotLanguage: onUpdateBotLanguage, onUpdateBotVoice: onUpdateBotVoice, @@ -244,6 +250,8 @@ class ConversationBotSettingsDialogState if (!isValid) return; updateFromTextControllers(); + botOptions.targetLanguage ??= MatrixState + .pangeaController.languageController.userL2?.langCode; Navigator.of(context).pop(botOptions); 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 6b5535bc4..7c7c7525c 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart @@ -15,6 +15,8 @@ class ConversationBotSettingsForm extends StatelessWidget { final TextEditingController customSystemPromptController; final bool enabled; + final bool hasUpdatedMode; + final void Function(String?) onUpdateBotMode; final void Function(String?) onUpdateBotLanguage; final void Function(String?) onUpdateBotVoice; @@ -31,6 +33,7 @@ class ConversationBotSettingsForm extends StatelessWidget { required this.onUpdateBotVoice, required this.onUpdateBotLanguageLevel, this.enabled = true, + this.hasUpdatedMode = false, }); @override @@ -94,17 +97,20 @@ class ConversationBotSettingsForm extends StatelessWidget { ), ), ConversationBotModeSelect( - initialMode: botOptions.mode, + initialMode: hasUpdatedMode ? botOptions.mode : null, onChanged: onUpdateBotMode, enabled: enabled, + validator: (value) { + return value == null ? L10n.of(context)!.botModeValidation : null; + }, ), const SizedBox(height: 12), ConversationBotModeDynamicZone( - botOptions: botOptions, discussionTopicController: discussionTopicController, discussionKeywordsController: discussionKeywordsController, customSystemPromptController: customSystemPromptController, enabled: enabled, + mode: hasUpdatedMode ? botOptions.mode : null, ), ], );