disable updating bot config if insufficient power level, remove respond on next reactions input (#1228)

* disable updating bot config if insufficient power level, remove respond on next reactions input

* comment .env file in pubspec.yaml

---------

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
Co-authored-by: ggurdin <ggurdin@gmail.com>
This commit is contained in:
Wilson 2024-12-12 14:04:36 -05:00 committed by GitHub
parent ad64031688
commit 3435658dbb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 176 additions and 117 deletions

View file

@ -4040,8 +4040,9 @@
"conversationBotCustomZone_customSystemPromptLabel": "System prompt",
"conversationBotCustomZone_customSystemPromptPlaceholder": "Set custom system prompt",
"conversationBotCustomZone_customSystemPromptEmptyError": "Missing custom system prompt",
"conversationBotCustomZone_customTriggerReactionEnabledLabel": "Responds on ⏩ reaction",
"botConfig": "Bot and activity settings",
"botConfigNoPermissionTitle": "No permission",
"botConfigNoPermissionMessage": "Contact room admin to change bot configuration",
"addConversationBotDialogTitleInvite": "Confirm inviting conversation bot",
"addConversationBotButtonInvite": "Invite",
"addConversationBotDialogInviteConfirmation": "Invite",

View file

@ -4816,7 +4816,6 @@
"conversationBotCustomZone_customSystemPromptLabel": "Mensaje del sistema",
"conversationBotCustomZone_customSystemPromptPlaceholder": "Establecer mensaje del sistema personalizado",
"conversationBotCustomZone_customSystemPromptEmptyError": "Falta mensaje del sistema personalizado",
"conversationBotCustomZone_customTriggerReactionEnabledLabel": "Responde a la reacción ⏩",
"addConversationBotDialogTitleInvite": "Confirmar la invitación del bot de conversación",
"addConversationBotButtonInvite": "Invitar",
"addConversationBotDialogInviteConfirmation": "Invitar",

View file

@ -1,4 +1,5 @@
import 'package:fluffychat/pangea/constants/bot_mode.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_no_permission_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
@ -9,12 +10,14 @@ class ConversationBotModeDynamicZone extends StatelessWidget {
final TextEditingController customSystemPromptController;
final bool enabled;
final bool hasPermission;
const ConversationBotModeDynamicZone({
super.key,
required this.discussionTopicController,
required this.discussionKeywordsController,
required this.customSystemPromptController,
required this.hasPermission,
this.enabled = true,
this.mode,
});
@ -22,59 +25,68 @@ class ConversationBotModeDynamicZone extends StatelessWidget {
@override
Widget build(BuildContext context) {
final discussionChildren = [
TextFormField(
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
decoration: InputDecoration(
hintText: L10n.of(context)
.conversationBotDiscussionZone_discussionTopicPlaceholder,
contentPadding:
const EdgeInsets.symmetric(horizontal: 28.0, vertical: 12.0),
InkWell(
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
child: TextFormField(
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
decoration: InputDecoration(
hintText: L10n.of(context)
.conversationBotDiscussionZone_discussionTopicPlaceholder,
contentPadding:
const EdgeInsets.symmetric(horizontal: 28.0, vertical: 12.0),
),
controller: discussionTopicController,
validator: (value) => enabled &&
mode == BotMode.discussion &&
(value == null || value.isEmpty)
? L10n.of(context).enterDiscussionTopic
: null,
enabled: hasPermission && enabled,
minLines: 1, // Minimum number of lines
maxLines: null, // Allow the field to expand based on content
keyboardType: TextInputType.multiline,
),
controller: discussionTopicController,
validator: (value) => enabled &&
mode == BotMode.discussion &&
(value == null || value.isEmpty)
? L10n.of(context).enterDiscussionTopic
: null,
enabled: enabled,
minLines: 1, // Minimum number of lines
maxLines: null, // Allow the field to expand based on content
keyboardType: TextInputType.multiline,
),
const SizedBox(height: 12),
TextFormField(
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
decoration: InputDecoration(
hintText: L10n.of(context)
.conversationBotDiscussionZone_discussionKeywordsPlaceholder,
contentPadding: const EdgeInsets.symmetric(horizontal: 28.0),
InkWell(
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
child: TextFormField(
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
decoration: InputDecoration(
hintText: L10n.of(context)
.conversationBotDiscussionZone_discussionKeywordsPlaceholder,
contentPadding: const EdgeInsets.symmetric(horizontal: 28.0),
),
controller: discussionKeywordsController,
enabled: hasPermission && enabled,
minLines: 1, // Minimum number of lines
maxLines: null, // Allow the field to expand based on content
keyboardType: TextInputType.multiline,
),
controller: discussionKeywordsController,
enabled: enabled,
minLines: 1, // Minimum number of lines
maxLines: null, // Allow the field to expand based on content
keyboardType: TextInputType.multiline,
),
];
final customChildren = [
TextFormField(
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
decoration: InputDecoration(
hintText: L10n.of(context)
.conversationBotCustomZone_customSystemPromptPlaceholder,
contentPadding: const EdgeInsets.symmetric(horizontal: 28.0),
InkWell(
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
child: TextFormField(
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
decoration: InputDecoration(
hintText: L10n.of(context)
.conversationBotCustomZone_customSystemPromptPlaceholder,
contentPadding: const EdgeInsets.symmetric(horizontal: 28.0),
),
validator: (value) => enabled &&
mode == BotMode.custom &&
(value == null || value.isEmpty)
? L10n.of(context).enterPrompt
: null,
controller: customSystemPromptController,
enabled: hasPermission && enabled,
minLines: 1, // Minimum number of lines
maxLines: null, // Allow the field to expand based on content
keyboardType: TextInputType.multiline,
),
validator: (value) => enabled &&
mode == BotMode.custom &&
(value == null || value.isEmpty)
? L10n.of(context).enterPrompt
: null,
controller: customSystemPromptController,
enabled: enabled,
minLines: 1, // Minimum number of lines
maxLines: null, // Allow the field to expand based on content
keyboardType: TextInputType.multiline,
),
];
@ -83,16 +95,6 @@ class ConversationBotModeDynamicZone extends StatelessWidget {
if (mode == BotMode.discussion) ...discussionChildren,
if (mode == BotMode.custom) ...customChildren,
const SizedBox(height: 12),
CheckboxListTile(
title: Text(
L10n.of(context)
.conversationBotCustomZone_customTriggerReactionEnabledLabel,
),
enabled: false,
value: true,
onChanged: null,
),
const SizedBox(height: 12),
],
);
}

View file

@ -5,7 +5,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
class ConversationBotModeSelect extends StatelessWidget {
final String? initialMode;
final void Function(String?) onChanged;
final void Function(String?)? onChanged;
final bool enabled;
final String? Function(String?)? validator;

View file

@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
Future<void> showNoPermissionDialog(BuildContext context) {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(L10n.of(context).botConfigNoPermissionTitle),
content: Text(L10n.of(context).botConfigNoPermissionMessage),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(L10n.of(context).ok),
),
],
);
},
);
}

View file

@ -8,6 +8,7 @@ import 'package:fluffychat/pangea/models/bot_options_model.dart';
import 'package:fluffychat/pangea/utils/bot_name.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/pangea/widgets/common/bot_face_svg.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_no_permission_dialog.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings_form.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/foundation.dart';
@ -113,6 +114,7 @@ class ConversationBotSettingsDialogState
TextEditingController();
bool hasUpdatedMode = false;
bool hasPermission = false;
@override
void initState() {
@ -124,6 +126,9 @@ class ConversationBotSettingsDialogState
widget.room.botIsInRoom.then((bool isBotRoom) {
setState(() => addBot = isBotRoom);
});
hasPermission =
widget.room.powerForChangingStateEvent(PangeaEventTypes.botOptions) <=
widget.room.ownPowerLevel;
discussionKeywordsController.text = botOptions.discussionKeywords ?? "";
discussionTopicController.text = botOptions.discussionTopic ?? "";
@ -193,15 +198,22 @@ class ConversationBotSettingsDialogState
),
],
),
SwitchListTile(
title: Text(
L10n.of(context).conversationBotStatus,
InkWell(
onTap: hasPermission
? null
: () => showNoPermissionDialog(context),
child: SwitchListTile(
title: Text(
L10n.of(context).conversationBotStatus,
),
value: addBot,
onChanged: hasPermission
? (bool value) {
setState(() => addBot = value);
}
: null, // Keeps the switch disabled
contentPadding: const EdgeInsets.all(4),
),
value: addBot,
onChanged: (bool value) {
setState(() => addBot = value);
},
contentPadding: const EdgeInsets.all(4),
),
Expanded(
child: SingleChildScrollView(
@ -221,6 +233,7 @@ class ConversationBotSettingsDialogState
discussionTopicController,
customSystemPromptController:
customSystemPromptController,
hasPermission: hasPermission,
enabled: addBot,
hasUpdatedMode: hasUpdatedMode,
onUpdateBotMode: onUpdateChatMode,
@ -237,15 +250,20 @@ class ConversationBotSettingsDialogState
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
Navigator.of(context).pop(null);
},
child: Text(L10n.of(context).cancel),
),
if (hasPermission)
TextButton(
onPressed: () {
Navigator.of(context).pop(null);
},
child: Text(L10n.of(context).cancel),
),
const SizedBox(width: 20),
TextButton(
onPressed: () async {
if (!hasPermission) {
Navigator.of(context).pop(null);
return;
}
final isValid = formKey.currentState!.validate();
if (!isValid) return;
@ -263,7 +281,9 @@ class ConversationBotSettingsDialogState
await widget.room.kick(BotName.byEnvironment);
}
},
child: Text(L10n.of(context).confirm),
child: hasPermission
? Text(L10n.of(context).confirm)
: Text(L10n.of(context).close),
),
],
),

View file

@ -2,6 +2,7 @@ import 'package:dropdown_button2/dropdown_button2.dart';
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/conversation_bot/conversation_bot_no_permission_dialog.dart';
import 'package:fluffychat/pangea/widgets/space/language_level_dropdown.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
@ -16,6 +17,7 @@ class ConversationBotSettingsForm extends StatelessWidget {
final bool enabled;
final bool hasUpdatedMode;
final bool hasPermission;
final void Function(String?) onUpdateBotMode;
final void Function(String?) onUpdateBotLanguage;
@ -32,6 +34,7 @@ class ConversationBotSettingsForm extends StatelessWidget {
required this.onUpdateBotLanguage,
required this.onUpdateBotVoice,
required this.onUpdateBotLanguageLevel,
required this.hasPermission,
this.enabled = true,
this.hasUpdatedMode = false,
});
@ -40,50 +43,60 @@ class ConversationBotSettingsForm extends StatelessWidget {
Widget build(BuildContext context) {
return Column(
children: [
DropdownButtonFormField2(
dropdownStyleData: const DropdownStyleData(
padding: EdgeInsets.zero,
InkWell(
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
child: DropdownButtonFormField2(
dropdownStyleData: const DropdownStyleData(
padding: EdgeInsets.zero,
),
hint: Text(
L10n.of(context).selectBotLanguage,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
),
value: botOptions.targetLanguage,
isExpanded: true,
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: hasPermission && enabled ? onUpdateBotLanguage : null,
),
hint: Text(
L10n.of(context).selectBotLanguage,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
),
value: botOptions.targetLanguage,
isExpanded: true,
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: enabled ? onUpdateBotLanguage : null,
),
const SizedBox(height: 12),
DropdownButtonFormField2<String>(
hint: Text(
L10n.of(context).chooseVoice,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
InkWell(
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
child: DropdownButtonFormField2<String>(
hint: Text(
L10n.of(context).chooseVoice,
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
),
value: botOptions.targetVoice,
isExpanded: true,
items: const [],
onChanged: hasPermission && enabled ? onUpdateBotVoice : null,
),
value: botOptions.targetVoice,
isExpanded: true,
items: const [],
onChanged: enabled ? onUpdateBotVoice : null,
),
const SizedBox(height: 12),
LanguageLevelDropdown(
initialLevel: botOptions.languageLevel,
onChanged: onUpdateBotLanguageLevel,
validator: (value) => enabled && value == null
? L10n.of(context).enterLanguageLevel
: null,
enabled: enabled,
InkWell(
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
child: LanguageLevelDropdown(
initialLevel: botOptions.languageLevel,
onChanged:
hasPermission && enabled ? onUpdateBotLanguageLevel : null,
validator: (value) => enabled && value == null
? L10n.of(context).enterLanguageLevel
: null,
enabled: enabled,
),
),
const SizedBox(height: 12),
Align(
@ -96,13 +109,16 @@ class ConversationBotSettingsForm extends StatelessWidget {
),
),
),
ConversationBotModeSelect(
initialMode: hasUpdatedMode ? botOptions.mode : null,
onChanged: onUpdateBotMode,
enabled: enabled,
validator: (value) {
return value == null ? L10n.of(context).botModeValidation : null;
},
InkWell(
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
child: ConversationBotModeSelect(
initialMode: hasUpdatedMode ? botOptions.mode : null,
onChanged: hasPermission && enabled ? onUpdateBotMode : null,
enabled: enabled,
validator: (value) {
return value == null ? L10n.of(context).botModeValidation : null;
},
),
),
const SizedBox(height: 12),
ConversationBotModeDynamicZone(
@ -110,6 +126,7 @@ class ConversationBotSettingsForm extends StatelessWidget {
discussionKeywordsController: discussionKeywordsController,
customSystemPromptController: customSystemPromptController,
enabled: enabled,
hasPermission: hasPermission,
mode: hasUpdatedMode ? botOptions.mode : null,
),
],