diff --git a/README.md b/README.md index 7c4970e00..7c27b6e2e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ -Pangea Chat Client Setup: +# Overview -* Download VSCode if you do not already have it installed +[Pangea Chat](https://pangea.chat) is a web and mobile platform which lets students ‘learn a language while texting their friends.’ Addressing the gap in communicative language teaching, especially for beginners lacking skill and confidence, Pangea Chat provides a low-stress, high-support environment for language learning through authentic conversations. By integrating human and artificial intelligence, the app enhances communicative abilities and supports educators. Pangea Chat has been grant funded by the National Science Foundation and Virginia Innovation Partnership Corporation based on its technical innovation and potential for broad social impact. Our mission is to build a global, decentralized learning network supporting intercultural learning and exchange. + +# Pangea Chat Client Setup + +* Download VSCode if you do not already have it installed. This is the preferred IDE for development with Pangea Chat. * Download flutter on your device using this guide: https://docs.flutter.dev/get-started/install * Test to make sure that flutter is properly installed by running “flutter –version” * You may need to add flutter to your path manually. Instructions can be found here: https://docs.flutter.dev/get-started/install/macos/mobile-ios?tab=download#add-flutter-to-your-path @@ -14,7 +18,7 @@ Pangea Chat Client Setup: * Run “brew install cocoapods” to install cocoapods * Run “flutter doctor” and for any missing components, follow the instructions from the print out to install / setup * Clone the client repo -* Copy the .env file (and the .env.prod file, if you want to run production builds), into the root folder of the client and the assets/ folder +* Copy the .env file (and the .env.prod file, if you want to run production builds), into the root folder of the client and the assets/ folder. Contact Gabby for a copy of this file. * Uncomment the lines in the pubspec.yaml file in the assets section with paths to .env file * To run on iOS: * Run “flutter precache --ios” @@ -25,62 +29,10 @@ Pangea Chat Client Setup: * On web, run `flutter run -d chrome –hot` * On mobile device or simulator, run `flutter run –hot -d ` -![Screenshot](https://github.com/krille-chan/fluffychat/blob/main/assets/banner_transparent.png?raw=true) - -[FluffyChat](https://fluffychat.im) is an open source, nonprofit and cute [[matrix](https://matrix.org)] client written in [Flutter](https://flutter.dev). The goal of the app is to create an easy to use instant messenger which is open source and accessible for everyone. - -### Links: - -- 🌐 [[Weblate] Translate FluffyChat into your language](https://hosted.weblate.org/projects/fluffychat/) -- 🌍 [[m] Join the community](https://matrix.to/#/#fluffychat:matrix.org) -- 📰 [[Mastodon] Get updates on social media](https://mastodon.art/@krille) -- 🖥️ [[Famedly] Server hosting and professional support](https://famedly.com/kontakt) -- 💝 [[Liberapay] Support FluffyChat development](https://de.liberapay.com/KrilleChritzelius) - -Buy Me a Coffee at ko-fi.com - -### Screenshots: - -![Screenshot](https://github.com/krille-chan/fluffychat/blob/main/docs/screenshots/product.jpeg?raw=true) - -# Features - -- 📩 Send all kinds of messages, images and files -- 🎙️ Voice messages -- 📍 Location sharing -- 🔔 Push notifications -- 💬 Unlimited private and public group chats -- 📣 Public channels with thousands of participants -- 🛠️ Feature rich group moderation including all matrix features -- 🔍 Discover and join public groups -- 🌙 Dark mode -- 🎨 Material You design -- 📟 Hides complexity of Matrix IDs behind simple QR codes -- 😄 Custom emotes and stickers -- 🌌 Spaces -- 🔄 Compatible with Element, Nheko, NeoChat and all other Matrix apps -- 🔐 End to end encryption -- 🔒 Encrypted chat backup -- 😀 Emoji verification & cross signing - -... and much more. - - -# Installation - -Please visit the website for installation instructions: - -- https://fluffychat.im - -# How to build - -Please visit the [Wiki](https://github.com/krille-chan/fluffychat/wiki) for build instructions: - -- https://github.com/krille-chan/fluffychat/wiki/How-To-Build - - # Special thanks +* Pangea Chat is a fork of [FluffyChat](https://fluffychat.im), is an open source, nonprofit and cute [[matrix](https://matrix.org)] client written in [Flutter](https://flutter.dev). The goal of FluffyChat is to create an easy to use instant messenger which is open source and accessible for everyone. You can [support the primary maker of FluffyChat directly here.](https://ko-fi.com/C1C86VN53) + * Fabiyamada is a graphics designer and has made the fluffychat logo and the banner. Big thanks for her great designs. * Advocatux has made the Spanish translation with great love and care. He always stands by my side and supports my work with great commitment. diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 6677bc3d3..fe2a3da03 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3945,6 +3945,21 @@ "accuracy": "Accuracy", "points": "Points", "noPaymentInfo": "No payment info necessary!", + "conversationBotModeSelectDescription": "Bot mode", + "conversationBotModeSelectOption_discussion": "Discussion", + "conversationBotModeSelectOption_custom": "Custom", + "conversationBotModeSelectOption_conversation": "Conversation", + "conversationBotModeSelectOption_textAdventure": "Text Adventure", + "conversationBotDiscussionZone_title": "Discussion Settings", + "conversationBotDiscussionZone_discussionTopicLabel": "Discussion Topic", + "conversationBotDiscussionZone_discussionTopicPlaceholder": "Set Discussion Topic", + "conversationBotDiscussionZone_discussionKeywordsLabel": "Discussion Keywords", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder": "Set Discussion Keywords", + "conversationBotDiscussionZone_discussionKeywordsHintText": "Comma separated list of keywords to guide the discussion", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel": "Send discussion prompt on a schedule", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel": "Hours between discussion prompts", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel": "Send discussion prompt when user reacts ⏩ to bot message", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel": "Reaction to send discussion prompt", "studentAnalyticsNotAvailable": "Student data not currently available", "roomDataMissing": "Some data may be missing from rooms in which you are not a member.", "updatePhoneOS": "You may need to update your device's OS version.", diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index 59f5719b0..d463699be 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -4634,5 +4634,22 @@ "points": "Puntos", "noPaymentInfo": "No se necesitan datos de pago.", "updatePhoneOS": "Puede que necesites actualizar la versión del sistema operativo de tu dispositivo.", - "wordsPerMinute": "Palabras por minuto" + "wordsPerMinute": "Palabras por minuto", + "conversationBotModeSelectDescription": "Modo bot", + "conversationBotModeSelectOption_discussion": "Debate", + "conversationBotModeSelectOption_custom": "A medida", + "conversationBotModeSelectOption_conversation": "Conversación", + "conversationBotModeSelectOption_textAdventure": "Aventura textual", + "conversationBotDiscussionZone_title": "Configuración del debate", + "conversationBotDiscussionZone_discussionTopicLabel": "Tema de debate", + "conversationBotDiscussionZone_discussionTopicPlaceholder": "Establecer tema de debate", + "conversationBotDiscussionZone_discussionKeywordsLabel": "Palabras clave del debate", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder": "Establecer palabras clave de debate", + "conversationBotDiscussionZone_discussionKeywordsHintText": "Lista de palabras clave separadas por comas para orientar el debate", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel": "Enviar mensajes de debate según un calendario", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel": "Horas entre temas de debate", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel": "Enviar aviso de discusión cuando el usuario reacciona ⏩ al mensaje del bot.", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel": "Reacción al envío del aviso de debate", + "studentAnalyticsNotAvailable": "Datos de los estudiantes no disponibles actualmente", + "roomDataMissing": "Es posible que falten algunos datos de las salas de las que no es miembro." } \ No newline at end of file diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index 9866ddb2d..f04296d38 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -38,6 +38,7 @@ class MessageContent extends StatelessWidget { //further down in the chain is also using pangeaController so its not constant final bool immersionMode; final ToolbarDisplayController? toolbarController; + final bool isOverlay; // Pangea# const MessageContent( @@ -50,6 +51,7 @@ class MessageContent extends StatelessWidget { this.pangeaMessageEvent, required this.immersionMode, required this.toolbarController, + this.isOverlay = false, // Pangea# required this.borderRadius, }); @@ -203,7 +205,8 @@ class MessageContent extends StatelessWidget { && !(pangeaMessageEvent?.showRichText( selected, - toolbarController?.highlighted ?? false, + isOverlay: isOverlay, + highlighted: toolbarController?.highlighted ?? false, ) ?? false) // Pangea# @@ -305,7 +308,8 @@ class MessageContent extends StatelessWidget { ); if (pangeaMessageEvent?.showRichText( selected, - toolbarController?.highlighted ?? false, + isOverlay: isOverlay, + highlighted: toolbarController?.highlighted ?? false, ) ?? false) { return PangeaRichText( diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index f96baa040..c0791c936 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -728,6 +728,11 @@ class ChatListController extends State while (selectedRoomIds.isNotEmpty) { final roomId = selectedRoomIds.first; try { + // #Pangea + if (client.getRoomById(roomId)!.isUnread) { + await client.getRoomById(roomId)!.markUnread(false); + } + // Pangea# await client.getRoomById(roomId)!.leave(); } finally { toggleSelection(roomId); diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index 447b5f6c3..9775ec624 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -53,6 +53,11 @@ class ChatListItem extends StatelessWidget { message: L10n.of(context)!.archiveRoomDescription, ); if (confirmed == OkCancelResult.cancel) return; + // #Pangea + if (room.isUnread) { + await room.markUnread(false); + } + // Pangea# await showFutureLoadingDialog( context: context, future: () => room.leave(), diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index 348550c65..48be9eb04 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -288,7 +288,10 @@ class _SpaceViewState extends State { // #Pangea // future: room!.leave, future: () async { - await room!.leave(); + if (room!.isUnread) { + await room.markUnread(false); + } + await room.leave(); if (Matrix.of(context).activeRoomId == room.id) { context.go('/rooms'); } diff --git a/lib/pages/chat_list/utils/on_chat_tap.dart b/lib/pages/chat_list/utils/on_chat_tap.dart index d24af1fb4..d9f1c8191 100644 --- a/lib/pages/chat_list/utils/on_chat_tap.dart +++ b/lib/pages/chat_list/utils/on_chat_tap.dart @@ -1,15 +1,13 @@ -import 'package:flutter/material.dart'; - import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:fluffychat/pages/chat/send_file_dialog.dart'; +import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; +import 'package:fluffychat/widgets/matrix.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:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pages/chat/send_file_dialog.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; -import 'package:fluffychat/widgets/matrix.dart'; - void onChatTap(Room room, BuildContext context) async { if (room.membership == Membership.invite) { final inviterId = @@ -47,6 +45,11 @@ void onChatTap(Room room, BuildContext context) async { return; } if (inviteAction == InviteActions.decline) { + // #Pangea + if (room.isUnread) { + await room.markUnread(false); + } + // Pangea# await showFutureLoadingDialog( context: context, future: room.leave, diff --git a/lib/pangea/choreographer/controllers/analytics_sender.dart b/lib/pangea/choreographer/controllers/analytics_sender.dart deleted file mode 100644 index fe4575f38..000000000 --- a/lib/pangea/choreographer/controllers/analytics_sender.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:fluffychat/pangea/choreographer/controllers/it_controller.dart'; - -class MlController { - final ITController controller; - MlController(this.controller); - - // sendPayloads(String message, String messageId) async { - // final MessageServiceModel serviceModel = MessageServiceModel( - // classId: controller.state!.classId, - // roomId: controller.state!.roomId, - // message: message.toString(), - // messageId: messageId.toString(), - // payloadIds: controller.state!.payLoadIds, - // userId: controller.state!.userId!, - // l1Lang: controller.state!.sourceLangCode, - // l2Lang: controller.state!.targetLangCode!, - // ); - // try { - // await MessageServiceRepo.sendPayloads(serviceModel); - // } catch (err) { - // debugPrint('$err in sendPayloads'); - // } - // } -} diff --git a/lib/pangea/choreographer/controllers/igc_controller.dart b/lib/pangea/choreographer/controllers/igc_controller.dart index f5e15a1e3..73694e257 100644 --- a/lib/pangea/choreographer/controllers/igc_controller.dart +++ b/lib/pangea/choreographer/controllers/igc_controller.dart @@ -113,7 +113,11 @@ class IgcController { ), ); - igcTextData!.matches[matchIndex].match = response.span; + try { + igcTextData!.matches[matchIndex].match = response.span; + } catch (err, s) { + ErrorHandler.logError(e: err, s: s); + } choreographer.setState(); } diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 74d0b0159..83d678e98 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -15,7 +15,6 @@ import '../../models/it_response_model.dart'; import '../../models/it_step.dart'; import '../../models/system_choice_translation_model.dart'; import '../../repo/interactive_translation_repo.dart'; -import '../../repo/message_service.repo.dart'; import 'choreographer.dart'; class ITController { @@ -247,19 +246,19 @@ class ITController { ), ); - MessageServiceModel? messageServiceModelWithMessageId() => - usedInteractiveTranslation - ? MessageServiceModel( - classId: choreographer.classId, - roomId: choreographer.roomId, - message: choreographer.currentText, - messageId: null, - payloadIds: payLoadIds, - userId: choreographer.userId!, - l1Lang: sourceLangCode, - l2Lang: targetLangCode, - ) - : null; + // MessageServiceModel? messageServiceModelWithMessageId() => + // usedInteractiveTranslation + // ? MessageServiceModel( + // classId: choreographer.classId, + // roomId: choreographer.roomId, + // message: choreographer.currentText, + // messageId: null, + // payloadIds: payLoadIds, + // userId: choreographer.userId!, + // l1Lang: sourceLangCode, + // l2Lang: targetLangCode, + // ) + // : null; //maybe we store IT data in the same format? make a specific kind of match? void selectTranslation(int chosenIndex) { diff --git a/lib/pangea/constants/model_keys.dart b/lib/pangea/constants/model_keys.dart index dd9764fb9..ce427f3d3 100644 --- a/lib/pangea/constants/model_keys.dart +++ b/lib/pangea/constants/model_keys.dart @@ -96,7 +96,17 @@ class ModelKey { // bot options static const String languageLevel = "difficulty"; - static const String conversationTopic = "conversation_topic"; - static const String keywords = "keywords"; static const String safetyModeration = "safety_moderation"; + static const String mode = "mode"; + static const String custom = "custom"; + static const String discussionTopic = "discussion_topic"; + static const String discussionKeywords = "discussion_keywords"; + static const String discussionTriggerScheduleEnabled = + "discussion_trigger_schedule_enabled"; + static const String discussionTriggerScheduleHourInterval = + "discussion_trigger_schedule_hour_interval"; + static const String discussionTriggerReactionEnabled = + "discussion_trigger_reaction_enabled"; + static const String discussionTriggerReactionKey = + "discussion_trigger_reaction_key"; } diff --git a/lib/pangea/controllers/language_detection_controller.dart b/lib/pangea/controllers/language_detection_controller.dart new file mode 100644 index 000000000..0ff18b556 --- /dev/null +++ b/lib/pangea/controllers/language_detection_controller.dart @@ -0,0 +1,138 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:fluffychat/pangea/config/environment.dart'; +import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; +import 'package:fluffychat/pangea/network/urls.dart'; +import 'package:http/http.dart' as http; + +import '../network/requests.dart'; + +class LanguageDetectionRequest { + /// The full text from which to detect the language. + String fullText; + + /// The base language of the user, if known. Including this is much preferred + /// and should return better results; however, it is not absolutely necessary. + /// This property is nullable to allow for situations where the languages are not set + /// at the time of the request. + String? userL1; + + /// The target language of the user. This is expected to be set for the request + /// but is nullable to handle edge cases where it might not be. + String? userL2; + + LanguageDetectionRequest({ + required this.fullText, + this.userL1 = "", + required this.userL2, + }); + + Map toJson() => { + 'full_text': fullText, + 'user_l1': userL1, + 'user_l2': userL2, + }; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is LanguageDetectionRequest && + other.fullText == fullText && + other.userL1 == userL1 && + other.userL2 == userL2; + } + + @override + int get hashCode => fullText.hashCode ^ userL1.hashCode ^ userL2.hashCode; +} + +class LanguageDetectionResponse { + List> detections; + String fullText; + + LanguageDetectionResponse({ + required this.detections, + required this.fullText, + }); + + factory LanguageDetectionResponse.fromJson(Map json) { + return LanguageDetectionResponse( + detections: List>.from(json['detections']), + fullText: json['full_text'], + ); + } + + Map toJson() { + return { + 'detections': detections, + 'full_text': fullText, + }; + } +} + +class _LanguageDetectionCacheItem { + Future data; + + _LanguageDetectionCacheItem({ + required this.data, + }); +} + +class LanguageDetectionController { + static final Map + _cache = {}; + late final PangeaController _pangeaController; + Timer? _cacheClearTimer; + + LanguageDetectionController(PangeaController pangeaController) { + _pangeaController = pangeaController; + _initializeCacheClearing(); + } + + void _initializeCacheClearing() { + const duration = Duration(minutes: 15); // Adjust the duration as needed + _cacheClearTimer = Timer.periodic(duration, (Timer t) => _clearCache()); + } + + void _clearCache() { + _cache.clear(); + } + + void dispose() { + _cacheClearTimer?.cancel(); + } + + Future get( + LanguageDetectionRequest params, + ) async { + if (_cache.containsKey(params)) { + return _cache[params]!.data; + } else { + final Future response = _fetchResponse( + await _pangeaController.userController.accessToken, + params, + ); + _cache[params] = _LanguageDetectionCacheItem(data: response); + return response; + } + } + + static Future _fetchResponse( + String accessToken, + LanguageDetectionRequest params, + ) async { + final Requests request = Requests( + choreoApiKey: Environment.choreoApiKey, + accessToken: accessToken, + ); + + final http.Response res = await request.post( + url: PApiUrls.languageDetection, + body: params.toJson(), + ); + + final Map json = jsonDecode(res.body); + return LanguageDetectionResponse.fromJson(json); + } +} diff --git a/lib/pangea/controllers/pangea_controller.dart b/lib/pangea/controllers/pangea_controller.dart index 204ef9307..753a8c9e6 100644 --- a/lib/pangea/controllers/pangea_controller.dart +++ b/lib/pangea/controllers/pangea_controller.dart @@ -6,6 +6,7 @@ import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/controllers/class_controller.dart'; import 'package:fluffychat/pangea/controllers/contextual_definition_controller.dart'; import 'package:fluffychat/pangea/controllers/language_controller.dart'; +import 'package:fluffychat/pangea/controllers/language_detection_controller.dart'; import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; import 'package:fluffychat/pangea/controllers/local_settings.dart'; import 'package:fluffychat/pangea/controllers/message_data_controller.dart'; @@ -51,6 +52,7 @@ class PangeaController { late SubscriptionController subscriptionController; late TextToSpeechController textToSpeech; late SpeechToTextController speechToText; + late LanguageDetectionController languageDetection; ///store Services late PLocalStore pStoreService; @@ -98,6 +100,7 @@ class PangeaController { itFeedback = ITFeedbackController(this); textToSpeech = TextToSpeechController(this); speechToText = SpeechToTextController(this); + languageDetection = LanguageDetectionController(this); PAuthGaurd.pController = this; } diff --git a/lib/pangea/extensions/client_extension.dart b/lib/pangea/extensions/client_extension.dart index b259d0c9e..47d67c0b8 100644 --- a/lib/pangea/extensions/client_extension.dart +++ b/lib/pangea/extensions/client_extension.dart @@ -25,7 +25,8 @@ extension PangeaClient on Client { .toList(); Future> get classesAndExchangesImTeaching async { - for (final Room space in rooms.where((room) => room.isSpace)) { + final allSpaces = rooms.where((room) => room.isSpace); + for (final Room space in allSpaces) { if (space.getState(EventTypes.RoomPowerLevels) == null) { await space.postLoad(); } diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index db5c7902a..91f19f6e7 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -80,18 +80,26 @@ class PangeaMessageEvent { return _latestEdit; } - bool showRichText(bool selected, bool highlighted) { + bool showRichText( + bool selected, { + bool highlighted = false, + bool isOverlay = false, + }) { if (!_isValidPangeaMessageEvent) { return false; } - // if (URLFinder.getMatches(event.body).isNotEmpty) { - // return false; - // } + if ([EventStatus.error, EventStatus.sending].contains(_event.status)) { return false; } - if (ownMessage && !selected && !highlighted) return false; + if (isOverlay) return true; + + // if ownMessage, don't show rich text if not selected or highlighted + // and don't show is the message is not an overlay + if (ownMessage && ((!selected && !highlighted) || !isOverlay)) { + return false; + } return true; } diff --git a/lib/pangea/models/bot_options_model.dart b/lib/pangea/models/bot_options_model.dart index 0cba5fd78..0b437159e 100644 --- a/lib/pangea/models/bot_options_model.dart +++ b/lib/pangea/models/bot_options_model.dart @@ -12,20 +12,45 @@ class BotOptionsModel { String topic; List keywords; bool safetyModeration; + String mode; + String? custom; + String? discussionTopic; + String? discussionKeywords; + bool? discussionTriggerScheduleEnabled; + int? discussionTriggerScheduleHourInterval; + bool? discussionTriggerReactionEnabled; + String? discussionTriggerReactionKey; BotOptionsModel({ this.languageLevel, this.topic = "General Conversation", this.keywords = const [], this.safetyModeration = true, + this.mode = "discussion", + this.custom = "", + this.discussionTopic, + this.discussionKeywords, + this.discussionTriggerScheduleEnabled, + this.discussionTriggerScheduleHourInterval, + this.discussionTriggerReactionEnabled, + this.discussionTriggerReactionKey, }); factory BotOptionsModel.fromJson(json) { return BotOptionsModel( languageLevel: json[ModelKey.languageLevel], - topic: json[ModelKey.conversationTopic] ?? "General Conversation", - keywords: (json[ModelKey.keywords] ?? []).cast(), safetyModeration: json[ModelKey.safetyModeration] ?? true, + mode: json[ModelKey.mode] ?? "discussion", + custom: json[ModelKey.custom], + discussionTopic: json[ModelKey.discussionTopic], + discussionKeywords: json[ModelKey.discussionKeywords], + discussionTriggerScheduleEnabled: + json[ModelKey.discussionTriggerScheduleEnabled], + discussionTriggerScheduleHourInterval: + json[ModelKey.discussionTriggerScheduleHourInterval], + discussionTriggerReactionEnabled: + json[ModelKey.discussionTriggerReactionEnabled], + discussionTriggerReactionKey: json[ModelKey.discussionTriggerReactionKey], ); } @@ -34,9 +59,19 @@ class BotOptionsModel { try { // data[ModelKey.isConversationBotChat] = isConversationBotChat; data[ModelKey.languageLevel] = languageLevel; - data[ModelKey.conversationTopic] = topic; - data[ModelKey.keywords] = keywords; data[ModelKey.safetyModeration] = safetyModeration; + data[ModelKey.mode] = mode; + data[ModelKey.custom] = custom; + data[ModelKey.discussionTopic] = discussionTopic; + data[ModelKey.discussionKeywords] = discussionKeywords; + data[ModelKey.discussionTriggerScheduleEnabled] = + discussionTriggerScheduleEnabled; + data[ModelKey.discussionTriggerScheduleHourInterval] = + discussionTriggerScheduleHourInterval; + data[ModelKey.discussionTriggerReactionEnabled] = + discussionTriggerReactionEnabled; + data[ModelKey.discussionTriggerReactionKey] = + discussionTriggerReactionKey; return data; } catch (e, s) { debugger(when: kDebugMode); @@ -51,15 +86,33 @@ class BotOptionsModel { case ModelKey.languageLevel: languageLevel = value; break; - case ModelKey.conversationTopic: - topic = value; - break; - case ModelKey.keywords: - keywords = value; - break; case ModelKey.safetyModeration: safetyModeration = value; break; + case ModelKey.mode: + mode = value; + break; + case ModelKey.custom: + custom = value; + break; + case ModelKey.discussionTopic: + discussionTopic = value; + break; + case ModelKey.discussionKeywords: + discussionKeywords = value; + break; + case ModelKey.discussionTriggerScheduleEnabled: + discussionTriggerScheduleEnabled = value; + break; + case ModelKey.discussionTriggerScheduleHourInterval: + discussionTriggerScheduleHourInterval = value; + break; + case ModelKey.discussionTriggerReactionEnabled: + discussionTriggerReactionEnabled = value; + break; + case ModelKey.discussionTriggerReactionKey: + discussionTriggerReactionKey = value; + break; default: throw Exception('Invalid key for bot options - $key'); } diff --git a/lib/pangea/models/representation_content_model.dart b/lib/pangea/models/representation_content_model.dart index c4ff52fe7..f49a465b4 100644 --- a/lib/pangea/models/representation_content_model.dart +++ b/lib/pangea/models/representation_content_model.dart @@ -1,8 +1,5 @@ -import 'package:fluffychat/pangea/constants/language_keys.dart'; import 'package:fluffychat/pangea/models/speech_to_text_models.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:matrix/matrix.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; /// this class is contained within a [RepresentationEvent] /// this event is the child of a [EventTypes.Message] @@ -56,14 +53,6 @@ class PangeaRepresentation { }); factory PangeaRepresentation.fromJson(Map json) { - if (json[_langCodeKey] == LanguageKeys.unknownLanguage) { - ErrorHandler.logError( - e: Exception("Language code cannot be 'unk'"), - s: StackTrace.current, - data: {"rep_content": json}, - level: SentryLevel.warning, - ); - } return PangeaRepresentation( langCode: json[_langCodeKey], text: json[_textKey], diff --git a/lib/pangea/models/span_card_model.dart b/lib/pangea/models/span_card_model.dart index 8a252e67b..f74a14332 100644 --- a/lib/pangea/models/span_card_model.dart +++ b/lib/pangea/models/span_card_model.dart @@ -1,5 +1,6 @@ import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; class SpanCardModel { // IGCTextData igcTextData; @@ -21,6 +22,18 @@ class SpanCardModel { required this.choreographer, }); - PangeaMatch? get pangeaMatch => - choreographer.igc.igcTextData?.matches[matchIndex]; + PangeaMatch? get pangeaMatch { + if (choreographer.igc.igcTextData == null) return null; + if (matchIndex >= choreographer.igc.igcTextData!.matches.length) { + ErrorHandler.logError( + m: "matchIndex out of bounds in span card", + data: { + "matchIndex": matchIndex, + "matchesLength": choreographer.igc.igcTextData?.matches.length, + }, + ); + return null; + } + return choreographer.igc.igcTextData?.matches[matchIndex]; + } } diff --git a/lib/pangea/models/word_data_model.dart b/lib/pangea/models/word_data_model.dart index 838240725..c4c059241 100644 --- a/lib/pangea/models/word_data_model.dart +++ b/lib/pangea/models/word_data_model.dart @@ -1,9 +1,8 @@ import 'dart:developer'; -import 'package:flutter/foundation.dart'; - import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/widgets/igc/word_data_card.dart'; +import 'package:flutter/foundation.dart'; class WordData { final String word; @@ -102,10 +101,11 @@ class WordData { }) => word == w && userL1 == l1 && userL2 == l2 && fullText == f; - String formattedPartOfSpeech(LanguageType languageType) { + String? formattedPartOfSpeech(LanguageType languageType) { final String pos = languageType == LanguageType.base ? basePartOfSpeech : targetPartOfSpeech; + if (pos.isEmpty) return null; return pos[0].toUpperCase() + pos.substring(1); } diff --git a/lib/pangea/network/urls.dart b/lib/pangea/network/urls.dart index 16d8bcd23..ff0404947 100644 --- a/lib/pangea/network/urls.dart +++ b/lib/pangea/network/urls.dart @@ -24,13 +24,12 @@ class PApiUrls { /// ---------------------- Conversation Partner ------------------------- static String searchUserProfiles = "/account/search"; - ///-------------------------------- Deprecated analytics -------------------- - static String classAnalytics = "${Environment.choreoApi}/class_analytics"; - static String messageService = "/message_service"; - ///-------------------------------- choreo -------------------------- static String igc = "${Environment.choreoApi}/grammar"; + static String languageDetection = + "${Environment.choreoApi}/language_detection"; + static String igcLite = "${Environment.choreoApi}/grammar_lite"; static String spanDetails = "${Environment.choreoApi}/span_details"; diff --git a/lib/pangea/pages/class_settings/p_class_widgets/delete_class_tile.dart b/lib/pangea/pages/class_settings/p_class_widgets/delete_class_tile.dart deleted file mode 100644 index 7e3fc3af6..000000000 --- a/lib/pangea/pages/class_settings/p_class_widgets/delete_class_tile.dart +++ /dev/null @@ -1,149 +0,0 @@ -import 'package:flutter/material.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:matrix/matrix.dart'; - -import 'package:fluffychat/pangea/utils/delete_room.dart'; -import 'package:fluffychat/widgets/matrix.dart'; - -class DeleteSpaceTile extends StatelessWidget { - final Room room; - - const DeleteSpaceTile({ - super.key, - required this.room, - }); - - @override - Widget build(BuildContext context) { - bool classNameMatch = true; - final textController = TextEditingController(); - Future deleteSpace() async { - final Client client = Matrix.of(context).client; - final GetSpaceHierarchyResponse spaceHierarchy = - await client.getSpaceHierarchy(room.id); - - if (spaceHierarchy.rooms.isNotEmpty) { - final List spaceChats = spaceHierarchy.rooms - .where((c) => c.roomId != room.id) - .map((e) => Matrix.of(context).client.getRoomById(e.roomId)) - .where((c) => c != null && !c.isSpace && !c.isDirectChat) - .cast() - .toList(); - - await Future.wait( - spaceChats.map((c) => deleteRoom(c.id, client)), - ); - } - deleteRoom(room.id, client); - context.go('/rooms'); - return; - } - - Future deleteChat() { - context.go('/rooms'); - return deleteRoom(room.id, Matrix.of(context).client); - } - - Future deleteChatAction() async { - showDialog( - context: context, - useRootNavigator: false, - builder: (context) { - return StatefulBuilder( - builder: (context, setState) { - return AlertDialog( - title: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - room.isSpace - ? L10n.of(context)!.areYouSureDeleteClass - : L10n.of(context)!.areYouSureDeleteGroup, - style: const TextStyle( - fontSize: 20, - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 5), - Text( - L10n.of(context)!.cannotBeReversed, - style: const TextStyle( - fontSize: 16, - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 10), - if (room.isSpace) - Text( - L10n.of(context)!.enterDeletedClassName, - style: const TextStyle( - fontSize: 14, - ), - textAlign: TextAlign.center, - ), - ], - ), - content: room.isSpace - ? TextField( - autofocus: true, - controller: textController, - decoration: InputDecoration( - hintText: room.name, - errorText: !classNameMatch - ? L10n.of(context)!.incorrectClassName - : null, - ), - ) - : null, - actions: [ - TextButton( - child: Text(L10n.of(context)!.ok), - onPressed: () async { - if (room.isSpace) { - setState(() { - classNameMatch = textController.text == room.name; - }); - if (classNameMatch) { - Navigator.of(context).pop(); - await showFutureLoadingDialog( - context: context, - future: () => deleteSpace(), - ); - } - } else { - await showFutureLoadingDialog( - context: context, - future: () => deleteChat(), - ); - } - }, - ), - TextButton( - child: Text(L10n.of(context)!.cancel), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ], - ); - }, - ); - }, - ); - } - - return ListTile( - trailing: const Icon(Icons.delete_outlined), - title: Text( - room.isSpace - ? L10n.of(context)!.deleteSpace - : L10n.of(context)!.deleteGroup, - style: const TextStyle(color: Colors.red), - ), - onTap: () => deleteChatAction(), - ); - } -} diff --git a/lib/pangea/repo/message_service.repo.dart b/lib/pangea/repo/message_service.repo.dart deleted file mode 100644 index ce51a3802..000000000 --- a/lib/pangea/repo/message_service.repo.dart +++ /dev/null @@ -1,55 +0,0 @@ -import '../config/environment.dart'; -import '../network/requests.dart'; -import '../network/urls.dart'; - -class MessageServiceRepo { - static Future sendPayloads( - MessageServiceModel serviceModel, - String messageId, - ) async { - final Requests req = Requests( - baseUrl: Environment.choreoApi, - choreoApiKey: Environment.choreoApiKey, - ); - - final json = serviceModel.toJson(); - json["msg_id"] = messageId; - - await req.post(url: PApiUrls.messageService, body: json); - } -} - -class MessageServiceModel { - List payloadIds; - String? messageId; - String message; - String userId; - String roomId; - String? classId; - String? l1Lang; - String l2Lang; - - MessageServiceModel({ - required this.payloadIds, - required this.messageId, - required this.message, - required this.userId, - required this.roomId, - required this.classId, - required this.l1Lang, - required this.l2Lang, - }); - - toJson() { - return { - 'payload_ids': payloadIds, - 'msg_id': messageId, - 'message': message, - 'user_id': userId, - 'room_id': roomId, - 'class_id': classId, - 'l1_lang': l1Lang, - 'l2_lang': l2Lang, - }; - } -} diff --git a/lib/pangea/utils/archive_space.dart b/lib/pangea/utils/archive_space.dart index 72f10fae4..ac83980fb 100644 --- a/lib/pangea/utils/archive_space.dart +++ b/lib/pangea/utils/archive_space.dart @@ -1,7 +1,6 @@ -import 'package:matrix/matrix.dart'; - import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:matrix/matrix.dart'; Future archiveSpace(Room? space, Client client) async { if (space == null) { @@ -14,6 +13,9 @@ Future archiveSpace(Room? space, Client client) async { final List children = await space.getChildRooms(); for (final Room child in children) { + if (child.isUnread) { + await child.markUnread(false); + } await child.leave(); } await space.leave(); diff --git a/lib/pangea/utils/delete_room.dart b/lib/pangea/utils/delete_room.dart deleted file mode 100644 index f8e168779..000000000 --- a/lib/pangea/utils/delete_room.dart +++ /dev/null @@ -1,89 +0,0 @@ -import 'package:matrix/matrix.dart'; - -import 'package:fluffychat/pangea/constants/class_default_values.dart'; -import 'error_handler.dart'; - -Future deleteRoom(String? roomID, Client client) async { - if (roomID == null) { - ErrorHandler.logError( - m: "in deleteRoomAction with null pangeaClassRoomID", - s: StackTrace.current, - ); - return; - } - - final Room? room = client.getRoomById(roomID); - if (room == null) { - ErrorHandler.logError( - m: "failed to fetch room with roomID $roomID", - s: StackTrace.current, - ); - return; - } - - try { - await room.join(); - } catch (err) { - ErrorHandler.logError( - m: "failed to join room with roomID $roomID", - s: StackTrace.current, - ); - return; - } - - List members; - try { - members = await room.requestParticipants(); - } catch (err) { - ErrorHandler.logError( - m: "failed to fetch members for room with roomID $roomID", - s: StackTrace.current, - ); - return; - } - - final List otherAdmins = []; - for (final User member in members) { - final String memberID = member.id; - final int memberPowerLevel = room.getPowerLevelByUserId(memberID); - if (memberID == client.userID) continue; - if (memberPowerLevel >= ClassDefaultValues.powerLevelOfAdmin) { - otherAdmins.add(member); - continue; - } - try { - await room.kick(memberID); - } catch (err) { - ErrorHandler.logError( - m: "Failed to kick user $memberID from room with id $roomID. Error: $err", - s: StackTrace.current, - ); - continue; - } - } - - if (otherAdmins.isNotEmpty && room.canSendEvent(EventTypes.RoomJoinRules)) { - try { - await client.setRoomStateWithKey( - roomID, - EventTypes.RoomJoinRules, - "", - {"join_rules": "invite"}, - ); - } catch (err) { - ErrorHandler.logError( - m: "Failed to update student create room permissions. error: $err, roomId: $roomID", - s: StackTrace.current, - ); - } - } - - try { - await room.leave(); - } catch (err) { - ErrorHandler.logError( - m: "Failed to leave room with id $roomID. Error: $err", - s: StackTrace.current, - ); - } -} diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 81884ffca..2f6d82ef1 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -134,8 +134,11 @@ class ToolbarDisplayController { }); } - bool get highlighted => - MatrixState.pAnyState.overlay.hashCode.toString() == overlayId; + bool get highlighted { + if (overlayId == null) return false; + if (MatrixState.pAnyState.overlay == null) overlayId = null; + return MatrixState.pAnyState.overlay.hashCode.toString() == overlayId; + } } class MessageToolbar extends StatefulWidget { diff --git a/lib/pangea/widgets/chat/overlay_message.dart b/lib/pangea/widgets/chat/overlay_message.dart index 5c7ccdef0..e8143b376 100644 --- a/lib/pangea/widgets/chat/overlay_message.dart +++ b/lib/pangea/widgets/chat/overlay_message.dart @@ -141,6 +141,7 @@ class OverlayMessage extends StatelessWidget { pangeaMessageEvent: pangeaMessageEvent, immersionMode: immersionMode, toolbarController: toolbarController, + isOverlay: true, ), if (event.hasAggregatedEvents( timeline, diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_conversation_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_conversation_zone.dart new file mode 100644 index 000000000..975cc1d0d --- /dev/null +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_conversation_zone.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +class ConversationBotConversationZone extends StatelessWidget { + const ConversationBotConversationZone({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return const Column( + children: [ + Text('Conversation Zone'), + ], + ); + } +} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart new file mode 100644 index 000000000..5fe8880ea --- /dev/null +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +class ConversationBotCustomZone extends StatelessWidget { + const ConversationBotCustomZone({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return const Column( + children: [ + Text('Custom Zone'), + ], + ); + } +} 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 new file mode 100644 index 000000000..9024e41bb --- /dev/null +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_keywords_input.dart @@ -0,0 +1,71 @@ +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( + 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 new file mode 100644 index 000000000..72caa3839 --- /dev/null +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_topic_input.dart @@ -0,0 +1,70 @@ +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( + 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 new file mode 100644 index 000000000..57c25e133 --- /dev/null +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_zone.dart @@ -0,0 +1,225 @@ +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: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) { + final String discussionTopic = initialBotOptions.discussionTopic ?? ""; + final String discussionKeywords = + initialBotOptions.discussionKeywords ?? ""; + // int discussionTriggerScheduleHourInterval = + // initialBotOptions.discussionTriggerScheduleHourInterval ?? 24; + // String discussionTriggerReactionKey = + // initialBotOptions.discussionTriggerReactionKey ?? "⏩"; + // List reactionKeyOptions = ["⏩"]; + return Column( + children: [ + const SizedBox(height: 12), + Text( + L10n.of(context)!.conversationBotDiscussionZone_title, + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + ), + const Divider( + color: Colors.grey, + thickness: 1, + ), + const SizedBox(height: 12), + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.fromLTRB(12, 0, 0, 0), + child: Text( + L10n.of(context)! + .conversationBotDiscussionZone_discussionTopicLabel, + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + child: ConversationBotDiscussionTopicInput( + initialBotOptions: initialBotOptions, + onChanged: onChanged, + ), + ), + const SizedBox(height: 12), + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.fromLTRB(12, 0, 0, 0), + child: Text( + L10n.of(context)! + .conversationBotDiscussionZone_discussionKeywordsLabel, + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + child: ConversationBotDiscussionKeywordsInput( + initialBotOptions: initialBotOptions, + onChanged: onChanged, + ), + ), + const SizedBox(height: 12), + // CheckboxListTile( + // title: Text( + // L10n.of(context)! + // .conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel, + // ), + // value: initialBotOptions.discussionTriggerScheduleEnabled ?? false, + // onChanged: (value) { + // initialBotOptions.discussionTriggerScheduleEnabled = value ?? false; + // onChanged?.call(initialBotOptions); + // }, + // ), + // if (initialBotOptions.discussionTriggerScheduleEnabled == true) + // Padding( + // padding: const EdgeInsets.all(8), + // child: TextField( + // keyboardType: TextInputType.number, + // controller: TextEditingController( + // text: discussionTriggerScheduleHourInterval.toString(), + // ), + // onChanged: (value) { + // discussionTriggerScheduleHourInterval = + // int.tryParse(value) ?? 0; + // }, + // decoration: InputDecoration( + // labelText: L10n.of(context)! + // .conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel, + // floatingLabelBehavior: FloatingLabelBehavior.auto, + // suffixIcon: IconButton( + // icon: const Icon(Icons.check), + // onPressed: () { + // if (discussionTriggerScheduleHourInterval != + // initialBotOptions + // .discussionTriggerScheduleHourInterval) { + // initialBotOptions.discussionTriggerScheduleHourInterval = + // discussionTriggerScheduleHourInterval; + // onChanged?.call( + // initialBotOptions, + // ); + // } + // }, + // ), + // ), + // ), + // ), + // const SizedBox(height: 12), + CheckboxListTile( + title: Text( + L10n.of(context)! + .conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel, + ), + value: initialBotOptions.discussionTriggerReactionEnabled ?? false, + onChanged: (value) { + initialBotOptions.discussionTriggerReactionEnabled = value ?? false; + initialBotOptions.discussionTriggerReactionKey = + "⏩"; // hard code this for now + onChanged.call(initialBotOptions); + }, + ), + // if (initialBotOptions.discussionTriggerReactionEnabled == true) + // Padding( + // padding: const EdgeInsets.all(8), + // child: Column( + // children: [ + // Text( + // L10n.of(context)! + // .conversationBotDiscussionZone_discussionTriggerReactionKeyLabel, + // style: TextStyle( + // color: Theme.of(context).colorScheme.secondary, + // fontWeight: FontWeight.bold, + // ), + // textAlign: TextAlign.left, + // ), + // 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( + // reactionKeyOptions[0], + // 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: [ + // for (final entry in reactionKeyOptions) + // DropdownMenuItem( + // value: entry, + // child: Padding( + // padding: const EdgeInsets.only(left: 15), + // child: Text( + // entry, + // style: const TextStyle().copyWith( + // color: Theme.of(context) + // .textTheme + // .bodyLarge! + // .color, + // fontSize: 14, + // ), + // overflow: TextOverflow.clip, + // textAlign: TextAlign.center, + // ), + // ), + // ), + // ], + // onChanged: (String? value) { + // if (value != + // initialBotOptions.discussionTriggerReactionKey) { + // initialBotOptions.discussionTriggerReactionKey = value; + // onChanged?.call( + // initialBotOptions, + // ); + // } + // }, + // ), + // ), + // ], + // ), + // ), + 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 new file mode 100644 index 000000000..b0c78888f --- /dev/null +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart @@ -0,0 +1,41 @@ +import 'package:fluffychat/pangea/models/bot_options_model.dart'; +import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_conversation_zone.dart'; +import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart'; +import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_text_adventure_zone.dart'; +import 'package:flutter/material.dart'; + +import 'conversation_bot_discussion_zone.dart'; + +class ConversationBotModeDynamicZone extends StatelessWidget { + final BotOptionsModel initialBotOptions; + final void Function(BotOptionsModel) onChanged; + + const ConversationBotModeDynamicZone({ + super.key, + required this.initialBotOptions, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + final zoneMap = { + 'discussion': ConversationBotDiscussionZone( + initialBotOptions: initialBotOptions, + onChanged: onChanged, + ), + "custom": const ConversationBotCustomZone(), + "conversation": const ConversationBotConversationZone(), + "text_adventure": const ConversationBotTextAdventureZone(), + }; + return Container( + decoration: BoxDecoration( + border: Border.all( + color: Theme.of(context).colorScheme.secondary, + width: 0.5, + ), + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: zoneMap[initialBotOptions.mode], + ); + } +} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart new file mode 100644 index 000000000..9662dec55 --- /dev/null +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class ConversationBotModeSelect extends StatelessWidget { + final String? initialMode; + final void Function(String?)? onChanged; + + const ConversationBotModeSelect({ + super.key, + this.initialMode, + this.onChanged, + }); + + @override + Widget build(BuildContext context) { + final Map options = { + "discussion": + L10n.of(context)!.conversationBotModeSelectOption_discussion, + // "custom": L10n.of(context)!.conversationBotModeSelectOption_custom, + // "conversation": + // L10n.of(context)!.conversationBotModeSelectOption_conversation, + // "text_adventure": + // L10n.of(context)!.conversationBotModeSelectOption_textAdventure, + }; + + 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( + options[initialMode ?? "discussion"]!, + 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: [ + 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, + ), + ), + ); + } +} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart index 0227c243a..d10fd6980 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart @@ -1,10 +1,10 @@ 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/conversation_bot/conversation_bot_mode_dynamic_zone.dart'; import 'package:fluffychat/pangea/widgets/space/language_level_dropdown.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -156,49 +156,49 @@ class ConversationBotSettingsState extends State { ), ), 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: 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( @@ -244,6 +244,41 @@ class ConversationBotSettingsState extends State { }), ), ), + // Padding( + // padding: const EdgeInsets.fromLTRB(32, 16, 0, 0), + // child: Text( + // L10n.of(context)!.conversationBotModeSelectDescription, + // style: TextStyle( + // color: Theme.of(context).colorScheme.secondary, + // fontWeight: FontWeight.bold, + // fontSize: 16, + // ), + // ), + // ), + // Padding( + // padding: const EdgeInsets.only(left: 16), + // child: ConversationBotModeSelect( + // initialMode: botOptions.mode, + // onChanged: (String? mode) => updateBotOption( + // () { + // botOptions.mode = mode ?? "discussion"; + // }, + // ), + // ), + // ), + Padding( + padding: const EdgeInsets.fromLTRB(28, 0, 12, 0), + child: ConversationBotModeDynamicZone( + initialBotOptions: botOptions, + onChanged: (BotOptionsModel? newOptions) { + updateBotOption(() { + if (newOptions != null) { + botOptions = newOptions; + } + }); + }, + ), + ), const SizedBox(height: 16), ], ], 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 new file mode 100644 index 000000000..2f65348cf --- /dev/null +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_text_adventure_zone.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +class ConversationBotTextAdventureZone extends StatelessWidget { + const ConversationBotTextAdventureZone({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return const Column( + children: [ + Text('Text Adventure Zone'), + ], + ); + } +} diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index 779955f82..43416e006 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -48,28 +48,33 @@ class PangeaRichTextState extends State { @override void initState() { super.initState(); - updateTextSpan(); - } - - void updateTextSpan() { - setState(() { - textSpan = getTextSpan(); - }); + setTextSpan(); } @override void didUpdateWidget(PangeaRichText oldWidget) { super.didUpdateWidget(oldWidget); - updateTextSpan(); + setTextSpan(); } - String getTextSpan() { + void _setTextSpan(String newTextSpan) { + widget.toolbarController?.toolbar?.textSelection.setMessageText( + newTextSpan, + ); + setState(() { + textSpan = newTextSpan; + }); + } + + void setTextSpan() { if (_fetchingRepresentation == true) { - return widget.pangeaMessageEvent.body; + _setTextSpan(textSpan = widget.pangeaMessageEvent.body); + return; } if (repEvent != null) { - return repEvent!.text; + _setTextSpan(repEvent!.text); + return; } if (widget.pangeaMessageEvent.eventId.contains("webdebug")) { @@ -84,7 +89,6 @@ class PangeaRichTextState extends State { if (repEvent == null) { setState(() => _fetchingRepresentation = true); - widget.pangeaMessageEvent .representationByLanguageGlobal( langCode: widget.pangeaMessageEvent.messageDisplayLangCode, @@ -95,23 +99,17 @@ class PangeaRichTextState extends State { ) .then((event) { repEvent = event; - widget.toolbarController?.toolbar?.textSelection.setMessageText( - repEvent?.text ?? widget.pangeaMessageEvent.body, - ); + _setTextSpan(repEvent?.text ?? widget.pangeaMessageEvent.body); }).whenComplete(() { if (mounted) { setState(() => _fetchingRepresentation = false); } }); - return widget.pangeaMessageEvent.body; - } else { - widget.toolbarController?.toolbar?.textSelection.setMessageText( - repEvent!.text, - ); - setState(() {}); - } - return repEvent!.text; + _setTextSpan(widget.pangeaMessageEvent.body); + } else { + _setTextSpan(repEvent!.text); + } } @override @@ -190,7 +188,10 @@ class PangeaRichTextState extends State { return blur > 0 ? ImageFiltered( - imageFilter: ImageFilter.blur(sigmaX: blur, sigmaY: blur), + imageFilter: ImageFilter.blur( + sigmaX: blur, + sigmaY: blur, + ), child: richText, ) : richText; diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index 7185d726c..9ef2f4122 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -58,10 +58,14 @@ class SpanCardState extends State { } //get selected choice - SpanChoice? get selectedChoice => selectedChoiceIndex != null && - widget.scm.pangeaMatch?.match.choices != null - ? widget.scm.pangeaMatch!.match.choices![selectedChoiceIndex!] - : null; + SpanChoice? get selectedChoice { + if (selectedChoiceIndex == null || + widget.scm.pangeaMatch?.match.choices == null || + widget.scm.pangeaMatch!.match.choices!.length >= selectedChoiceIndex!) { + return null; + } + return widget.scm.pangeaMatch?.match.choices?[selectedChoiceIndex!]; + } Future getSpanDetails() async { try { diff --git a/lib/pangea/widgets/igc/word_data_card.dart b/lib/pangea/widgets/igc/word_data_card.dart index a6ef7b511..4b8445417 100644 --- a/lib/pangea/widgets/igc/word_data_card.dart +++ b/lib/pangea/widgets/igc/word_data_card.dart @@ -314,6 +314,23 @@ class PartOfSpeechBlock extends StatelessWidget { required this.languageType, }); + String get exampleSentence => languageType == LanguageType.target + ? wordData.targetExampleSentence + : wordData.baseExampleSentence; + + String get definition => languageType == LanguageType.target + ? wordData.targetDefinition + : wordData.baseDefinition; + + String formattedTitle(BuildContext context) { + final String word = languageType == LanguageType.target + ? wordData.targetWord + : wordData.baseWord; + String? pos = wordData.formattedPartOfSpeech(languageType); + if (pos == null || pos.isEmpty) pos = L10n.of(context)!.unkDisplayName; + return "$word (${wordData.formattedPartOfSpeech(languageType)})"; + } + @override Widget build(BuildContext context) { return Padding( @@ -324,9 +341,7 @@ class PartOfSpeechBlock extends StatelessWidget { Align( alignment: Alignment.centerLeft, child: Text( - languageType == LanguageType.target - ? "${wordData.targetWord} (${wordData.formattedPartOfSpeech(languageType)})" - : "${wordData.baseWord} (${wordData.formattedPartOfSpeech(languageType)})", + formattedTitle(context), style: BotStyle.text(context, italics: true, bold: false), ), ), @@ -337,47 +352,43 @@ class PartOfSpeechBlock extends StatelessWidget { alignment: Alignment.centerLeft, child: Column( children: [ - RichText( - text: TextSpan( - style: BotStyle.text( - context, - italics: false, - bold: false, + if (definition.isNotEmpty) + RichText( + text: TextSpan( + style: BotStyle.text( + context, + italics: false, + bold: false, + ), + children: [ + TextSpan( + text: "${L10n.of(context)!.definition}: ", + style: const TextStyle(fontWeight: FontWeight.bold), + ), + TextSpan(text: definition), + ], ), - children: [ - TextSpan( - text: "${L10n.of(context)!.definition}: ", - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan( - text: languageType == LanguageType.target - ? wordData.targetDefinition - : wordData.baseDefinition, - ), - ], ), - ), const SizedBox(height: 10), - RichText( - text: TextSpan( - style: BotStyle.text( - context, - italics: false, - bold: false, + if (exampleSentence.isNotEmpty) + RichText( + text: TextSpan( + style: BotStyle.text( + context, + italics: false, + bold: false, + ), + children: [ + TextSpan( + text: "${L10n.of(context)!.exampleSentence}: ", + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + TextSpan(text: exampleSentence), + ], ), - children: [ - TextSpan( - text: "${L10n.of(context)!.exampleSentence}: ", - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan( - text: languageType == LanguageType.target - ? wordData.targetExampleSentence - : wordData.baseExampleSentence, - ), - ], ), - ), ], ), ), diff --git a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart index 301d0c6ee..e1a8b99d5 100644 --- a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart +++ b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart @@ -1,20 +1,16 @@ import 'dart:io'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart'; +import 'package:fluffychat/utils/platform_infos.dart'; import 'package:flutter/foundation.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:universal_html/html.dart' as html; -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/utils/client_manager.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart'; -import 'package:fluffychat/utils/platform_infos.dart'; import 'cipher.dart'; - import 'sqlcipher_stub.dart' if (dart.library.io) 'package:sqlcipher_flutter_libs/sqlcipher_flutter_libs.dart'; @@ -24,25 +20,49 @@ Future flutterMatrixSdkDatabaseBuilder(Client client) async { database = await _constructDatabase(client); await database.open(); return database; - } catch (e) { + // #Pangea + // } catch (e) { + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + m: "Failed to open matrix sdk database. Openning fallback database.", + ); + // Pangea# // Try to delete database so that it can created again on next init: database?.delete().catchError( - (e, s) => Logs().w( - 'Unable to delete database, after failed construction', - e, - s, - ), + // #Pangea + // (e, s) => Logs().w( + // 'Unable to delete database, after failed construction', + // e, + // s, + // ), + (e, s) { + Logs().w( + 'Unable to delete database, after failed construction', + e, + s, + ); + ErrorHandler.logError( + e: e, + s: s, + m: "Failed to delete matrix database after failed construction.", + ); + } + // Pangea# ); // Send error notification: - final l10n = lookupL10n(PlatformDispatcher.instance.locale); - ClientManager.sendInitNotification( - l10n.initAppError, - l10n.databaseBuildErrorBody( - AppConfig.newIssueUrl.toString(), - e.toString(), - ), - ); + // #Pangea + // final l10n = lookupL10n(PlatformDispatcher.instance.locale); + // ClientManager.sendInitNotification( + // l10n.initAppError, + // l10n.databaseBuildErrorBody( + // AppConfig.newIssueUrl.toString(), + // e.toString(), + // ), + // ); + // Pangea# return FlutterHiveCollectionsDatabase.databaseBuilder(client); } diff --git a/needed-translations.txt b/needed-translations.txt index 7cbcc8a05..bb967d011 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -821,6 +821,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -2242,6 +2259,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -3125,6 +3159,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -4008,6 +4059,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -4891,6 +4959,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -5774,6 +5859,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -6604,6 +6706,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -7487,6 +7606,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -8370,6 +8506,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -9196,6 +9349,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -10022,6 +10192,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -10905,6 +11092,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -11788,6 +11992,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -12671,6 +12892,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -13554,6 +13792,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -14380,6 +14635,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -15263,6 +15535,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -16146,6 +16435,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -17016,6 +17322,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -17899,6 +18222,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -19306,6 +19646,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -20189,6 +20546,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -21072,6 +21446,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -21940,6 +22331,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -22823,6 +23231,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -23706,6 +24131,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -24589,6 +25031,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -25472,6 +25931,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -26355,6 +26831,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -27238,6 +27731,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -28121,6 +28631,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -29004,6 +29531,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -29856,6 +30400,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -30739,6 +31300,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -31622,6 +32200,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -32448,6 +33043,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -33331,6 +33943,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -34214,6 +34843,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -35097,6 +35743,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -35945,6 +36608,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -36828,6 +37508,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -37711,6 +38408,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -38579,6 +39293,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -39405,6 +40136,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -40288,6 +41036,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -41114,6 +41879,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ], @@ -41997,6 +42779,23 @@ "accuracy", "points", "noPaymentInfo", + "conversationBotModeSelectDescription", + "conversationBotModeSelectOption_discussion", + "conversationBotModeSelectOption_custom", + "conversationBotModeSelectOption_conversation", + "conversationBotModeSelectOption_textAdventure", + "conversationBotDiscussionZone_title", + "conversationBotDiscussionZone_discussionTopicLabel", + "conversationBotDiscussionZone_discussionTopicPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsLabel", + "conversationBotDiscussionZone_discussionKeywordsPlaceholder", + "conversationBotDiscussionZone_discussionKeywordsHintText", + "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", + "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", + "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "studentAnalyticsNotAvailable", + "roomDataMissing", "updatePhoneOS", "wordsPerMinute" ]