merge conflicts

pull/1011/head
ggurdin 2 years ago
commit 8d77ca8951

@ -3875,5 +3875,15 @@
"placeholders": {}
},
"define": "Define",
"listen": "Listen"
"listen": "Listen",
"addConversationBot": "Enable Conversation Bot",
"addConversationBotDesc": "Add a bot to this group chat that will ask questions on a specific topic",
"convoBotSettingsTitle": "Conversation Bot Settings",
"convoBotSettingsDescription": "Edit conversation topic and difficulty",
"enterAConversationTopic": "Enter a conversation topic",
"conversationTopic": "Conversation topic",
"enableModeration": "Enable moderation",
"enableModerationDesc": "Enable automatic moderation to review messages before they are sent",
"conversationLanguageLevel": "What is the language level of this conversation?",
"showDefinition": "Show Definition"
}

@ -2872,8 +2872,8 @@
"type": "text",
"placeholders": {}
},
"langaugeLevel": "Nivel de lengua",
"@langaugeLevel": {
"languageLevel": "Nivel de lengua",
"@languageLevel": {
"type": "text",
"placeholders": {}
},
@ -4534,5 +4534,14 @@
"placeholders": {
"roomName": {}
}
}
},
"addConversationBot": "Añadir bot de conversación",
"addConversationBotDesc": "Añadir un bot de conversación para enviar mensajes automáticos a este chat",
"convoBotSettingsTitle": "Configuración del bot de conversación",
"convoBotSettingsDescription": "Editar tema de conversación y dificultad",
"enterAConversationTopic": "Introducir un tema de conversación",
"conversationTopic": "Tema de conversación",
"enableModeration": "Activar la moderación",
"enableModerationDesc": "Activar la moderación automática para revisar los mensajes antes de enviarlos",
"conversationLanguageLevel": "¿Cuál es el nivel lingüístico de esta conversación?"
}

@ -3,8 +3,6 @@
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.im.fluffychat.app</string>
</array>
<array/>
</dict>
</plist>

@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>

@ -457,7 +457,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@ -546,7 +546,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -595,7 +595,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;

@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@ -38,8 +36,8 @@
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@ -61,8 +59,6 @@
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"

@ -1,25 +1,24 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
import 'package:matrix/matrix.dart' as matrix;
import 'package:matrix/matrix.dart';
import 'package:fluffychat/pages/chat_details/chat_details_view.dart';
import 'package:fluffychat/pages/settings/settings.dart';
import 'package:fluffychat/pangea/utils/set_class_name.dart';
import 'package:fluffychat/pangea/utils/set_class_topic.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/app_lock.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
import 'package:matrix/matrix.dart' as matrix;
import 'package:matrix/matrix.dart';
enum AliasActions { copy, delete, setCanonical }
@ -45,6 +44,8 @@ class ChatDetailsController extends State<ChatDetails> {
// #Pangea
final GlobalKey<AddToSpaceState> addToSpaceKey = GlobalKey<AddToSpaceState>();
final GlobalKey<ConversationBotSettingsState> addConversationBotKey =
GlobalKey<ConversationBotSettingsState>();
bool displayAddStudentOptions = false;
void toggleAddStudentOptions() =>
@ -424,5 +425,11 @@ class ChatDetailsController extends State<ChatDetails> {
bool showEditNameIcon = false;
void hoverEditNameIcon(bool hovering) =>
setState(() => showEditNameIcon = !showEditNameIcon);
@override
void initState() {
super.initState();
MatrixState.pangeaController.classController.addMissingRoomRules(roomId);
}
// Pangea#
}

@ -12,6 +12,7 @@ import 'package:fluffychat/pangea/utils/archive_space.dart';
import 'package:fluffychat/pangea/utils/lock_room.dart';
import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/pangea/widgets/space/class_settings.dart';
import 'package:fluffychat/utils/fluffy_share.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
@ -489,6 +490,13 @@ class ChatDetailsView extends StatelessWidget {
if (controller.displayAddStudentOptions &&
room.showClassEditOptions)
ClassInvitationButtons(roomId: controller.roomId!),
const Divider(height: 1),
if (!room.isSpace && room.canInvite)
ConversationBotSettings(
key: controller.addConversationBotKey,
room: room,
),
const Divider(height: 1),
if (!room.isPangeaClass)
AddToSpaceToggles(
roomId: room.id,

@ -1,20 +1,20 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart' as sdk;
import 'package:fluffychat/pages/new_group/new_group_view.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/models/chat_topic_model.dart';
import 'package:fluffychat/pangea/models/lemma.dart';
import 'package:fluffychat/pangea/utils/bot_name.dart';
import 'package:fluffychat/pangea/utils/class_chat_power_levels.dart';
import 'package:fluffychat/pangea/utils/firebase_analytics.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart' as sdk;
class NewGroup extends StatefulWidget {
const NewGroup({super.key});
@ -42,6 +42,8 @@ class NewGroupController extends State<NewGroup> {
// #Pangea
PangeaController pangeaController = MatrixState.pangeaController;
final GlobalKey<AddToSpaceState> addToSpaceKey = GlobalKey<AddToSpaceState>();
final GlobalKey<ConversationBotSettingsState> addConversationBotKey =
GlobalKey<ConversationBotSettingsState>();
ChatTopic chatTopic = ChatTopic.empty;
@ -121,6 +123,10 @@ class NewGroupController extends State<NewGroup> {
.map((suggestionStatus) => suggestionStatus.room)
.toList(),
),
invite: [
if (addConversationBotKey.currentState?.addBot ?? false)
BotName.byEnvironment,
],
// Pangea#
);
if (!mounted) return;

@ -1,14 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/new_group/new_group.dart';
import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
class NewGroupView extends StatelessWidget {
final NewGroupController controller;
@ -85,6 +84,10 @@ class NewGroupView extends StatelessWidget {
// ),
// ),
// ),
ConversationBotSettings(
key: controller.addConversationBotKey,
),
const Divider(height: 1),
AddToSpaceToggles(
key: controller.addToSpaceKey,
startOpen: false,

@ -89,4 +89,10 @@ class ModelKey {
static const String feedbackLang = "feedback_lang";
static const String transcription = "transcription";
// bot options
static const String languageLevel = "difficulty";
static const String conversationTopic = "conversation_topic";
static const String keywords = "keywords";
static const String safetyModeration = "safety_moderation";
}

@ -15,4 +15,5 @@ class PangeaEventTypes {
static const roomInfo = "pangea.roomtopic";
static const audio = "p.audio";
static const botOptions = "pangea.bot_options";
}

@ -3,9 +3,11 @@ import 'dart:developer';
import 'package:collection/collection.dart';
import 'package:fluffychat/pangea/constants/local.key.dart';
import 'package:fluffychat/pangea/constants/pangea_event_types.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/extensions/client_extension.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
import 'package:fluffychat/pangea/models/class_model.dart';
import 'package:fluffychat/pangea/utils/class_code.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:flutter/foundation.dart';
@ -156,4 +158,24 @@ class ClassController extends BaseController {
// BE - check class code and if class code is correct, invite student to room
// FE - look for invite from room and automatically accept
}
Future<void> addMissingRoomRules(String? roomId) async {
if (roomId == null) return;
final Room? room = _pangeaController.matrixState.client.getRoomById(roomId);
if (room == null) return;
if (room.classSettings != null && room.pangeaRoomRules == null) {
try {
await _pangeaController.matrixState.client.setRoomStateWithKey(
roomId,
PangeaEventTypes.rules,
'',
PangeaRoomRules().toJson(),
);
} catch (err, stack) {
debugger(when: kDebugMode);
ErrorHandler.logError(e: err, s: stack);
}
}
}
}

@ -4,6 +4,7 @@ import 'dart:developer';
import 'package:fluffychat/pangea/constants/class_default_values.dart';
import 'package:fluffychat/pangea/constants/model_keys.dart';
import 'package:fluffychat/pangea/constants/pangea_room_types.dart';
import 'package:fluffychat/pangea/models/bot_options_model.dart';
import 'package:fluffychat/pangea/models/class_model.dart';
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
import 'package:fluffychat/pangea/utils/bot_name.dart';
@ -980,4 +981,18 @@ extension PangeaRoom on Room {
if (!isSpace) return null;
return pangeaRoomRulesStateEvent?.originServerTs ?? creationTime;
}
Future<bool> get isBotRoom async {
final List<User> participants = await requestParticipants();
return participants.any(
(User user) => user.id == BotName.byEnvironment,
);
}
BotOptionsModel? get botOptions {
if (isSpace) return null;
return BotOptionsModel.fromJson(
getState(PangeaEventTypes.botOptions)?.content ?? {},
);
}
}

@ -0,0 +1,72 @@
import 'dart:developer';
import 'package:fluffychat/pangea/constants/model_keys.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:flutter/foundation.dart';
import 'package:matrix/matrix.dart';
import '../constants/pangea_event_types.dart';
class BotOptionsModel {
int? languageLevel;
String topic;
List<String> keywords;
bool safetyModeration;
BotOptionsModel({
this.languageLevel,
this.topic = "General Conversation",
this.keywords = const [],
this.safetyModeration = true,
});
factory BotOptionsModel.fromJson(json) {
return BotOptionsModel(
languageLevel: json[ModelKey.languageLevel],
topic: json[ModelKey.conversationTopic] ?? "General Conversation",
keywords: (json[ModelKey.keywords] ?? []).cast<String>(),
safetyModeration: json[ModelKey.safetyModeration] ?? true,
);
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
try {
// data[ModelKey.isConversationBotChat] = isConversationBotChat;
data[ModelKey.languageLevel] = languageLevel;
data[ModelKey.conversationTopic] = topic;
data[ModelKey.keywords] = keywords;
data[ModelKey.safetyModeration] = safetyModeration;
return data;
} catch (e, s) {
debugger(when: kDebugMode);
ErrorHandler.logError(e: e, s: s);
return data;
}
}
//TODO: define enum with all possible values
updateBotOption(String key, dynamic value) {
switch (key) {
case ModelKey.languageLevel:
languageLevel = value;
break;
case ModelKey.conversationTopic:
topic = value;
break;
case ModelKey.keywords:
keywords = value;
break;
case ModelKey.safetyModeration:
safetyModeration = value;
break;
default:
throw Exception('Invalid key for bot options - $key');
}
}
StateEvent get toStateEvent => StateEvent(
content: toJson(),
type: PangeaEventTypes.botOptions,
);
}

@ -1,4 +1,5 @@
import 'dart:async';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat/chat.dart';
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
@ -161,8 +162,8 @@ class MessageToolbarState extends State<MessageToolbar> {
case MessageMode.play:
return true;
case MessageMode.definition:
debugPrint("checking");
return widget.textSelection.selectedText != null;
// return widget.textSelection.selectedText != null;
return true;
default:
return false;
}

@ -1,8 +1,9 @@
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat/events/message_content.dart';
import 'package:fluffychat/pangea/models/language_model.dart';
import 'package:fluffychat/pangea/enum/use_type.dart';
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
import 'package:fluffychat/utils/date_time_extension.dart';
import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';
@ -102,16 +103,64 @@ class OverlayMessage extends StatelessWidget {
constraints: BoxConstraints(
maxWidth: width ?? FluffyThemes.columnWidth * 1.25,
),
child: MessageContent(
event,
textColor: textColor,
borderRadius: borderRadius,
selected: selected,
pangeaMessageEvent: pangeaMessageEvent,
// selectedDisplayLang: selectedDisplayLang,
immersionMode: immersionMode,
// definitions: definitions,
toolbarController: toolbarController,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MessageContent(
event,
textColor: textColor,
borderRadius: borderRadius,
selected: selected,
pangeaMessageEvent: pangeaMessageEvent,
immersionMode: immersionMode,
toolbarController: toolbarController,
),
if (event.hasAggregatedEvents(
timeline,
RelationshipTypes.edit,
) // #Pangea
||
(pangeaMessageEvent.showUseType)
// Pangea#
)
Padding(
padding: const EdgeInsets.only(
top: 4.0,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// #Pangea
if (pangeaMessageEvent.showUseType) ...[
pangeaMessageEvent.useType.iconView(
context,
textColor.withAlpha(164),
),
const SizedBox(width: 4),
],
if (event.hasAggregatedEvents(
timeline,
RelationshipTypes.edit,
)) ...[
// Pangea#
Icon(
Icons.edit_outlined,
color: textColor.withAlpha(164),
size: 14,
),
Text(
' - ${event.originServerTs.localizedTimeShort(context)}',
style: TextStyle(
color: textColor.withAlpha(164),
fontSize: 12,
),
),
],
],
),
),
],
),
),
);

@ -0,0 +1,245 @@
import 'dart:developer';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/models/bot_options_model.dart';
import 'package:fluffychat/pangea/utils/bot_name.dart';
import 'package:fluffychat/pangea/widgets/common/bot_face_svg.dart';
import 'package:fluffychat/pangea/widgets/space/language_level_dropdown.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart';
import '../../../widgets/matrix.dart';
import '../../constants/pangea_event_types.dart';
import '../../extensions/pangea_room_extension.dart';
import '../../utils/error_handler.dart';
class ConversationBotSettings extends StatefulWidget {
final Room? room;
final bool startOpen;
// final ClassSettingsModel? initialSettings;
const ConversationBotSettings({
super.key,
this.room,
this.startOpen = false,
// this.initialSettings,
});
@override
ConversationBotSettingsState createState() => ConversationBotSettingsState();
}
class ConversationBotSettingsState extends State<ConversationBotSettings> {
late BotOptionsModel botOptions;
late bool isOpen;
bool addBot = false;
ConversationBotSettingsState({Key? key});
@override
void initState() {
super.initState();
isOpen = widget.startOpen;
botOptions = widget.room?.botOptions ?? BotOptionsModel();
widget.room?.isBotRoom.then((bool isBotRoom) {
setState(() {
addBot = isBotRoom;
});
});
}
Future<void> updateBotOption(void Function() makeLocalChange) async {
makeLocalChange();
await showFutureLoadingDialog(
context: context,
future: () async {
try {
await setBotOption();
} catch (err, stack) {
debugger(when: kDebugMode);
ErrorHandler.logError(e: err, s: stack);
}
setState(() {});
},
);
}
Future<void> setBotOption() async {
if (widget.room == null) return;
try {
await Matrix.of(context).client.setRoomStateWithKey(
widget.room!.id,
PangeaEventTypes.botOptions,
'',
botOptions.toJson(),
);
} catch (err, stack) {
debugger(when: kDebugMode);
ErrorHandler.logError(e: err, s: stack);
}
}
@override
Widget build(BuildContext context) => Column(
children: [
ListTile(
title: Text(
L10n.of(context)!.convoBotSettingsTitle,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
subtitle: Text(L10n.of(context)!.convoBotSettingsDescription),
leading: CircleAvatar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor: Theme.of(context).textTheme.bodyLarge!.color,
child: const Icon(Icons.psychology_outlined),
),
trailing: Icon(
isOpen
? Icons.keyboard_arrow_down_outlined
: Icons.keyboard_arrow_right_outlined,
),
onTap: () => setState(() => isOpen = !isOpen),
),
if (isOpen)
AnimatedContainer(
duration: const Duration(milliseconds: 300),
height: isOpen ? null : 0,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 16),
child: SwitchListTile.adaptive(
title: Text(
L10n.of(context)!.addConversationBot,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
subtitle: Text(L10n.of(context)!.addConversationBotDesc),
secondary: CircleAvatar(
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor:
Theme.of(context).textTheme.bodyLarge!.color,
child: const BotFace(
width: 30.0,
expression: BotExpression.right,
),
),
activeColor: AppConfig.activeToggleColor,
value: addBot,
onChanged: (bool add) {
setState(() => addBot = add);
add
? widget.room?.invite(BotName.byEnvironment)
: widget.room?.kick(BotName.byEnvironment);
},
),
),
if (addBot) ...[
Padding(
padding: const EdgeInsets.only(left: 16),
child: ListTile(
onTap: () async {
final topic = await showTextInputDialog(
context: context,
textFields: [
DialogTextField(
initialText: botOptions.topic.isEmpty
? ""
: botOptions.topic,
hintText:
L10n.of(context)!.enterAConversationTopic,
),
],
title: L10n.of(context)!.conversationTopic,
);
if (topic == null) return;
updateBotOption(() {
botOptions.topic = topic.single;
});
},
leading: CircleAvatar(
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor:
Theme.of(context).textTheme.bodyLarge!.color,
child: const Icon(Icons.topic_outlined),
),
subtitle: Text(
botOptions.topic.isEmpty
? L10n.of(context)!.enterAConversationTopic
: botOptions.topic,
),
title: Text(
L10n.of(context)!.conversationTopic,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
),
),
Padding(
padding: const EdgeInsets.only(left: 16),
child: SwitchListTile.adaptive(
title: Text(
L10n.of(context)!.enableModeration,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
subtitle: Text(L10n.of(context)!.enableModerationDesc),
secondary: CircleAvatar(
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor:
Theme.of(context).textTheme.bodyLarge!.color,
child: const Icon(Icons.shield_outlined),
),
activeColor: AppConfig.activeToggleColor,
value: botOptions.safetyModeration,
onChanged: (bool newValue) => updateBotOption(() {
botOptions.safetyModeration = newValue;
}),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(32, 16, 0, 0),
child: Text(
L10n.of(context)!.conversationLanguageLevel,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 16),
child: LanguageLevelDropdown(
initialLevel: botOptions.languageLevel,
onChanged: (int? newValue) => updateBotOption(() {
botOptions.languageLevel = newValue!;
}),
),
),
const SizedBox(height: 16),
],
],
),
),
],
);
}

@ -1,6 +1,7 @@
import 'dart:developer';
import 'package:fluffychat/pangea/models/class_model.dart';
import 'package:fluffychat/pangea/widgets/space/language_level_dropdown.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
@ -9,14 +10,12 @@ import 'package:matrix/matrix.dart';
import '../../../widgets/matrix.dart';
import '../../constants/language_keys.dart';
import '../../constants/language_level_type.dart';
import '../../constants/pangea_event_types.dart';
import '../../controllers/language_list_controller.dart';
import '../../controllers/pangea_controller.dart';
import '../../extensions/pangea_room_extension.dart';
import '../../models/language_model.dart';
import '../../utils/error_handler.dart';
import '../../utils/language_level_copy.dart';
import '../user_settings/p_language_dropdown.dart';
import '../user_settings/p_question_container.dart';
@ -169,72 +168,11 @@ class ClassSettingsState extends State<ClassSettings> {
PQuestionContainer(
title: L10n.of(context)!.whatIsYourClassLanguageLevel,
),
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(
classSettings.languageLevel == null
? L10n.of(context)!.selectLanguageLevel
: LanguageLevelTextPicker.languageLevelText(
context,
classSettings.languageLevel!,
),
style: const TextStyle().copyWith(
color: Theme.of(context)
.textTheme
.bodyLarge!
.color,
fontSize: 14,
),
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: (int? newValue) => updatePermission(() {
classSettings.languageLevel = newValue!;
}),
),
),
LanguageLevelDropdown(
initialLevel: classSettings.languageLevel,
onChanged: (int? newValue) => updatePermission(() {
classSettings.languageLevel = newValue!;
}),
),
],
),

@ -0,0 +1,76 @@
import 'package:fluffychat/pangea/constants/language_level_type.dart';
import 'package:fluffychat/pangea/utils/language_level_copy.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
class LanguageLevelDropdown extends StatelessWidget {
final int? initialLevel;
final void Function(int?)? onChanged;
const LanguageLevelDropdown({
super.key,
this.initialLevel,
this.onChanged,
});
@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,
),
),
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,
),
),
);
}
}

@ -115,6 +115,7 @@ abstract class ClientManager {
PangeaEventTypes.classSettings,
PangeaEventTypes.rules,
PangeaEventTypes.vocab,
PangeaEventTypes.botOptions,
EventTypes.RoomTopic,
EventTypes.RoomAvatar,
// Pangea#

@ -142,7 +142,6 @@ flutter:
generate: true
uses-material-design: true
assets:
- .env
- assets/
# #Pangea
- assets/pangea/

Loading…
Cancel
Save